summaryrefslogtreecommitdiff
path: root/chromium/components/autofill
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-24 11:30:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-30 12:56:19 +0000
commit6036726eb981b6c4b42047513b9d3f4ac865daac (patch)
tree673593e70678e7789766d1f732eb51f613a2703b /chromium/components/autofill
parent466052c4e7c052268fd931888cd58961da94c586 (diff)
downloadqtwebengine-chromium-6036726eb981b6c4b42047513b9d3f4ac865daac.tar.gz
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/autofill')
-rw-r--r--chromium/components/autofill/android/BUILD.gn2
-rw-r--r--chromium/components/autofill/android/autofill_provider_android.cc8
-rw-r--r--chromium/components/autofill/android/form_data_android.cc21
-rw-r--r--chromium/components/autofill/android/form_data_android.h6
-rw-r--r--chromium/components/autofill/android/form_field_data_android.cc13
-rw-r--r--chromium/components/autofill/android/form_field_data_android.h7
-rw-r--r--chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml64
-rw-r--r--chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml55
-rw-r--r--chromium/components/autofill/android/java/res/values/dimens.xml11
-rw-r--r--chromium/components/autofill/content/browser/BUILD.gn3
-rw-r--r--chromium/components/autofill/content/browser/DEPS1
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc10
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h10
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.cc2
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.h5
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc23
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.cc17
-rw-r--r--chromium/components/autofill/content/common/autofill_agent.mojom3
-rw-r--r--chromium/components/autofill/content/common/autofill_driver.mojom5
-rw-r--r--chromium/components/autofill/content/common/autofill_types.mojom5
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.cc8
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits.h21
-rw-r--r--chromium/components/autofill/content/common/autofill_types_struct_traits_unittest.cc7
-rw-r--r--chromium/components/autofill/content/renderer/BUILD.gn11
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc97
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.h27
-rw-r--r--chromium/components/autofill/content/renderer/field_data_manager.cc84
-rw-r--r--chromium/components/autofill/content/renderer/field_data_manager.h56
-rw-r--r--chromium/components/autofill/content/renderer/field_data_manager_browsertest.cc113
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.cc83
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.h23
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc49
-rw-r--r--chromium/components/autofill/content/renderer/form_classifier.cc265
-rw-r--r--chromium/components/autofill/content/renderer/form_classifier.h19
-rw-r--r--chromium/components/autofill/content/renderer/form_tracker.h2
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector.cc20
-rw-r--r--chromium/components/autofill/content/renderer/page_passwords_analyser.cc5
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc445
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.h67
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc15
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.h17
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc150
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc113
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.h16
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc4
-rw-r--r--chromium/components/autofill/content/renderer/test_password_autofill_agent.cc2
-rw-r--r--chromium/components/autofill/content/renderer/test_password_autofill_agent.h2
-rw-r--r--chromium/components/autofill/content/renderer/test_password_generation_agent.cc2
-rw-r--r--chromium/components/autofill/content/renderer/test_password_generation_agent.h4
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn67
-rw-r--r--chromium/components/autofill/core/browser/DEPS7
-rw-r--r--chromium/components/autofill/core/browser/account_info_getter.h33
-rw-r--r--chromium/components/autofill/core/browser/address_combobox_model.h2
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl.cc4
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_policy_handler.cc6
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_policy_handler_unittest.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.cc15
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.h7
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant_unittest.cc102
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h20
-rw-r--r--chromium/components/autofill/core/browser/autofill_credit_card_policy_handler.cc6
-rw-r--r--chromium/components/autofill/core/browser/autofill_credit_card_policy_handler_unittest.cc32
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc16
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.h7
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.cc136
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.h6
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc217
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc265
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.h142
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments_unittest.cc33
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc37
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.cc7
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.h12
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.cc162
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.h49
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler_proxy.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc226
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h43
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc119
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc43
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h48
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc22
-rw-r--r--chromium/components/autofill/core/browser/autofill_policy_handler.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_policy_handler_unittest.cc88
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.cc8
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_sync_util.cc9
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_unittest.cc32
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc24
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h1
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc77
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.h26
-rw-r--r--chromium/components/autofill/core/browser/autofill_type.cc3
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.cc9
-rw-r--r--chromium/components/autofill/core/browser/autofill_wallet_data_type_controller_unittest.cc12
-rw-r--r--chromium/components/autofill/core/browser/contact_info.cc4
-rw-r--r--chromium/components/autofill/core/browser/contact_info_unittest.cc28
-rw-r--r--chromium/components/autofill/core/browser/credit_card.cc13
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager.cc122
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager.h19
-rw-r--r--chromium/components/autofill/core/browser/credit_card_save_manager_unittest.cc580
-rw-r--r--chromium/components/autofill/core/browser/field_filler.cc4
-rw-r--r--chromium/components/autofill/core/browser/field_filler_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.cc4
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.h5
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer_unittest.cc211
-rw-r--r--chromium/components/autofill/core/browser/form_field.cc3
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc123
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h54
-rw-r--r--chromium/components/autofill/core/browser/form_structure_process_query_response_fuzzer.cc50
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc262
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_manager.cc233
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_manager.h134
-rw-r--r--chromium/components/autofill/core/browser/local_card_migration_manager_unittest.cc295
-rw-r--r--chromium/components/autofill/core/browser/password_generator_proto_fuzzer.cc15
-rw-r--r--chromium/components/autofill/core/browser/password_requirements_spec_printer.cc8
-rw-r--r--chromium/components/autofill/core/browser/password_requirements_spec_printer.h8
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.cc11
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc19
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc326
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.h117
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client_unittest.cc475
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_customer_data.h30
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_util.cc49
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_util.h27
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_util_unittest.cc103
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.cc46
-rw-r--r--chromium/components/autofill/core/browser/payments/test_payments_client.h44
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc251
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h88
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc448
-rw-r--r--chromium/components/autofill/core/browser/proto/BUILD.gn4
-rw-r--r--chromium/components/autofill/core/browser/proto/server.proto53
-rw-r--r--chromium/components/autofill/core/browser/region_combobox_model.h2
-rw-r--r--chromium/components/autofill/core/browser/region_data_loader_impl.cc8
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc16
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h9
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_manager.cc7
-rw-r--r--chromium/components/autofill/core/browser/test_credit_card_save_manager.cc7
-rw-r--r--chromium/components/autofill/core/browser/test_credit_card_save_manager.h1
-rw-r--r--chromium/components/autofill/core/browser/test_event_waiter.h22
-rw-r--r--chromium/components/autofill/core/browser/test_local_card_migration_manager.cc36
-rw-r--r--chromium/components/autofill/core/browser/test_local_card_migration_manager.h22
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.cc8
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.h17
-rw-r--r--chromium/components/autofill/core/browser/test_sync_service.cc12
-rw-r--r--chromium/components/autofill/core/browser/test_sync_service.h18
-rw-r--r--chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc2
-rw-r--r--chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/ui/local_card_migration_bubble_controller.h4
-rw-r--r--chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h44
-rw-r--r--chromium/components/autofill/core/browser/ui/save_card_bubble_controller.h27
-rw-r--r--chromium/components/autofill/core/browser/webdata/OWNERS2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc7
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.cc8
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc10
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc61
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h33
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc422
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h101
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc204
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc67
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h15
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc34
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc327
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h114
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc500
-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_sync_bridge.cc452
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h140
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc738
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc65
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc50
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata.h7
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h5
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h6
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc36
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h49
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_service_unittest.cc8
-rw-r--r--chromium/components/autofill/core/common/BUILD.gn17
-rw-r--r--chromium/components/autofill/core/common/autofill_features.cc262
-rw-r--r--chromium/components/autofill/core/common/autofill_features.h124
-rw-r--r--chromium/components/autofill/core/common/autofill_pref_names.cc62
-rw-r--r--chromium/components/autofill/core/common/autofill_pref_names.h39
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.cc195
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs.h83
-rw-r--r--chromium/components/autofill/core/common/autofill_prefs_unittest.cc77
-rw-r--r--chromium/components/autofill/core/common/autofill_regex_constants.cc35
-rw-r--r--chromium/components/autofill/core/common/autofill_util.h4
-rw-r--r--chromium/components/autofill/core/common/form_data.cc6
-rw-r--r--chromium/components/autofill/core/common/form_field_data.cc8
-rw-r--r--chromium/components/autofill/core/common/form_field_data.h1
-rw-r--r--chromium/components/autofill/core/common/password_form.cc6
-rw-r--r--chromium/components/autofill/core/common/password_form.h8
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.cc15
-rw-r--r--chromium/components/autofill/core/common/password_form_fill_data.h18
-rw-r--r--chromium/components/autofill/core/common/password_generation_util.cc4
-rw-r--r--chromium/components/autofill/core/common/password_generation_util.h21
-rw-r--r--chromium/components/autofill/ios/browser/BUILD.gn16
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.mm11
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent_unittests.mm4
-rw-r--r--chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h53
-rw-r--r--chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm42
-rw-r--r--chromium/components/autofill/ios/browser/ios_test_event_waiter.h85
-rw-r--r--chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.h12
-rw-r--r--chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.mm2
-rw-r--r--chromium/components/autofill/ios/form_util/BUILD.gn1
-rw-r--r--chromium/components/autofill/ios/form_util/DEPS6
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.h2
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm11
-rw-r--r--chromium/components/autofill/ios/form_util/form_unittest.mm4
-rw-r--r--chromium/components/autofill/ios/form_util/resources/form.js44
219 files changed, 10046 insertions, 3551 deletions
diff --git a/chromium/components/autofill/android/BUILD.gn b/chromium/components/autofill/android/BUILD.gn
index fea72723c6e..cd72694f8a0 100644
--- a/chromium/components/autofill/android/BUILD.gn
+++ b/chromium/components/autofill/android/BUILD.gn
@@ -59,6 +59,7 @@ android_resources("autofill_java_resources") {
resource_dirs = [ "java/res" ]
deps = [
":autofill_strings_grd",
+ "//ui/android:ui_java_resources",
]
}
@@ -78,6 +79,7 @@ android_library("autofill_java") {
]
java_files = [
"java/src/org/chromium/components/autofill/AutofillDelegate.java",
+ "java/src/org/chromium/components/autofill/AutofillDropdownAdapter.java",
"java/src/org/chromium/components/autofill/AutofillPopup.java",
"java/src/org/chromium/components/autofill/AutofillSuggestion.java",
]
diff --git a/chromium/components/autofill/android/autofill_provider_android.cc b/chromium/components/autofill/android/autofill_provider_android.cc
index 644270cb779..a930d663e0e 100644
--- a/chromium/components/autofill/android/autofill_provider_android.cc
+++ b/chromium/components/autofill/android/autofill_provider_android.cc
@@ -92,9 +92,15 @@ void AutofillProviderAndroid::StartNewSession(AutofillHandlerProxy* handler,
return;
}
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!handler->GetCachedFormAndField(form, field, &form_structure,
+ &autofill_field)) {
+ form_structure = nullptr;
+ }
gfx::RectF transformed_bounding = ToClientAreaBound(bounding_box);
- ScopedJavaLocalRef<jobject> form_obj = form_->GetJavaPeer();
+ ScopedJavaLocalRef<jobject> form_obj = form_->GetJavaPeer(form_structure);
handler_ = handler->GetWeakPtr();
Java_AutofillProvider_startAutofillSession(
env, obj, form_obj, index, transformed_bounding.x(),
diff --git a/chromium/components/autofill/android/form_data_android.cc b/chromium/components/autofill/android/form_data_android.cc
index 3addcce6ffb..f1af3d53a5b 100644
--- a/chromium/components/autofill/android/form_data_android.cc
+++ b/chromium/components/autofill/android/form_data_android.cc
@@ -6,6 +6,7 @@
#include "base/android/jni_string.h"
#include "components/autofill/android/form_field_data_android.h"
+#include "components/autofill/core/browser/form_structure.h"
#include "jni/FormData_jni.h"
using base::android::AttachCurrentThread;
@@ -30,7 +31,10 @@ FormDataAndroid::~FormDataAndroid() {
Java_FormData_onNativeDestroyed(env, obj);
}
-ScopedJavaLocalRef<jobject> FormDataAndroid::GetJavaPeer() {
+ScopedJavaLocalRef<jobject> FormDataAndroid::GetJavaPeer(
+ const FormStructure* form_structure) {
+ // |form_structure| is ephemeral and shouldn't be used outside this call
+ // stack.
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null()) {
@@ -38,6 +42,8 @@ ScopedJavaLocalRef<jobject> FormDataAndroid::GetJavaPeer() {
fields_.push_back(std::unique_ptr<FormFieldDataAndroid>(
new FormFieldDataAndroid(&form_.fields[i])));
}
+ if (form_structure)
+ ApplyHeuristicFieldType(*form_structure);
ScopedJavaLocalRef<jstring> jname =
ConvertUTF16ToJavaString(env, form_.name);
ScopedJavaLocalRef<jstring> jhost =
@@ -95,4 +101,17 @@ bool FormDataAndroid::SimilarFormAs(const FormData& form) {
return form_.SimilarFormAs(form);
}
+void FormDataAndroid::ApplyHeuristicFieldType(
+ const FormStructure& form_structure) {
+ DCHECK(form_structure.field_count() == fields_.size());
+ auto form_field_data_android = fields_.begin();
+ for (const auto& autofill_field : form_structure) {
+ DCHECK(form_field_data_android->get()->SimilarFieldAs(*autofill_field));
+ form_field_data_android->get()->set_heuristic_type(
+ AutofillType(autofill_field->heuristic_type()));
+ if (++form_field_data_android == fields_.end())
+ break;
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/android/form_data_android.h b/chromium/components/autofill/android/form_data_android.h
index 81059fcba48..b54928f76d4 100644
--- a/chromium/components/autofill/android/form_data_android.h
+++ b/chromium/components/autofill/android/form_data_android.h
@@ -12,6 +12,7 @@
namespace autofill {
class FormFieldDataAndroid;
+class FormStructure;
// This class is native peer of FormData.java, to make autofill::FormData
// available in Java.
@@ -20,7 +21,8 @@ class FormDataAndroid {
FormDataAndroid(const FormData& form);
virtual ~FormDataAndroid();
- base::android::ScopedJavaLocalRef<jobject> GetJavaPeer();
+ base::android::ScopedJavaLocalRef<jobject> GetJavaPeer(
+ const FormStructure* form_structure);
// Get autofill values from Java side and return FormData.
const FormData& GetAutofillValues();
@@ -46,6 +48,8 @@ class FormDataAndroid {
// |value|.
void OnFormFieldDidChange(size_t index, const base::string16& value);
+ void ApplyHeuristicFieldType(const FormStructure& form);
+
const FormData& form_for_testing() { return form_; }
private:
diff --git a/chromium/components/autofill/android/form_field_data_android.cc b/chromium/components/autofill/android/form_field_data_android.cc
index e44e88ece75..e4f841873be 100644
--- a/chromium/components/autofill/android/form_field_data_android.cc
+++ b/chromium/components/autofill/android/form_field_data_android.cc
@@ -22,7 +22,7 @@ using base::android::ToJavaArrayOfStrings;
namespace autofill {
FormFieldDataAndroid::FormFieldDataAndroid(FormFieldData* field)
- : field_ptr_(field) {}
+ : heuristic_type_(AutofillType(UNKNOWN_TYPE)), field_ptr_(field) {}
ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
JNIEnv* env = AttachCurrentThread();
@@ -46,12 +46,17 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() {
ToJavaArrayOfStrings(env, field_ptr_->option_values);
ScopedJavaLocalRef<jobjectArray> joption_contents =
ToJavaArrayOfStrings(env, field_ptr_->option_contents);
+ ScopedJavaLocalRef<jstring> jheuristic_type;
+ if (!heuristic_type_.IsUnknown())
+ jheuristic_type =
+ ConvertUTF8ToJavaString(env, heuristic_type_.ToString());
obj = Java_FormFieldData_createFormFieldData(
env, jname, jlabel, jvalue, jautocomplete_attr,
field_ptr_->should_autocomplete, jplaceholder, jtype, jid,
joption_values, joption_contents, IsCheckable(field_ptr_->check_status),
- IsChecked(field_ptr_->check_status), field_ptr_->max_length);
+ IsChecked(field_ptr_->check_status), field_ptr_->max_length,
+ jheuristic_type);
java_ref_ = JavaObjectWeakGlobalRef(env, obj);
}
return obj;
@@ -88,4 +93,8 @@ void FormFieldDataAndroid::OnFormFieldDidChange(const base::string16& value) {
ConvertUTF16ToJavaString(env, value));
}
+bool FormFieldDataAndroid::SimilarFieldAs(const FormFieldData& field) const {
+ return field_ptr_->SimilarFieldAs(field);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/android/form_field_data_android.h b/chromium/components/autofill/android/form_field_data_android.h
index 2cb598ec4c5..e882bb49704 100644
--- a/chromium/components/autofill/android/form_field_data_android.h
+++ b/chromium/components/autofill/android/form_field_data_android.h
@@ -7,6 +7,7 @@
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
+#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/common/form_field_data.h"
namespace autofill {
@@ -21,8 +22,14 @@ class FormFieldDataAndroid {
base::android::ScopedJavaLocalRef<jobject> GetJavaPeer();
void GetValue();
void OnFormFieldDidChange(const base::string16& value);
+ bool SimilarFieldAs(const FormFieldData& field) const;
+
+ void set_heuristic_type(const AutofillType& heuristic_type) {
+ heuristic_type_ = heuristic_type;
+ }
private:
+ AutofillType heuristic_type_;
// Not owned.
FormFieldData* field_ptr_;
JavaObjectWeakGlobalRef java_ref_;
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
new file mode 100644
index 00000000000..93512e2012a
--- /dev/null
+++ b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="horizontal" >
+
+ <!-- These layout params are overwritten in DropdownAdapter.java -->
+ <ImageView
+ android:id="@+id/start_dropdown_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="@dimen/autofill_dropdown_icon_margin"
+ tools:ignore="ContentDescription" />
+
+ <LinearLayout
+ android:id="@+id/dropdown_label_wrapper"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:gravity="center_vertical"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/dropdown_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/autofill_dropdown_item_label_margin"
+ android:layout_marginStart="@dimen/autofill_dropdown_item_label_margin"
+ android:ellipsize="end"
+ android:includeFontPadding="false"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ android:textAppearance="@style/BlackTitle1" />
+
+ <TextView
+ android:id="@+id/dropdown_sublabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/autofill_dropdown_item_label_margin"
+ android:layout_marginStart="@dimen/autofill_dropdown_item_label_margin"
+ android:ellipsize="end"
+ android:includeFontPadding="false"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ android:textAppearance="@style/BlackCaption" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/end_dropdown_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"
+ tools:ignore="ContentDescription" />
+
+</LinearLayout> \ No newline at end of file
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
new file mode 100644
index 00000000000..4287074b5f8
--- /dev/null
+++ b/chromium/components/autofill/android/java/res/layout/autofill_dropdown_item_refresh.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="@dimen/autofill_dropdown_refresh_horizontal_padding"
+ android:paddingStart="@dimen/autofill_dropdown_refresh_horizontal_padding"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ tools:ignore="UnusedResources" >
+
+ <LinearLayout
+ android:id="@+id/dropdown_label_wrapper"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/autofill_dropdown_refresh_item_height"
+ android:layout_weight="1"
+ android:gravity="center_vertical"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/dropdown_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:includeFontPadding="false"
+ android:singleLine="true"
+ android:textAppearance="@style/BlackBodyDefault" />
+
+ <TextView
+ android:id="@+id/dropdown_sublabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:includeFontPadding="false"
+ android:singleLine="true"
+ android:textAlignment="viewStart"
+ android:textAppearance="@style/BlackCaption" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/end_dropdown_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/autofill_dropdown_refresh_icon_margin"
+ android:layout_marginEnd="0dp"
+ tools:ignore="ContentDescription" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/chromium/components/autofill/android/java/res/values/dimens.xml b/chromium/components/autofill/android/java/res/values/dimens.xml
index 1327d16ea44..ed876f854d2 100644
--- a/chromium/components/autofill/android/java/res/values/dimens.xml
+++ b/chromium/components/autofill/android/java/res/values/dimens.xml
@@ -5,4 +5,15 @@
found in the LICENSE file.
-->
<resources>
+ <!-- Dimens for legacy UI
+ TODO(crbug.com/874077): Remove once refresh UI is fully rolled out. -->
+ <dimen name="autofill_dropdown_item_height">50dp</dimen>
+ <dimen name="autofill_dropdown_item_divider_height">1dp</dimen>
+ <dimen name="autofill_dropdown_item_label_margin">10dp</dimen>
+ <dimen name="autofill_dropdown_icon_margin">8dp</dimen>
+
+ <!-- Dimens for refresh UI -->
+ <dimen name="autofill_dropdown_refresh_item_height">48dp</dimen>
+ <dimen name="autofill_dropdown_refresh_horizontal_padding">16dp</dimen>
+ <dimen name="autofill_dropdown_refresh_icon_margin">24dp</dimen>
</resources>
diff --git a/chromium/components/autofill/content/browser/BUILD.gn b/chromium/components/autofill/content/browser/BUILD.gn
index 877af89df15..0d8a0b42348 100644
--- a/chromium/components/autofill/content/browser/BUILD.gn
+++ b/chromium/components/autofill/content/browser/BUILD.gn
@@ -2,9 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/jumbo.gni")
import("//third_party/protobuf/proto_library.gni")
-static_library("browser") {
+jumbo_static_library("browser") {
sources = [
"content_autofill_driver.cc",
"content_autofill_driver.h",
diff --git a/chromium/components/autofill/content/browser/DEPS b/chromium/components/autofill/content/browser/DEPS
index c9b21e464f1..847530b9afd 100644
--- a/chromium/components/autofill/content/browser/DEPS
+++ b/chromium/components/autofill/content/browser/DEPS
@@ -4,6 +4,7 @@ include_rules = [
"+gpu/config/gpu_info.h",
"+services/device/public",
"+services/service_manager/public/mojom",
+ "+third_party/blink/public/common",
"+third_party/blink/public/platform/web_rect.h",
]
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index fb8391c870f..944b69b2ea2 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -24,7 +24,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/origin_util.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "ui/gfx/geometry/size_f.h"
namespace autofill {
@@ -64,7 +64,8 @@ ContentAutofillDriver* ContentAutofillDriver::GetForRenderFrameHost(
return factory ? factory->DriverForFrame(render_frame_host) : nullptr;
}
-void ContentAutofillDriver::BindRequest(mojom::AutofillDriverRequest request) {
+void ContentAutofillDriver::BindRequest(
+ mojom::AutofillDriverAssociatedRequest request) {
binding_.Bind(std::move(request));
}
@@ -285,10 +286,11 @@ void ContentAutofillDriver::SetAutofillManager(
autofill_manager_->SetExternalDelegate(autofill_external_delegate_.get());
}
-const mojom::AutofillAgentPtr& ContentAutofillDriver::GetAutofillAgent() {
+const mojom::AutofillAgentAssociatedPtr&
+ContentAutofillDriver::GetAutofillAgent() {
// Here is a lazy binding, and will not reconnect after connection error.
if (!autofill_agent_) {
- render_frame_host_->GetRemoteInterfaces()->GetInterface(
+ render_frame_host_->GetRemoteAssociatedInterfaces()->GetInterface(
mojo::MakeRequest(&autofill_agent_));
}
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index 83c9d743c57..248daefe0ea 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -15,7 +15,7 @@
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_manager.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
namespace content {
class NavigationHandle;
@@ -46,7 +46,7 @@ class ContentAutofillDriver : public AutofillDriver,
static ContentAutofillDriver* GetForRenderFrameHost(
content::RenderFrameHost* render_frame_host);
- void BindRequest(mojom::AutofillDriverRequest request);
+ void BindRequest(mojom::AutofillDriverAssociatedRequest request);
// AutofillDriver:
bool IsIncognito() const override;
@@ -118,7 +118,7 @@ class ContentAutofillDriver : public AutofillDriver,
AutofillManager* autofill_manager() { return autofill_manager_; }
content::RenderFrameHost* render_frame_host() { return render_frame_host_; }
- const mojom::AutofillAgentPtr& GetAutofillAgent();
+ const mojom::AutofillAgentAssociatedPtr& GetAutofillAgent();
// Methods forwarded to key_press_handler_manager_.
void RegisterKeyPressHandler(
@@ -160,9 +160,9 @@ class ContentAutofillDriver : public AutofillDriver,
KeyPressHandlerManager key_press_handler_manager_;
- mojo::Binding<mojom::AutofillDriver> binding_;
+ mojo::AssociatedBinding<mojom::AutofillDriver> binding_;
- mojom::AutofillAgentPtr autofill_agent_;
+ mojom::AutofillAgentAssociatedPtr autofill_agent_;
};
} // namespace autofill
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 f67d15c2a7f..6825bcf6749 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -79,7 +79,7 @@ ContentAutofillDriverFactory* ContentAutofillDriverFactory::FromWebContents(
// static
void ContentAutofillDriverFactory::BindAutofillDriver(
- mojom::AutofillDriverRequest request,
+ mojom::AutofillDriverAssociatedRequest request,
content::RenderFrameHost* render_frame_host) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
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 1bcb2f909f3..2ff9b3352ab 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -45,9 +45,8 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
static ContentAutofillDriverFactory* FromWebContents(
content::WebContents* contents);
- static void BindAutofillDriver(
- mojom::AutofillDriverRequest request,
- content::RenderFrameHost* render_frame_host);
+ static void BindAutofillDriver(mojom::AutofillDriverAssociatedRequest request,
+ content::RenderFrameHost* render_frame_host);
// Gets the |ContentAutofillDriver| associated with |render_frame_host|.
// |render_frame_host| must be owned by |web_contents()|.
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 bb199189394..b883e961a5c 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -28,11 +28,11 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/frame_navigate_params.h"
#include "content/public/test/test_renderer_host.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "net/base/net_errors.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace autofill {
@@ -52,8 +52,9 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
~FakeAutofillAgent() override {}
- void BindRequest(mojo::ScopedMessagePipeHandle handle) {
- bindings_.AddBinding(this, mojom::AutofillAgentRequest(std::move(handle)));
+ void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) {
+ bindings_.AddBinding(
+ this, mojom::AutofillAgentAssociatedRequest(std::move(handle)));
}
void SetQuitLoopClosure(base::Closure closure) { quit_closure_ = closure; }
@@ -210,7 +211,7 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
void SetQueryPasswordSuggestion(bool query) override{};
- mojo::BindingSet<mojom::AutofillAgent> bindings_;
+ mojo::AssociatedBindingSet<mojom::AutofillAgent> bindings_;
base::Closure quit_closure_;
@@ -285,12 +286,12 @@ class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
driver_.reset(new TestContentAutofillDriver(web_contents()->GetMainFrame(),
test_autofill_client_.get()));
- service_manager::InterfaceProvider* remote_interfaces =
- web_contents()->GetMainFrame()->GetRemoteInterfaces();
- service_manager::InterfaceProvider::TestApi test_api(remote_interfaces);
- test_api.SetBinderForName(mojom::AutofillAgent::Name_,
- base::Bind(&FakeAutofillAgent::BindRequest,
- base::Unretained(&fake_agent_)));
+ blink::AssociatedInterfaceProvider* remote_interfaces =
+ web_contents()->GetMainFrame()->GetRemoteAssociatedInterfaces();
+ remote_interfaces->OverrideBinderForTesting(
+ mojom::AutofillAgent::Name_,
+ base::BindRepeating(&FakeAutofillAgent::BindRequest,
+ base::Unretained(&fake_agent_)));
}
void TearDown() override {
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.cc b/chromium/components/autofill/content/browser/risk/fingerprint.cc
index 5b8edff8583..e6fd9107e60 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.cc
@@ -289,9 +289,10 @@ FingerprintDataLoader::FingerprintDataLoader(
weak_ptr_factory_(this) {
DCHECK(!install_time_.is_null());
- timeout_timer_.Start(FROM_HERE, timeout,
- base::Bind(&FingerprintDataLoader::MaybeFillFingerprint,
- weak_ptr_factory_.GetWeakPtr()));
+ timeout_timer_.Start(
+ FROM_HERE, timeout,
+ base::BindOnce(&FingerprintDataLoader::MaybeFillFingerprint,
+ weak_ptr_factory_.GetWeakPtr()));
// Load GPU data if needed.
if (gpu_data_manager_->GpuAccessAllowed(nullptr) &&
@@ -302,17 +303,15 @@ FingerprintDataLoader::FingerprintDataLoader(
#if BUILDFLAG(ENABLE_PLUGINS)
// Load plugin data.
- content::PluginService::GetInstance()->GetPlugins(
- base::Bind(&FingerprintDataLoader::OnGotPlugins,
- weak_ptr_factory_.GetWeakPtr()));
+ content::PluginService::GetInstance()->GetPlugins(base::BindOnce(
+ &FingerprintDataLoader::OnGotPlugins, weak_ptr_factory_.GetWeakPtr()));
#else
waiting_on_plugins_ = false;
#endif
// Load font data.
- content::GetFontListAsync(
- base::Bind(&FingerprintDataLoader::OnGotFonts,
- weak_ptr_factory_.GetWeakPtr()));
+ content::GetFontListAsync(base::BindOnce(&FingerprintDataLoader::OnGotFonts,
+ weak_ptr_factory_.GetWeakPtr()));
// Load geolocation data.
DCHECK(connector);
diff --git a/chromium/components/autofill/content/common/autofill_agent.mojom b/chromium/components/autofill/content/common/autofill_agent.mojom
index 891f2b86ea0..e3fc0feb404 100644
--- a/chromium/components/autofill/content/common/autofill_agent.mojom
+++ b/chromium/components/autofill/content/common/autofill_agent.mojom
@@ -122,7 +122,4 @@ 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.
FoundFormsEligibleForGeneration(array<PasswordFormGenerationData> forms);
-
- // Tells the renderer to enable the form classifier.
- AllowToRunFormClassifier();
};
diff --git a/chromium/components/autofill/content/common/autofill_driver.mojom b/chromium/components/autofill/content/common/autofill_driver.mojom
index 34be2a1e28e..5f8af515d83 100644
--- a/chromium/components/autofill/content/common/autofill_driver.mojom
+++ b/chromium/components/autofill/content/common/autofill_driver.mojom
@@ -124,11 +124,6 @@ interface PasswordManagerDriver {
mojo_base.mojom.String16 typed_username,
int32 options, gfx.mojom.RectF bounds);
- // Sends the outcome of HTML parsing based form classifier that detects the
- // forms where password generation should be available.
- SaveGenerationFieldDetectedByClassifier(
- PasswordForm password_form, mojo_base.mojom.String16 generation_field);
-
// Checks the safe browsing reputation of the website where the focused
// username/password field is on.
CheckSafeBrowsingReputation(
diff --git a/chromium/components/autofill/content/common/autofill_types.mojom b/chromium/components/autofill/content/common/autofill_types.mojom
index c9ecc5760f8..546c8bca5f0 100644
--- a/chromium/components/autofill/content/common/autofill_types.mojom
+++ b/chromium/components/autofill/content/common/autofill_types.mojom
@@ -130,7 +130,6 @@ struct FormFieldData {
mojo_base.mojom.TextDirection text_direction;
bool is_enabled;
bool is_readonly;
- bool is_default;
mojo_base.mojom.String16 typed_value;
array<mojo_base.mojom.String16> option_values;
@@ -180,7 +179,6 @@ struct PasswordAndRealm {
// autofill::PasswordFormFillData
struct PasswordFormFillData {
uint32 form_renderer_id;
- mojo_base.mojom.String16 name;
url.mojom.Url origin;
url.mojom.Url action;
FormFieldData username_field;
@@ -189,7 +187,6 @@ struct PasswordFormFillData {
string preferred_realm;
map<mojo_base.mojom.String16, PasswordAndRealm> additional_logins;
bool wait_for_username;
- bool is_possible_change_password_form;
bool has_renderer_ids;
};
@@ -232,10 +229,8 @@ struct PasswordForm {
bool form_has_autofilled_value;
mojo_base.mojom.String16 password_element;
mojo_base.mojom.String16 password_value;
- bool password_value_is_default;
mojo_base.mojom.String16 new_password_element;
mojo_base.mojom.String16 new_password_value;
- bool new_password_value_is_default;
bool new_password_marked_by_site;
mojo_base.mojom.String16 confirmation_password_element;
bool preferred;
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 fad95dddd5c..77f14cdadcd 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.cc
@@ -614,7 +614,6 @@ bool StructTraits<
out->is_enabled = data.is_enabled();
out->is_readonly = data.is_readonly();
- out->is_default = data.is_default();
if (!data.ReadValue(&out->typed_value))
return false;
@@ -711,8 +710,7 @@ bool StructTraits<autofill::mojom::PasswordFormFillDataDataView,
autofill::PasswordFormFillData>::
Read(autofill::mojom::PasswordFormFillDataDataView data,
autofill::PasswordFormFillData* out) {
- if (!data.ReadName(&out->name) || !data.ReadOrigin(&out->origin) ||
- !data.ReadAction(&out->action) ||
+ if (!data.ReadOrigin(&out->origin) || !data.ReadAction(&out->action) ||
!data.ReadUsernameField(&out->username_field) ||
!data.ReadPasswordField(&out->password_field) ||
!data.ReadPreferredRealm(&out->preferred_realm) ||
@@ -721,8 +719,6 @@ bool StructTraits<autofill::mojom::PasswordFormFillDataDataView,
out->form_renderer_id = data.form_renderer_id();
out->wait_for_username = data.wait_for_username();
- out->is_possible_change_password_form =
- data.is_possible_change_password_form();
out->has_renderer_ids = data.has_renderer_ids();
out->username_may_use_prefilled_placeholder =
data.username_may_use_prefilled_placeholder();
@@ -789,13 +785,11 @@ bool StructTraits<
return false;
out->form_has_autofilled_value = data.form_has_autofilled_value();
- out->password_value_is_default = data.password_value_is_default();
if (!data.ReadNewPasswordElement(&out->new_password_element) ||
!data.ReadNewPasswordValue(&out->new_password_value))
return false;
- out->new_password_value_is_default = data.new_password_value_is_default();
out->new_password_marked_by_site = data.new_password_marked_by_site();
if (!data.ReadConfirmationPasswordElement(
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 68d03e0ec10..dcc44134d8e 100644
--- a/chromium/components/autofill/content/common/autofill_types_struct_traits.h
+++ b/chromium/components/autofill/content/common/autofill_types_struct_traits.h
@@ -216,10 +216,6 @@ struct StructTraits<autofill::mojom::FormFieldDataDataView,
return r.is_readonly;
}
- static bool is_default(const autofill::FormFieldData& r) {
- return r.is_default;
- }
-
static const base::string16& typed_value(const autofill::FormFieldData& r) {
return r.typed_value;
}
@@ -366,10 +362,6 @@ struct StructTraits<autofill::mojom::PasswordFormFillDataDataView,
return r.form_renderer_id;
}
- static const base::string16& name(const autofill::PasswordFormFillData& r) {
- return r.name;
- }
-
static const GURL& origin(const autofill::PasswordFormFillData& r) {
return r.origin;
}
@@ -407,11 +399,6 @@ struct StructTraits<autofill::mojom::PasswordFormFillDataDataView,
return r.wait_for_username;
}
- static bool is_possible_change_password_form(
- const autofill::PasswordFormFillData& r) {
- return r.is_possible_change_password_form;
- }
-
static bool has_renderer_ids(const autofill::PasswordFormFillData& r) {
return r.has_renderer_ids;
}
@@ -545,10 +532,6 @@ struct StructTraits<autofill::mojom::PasswordFormDataView,
return r.password_value;
}
- static bool password_value_is_default(const autofill::PasswordForm& r) {
- return r.password_value_is_default;
- }
-
static const base::string16& new_password_element(
const autofill::PasswordForm& r) {
return r.new_password_element;
@@ -559,10 +542,6 @@ struct StructTraits<autofill::mojom::PasswordFormDataView,
return r.new_password_value;
}
- static bool new_password_value_is_default(const autofill::PasswordForm& r) {
- return r.new_password_value_is_default;
- }
-
static bool new_password_marked_by_site(const autofill::PasswordForm& r) {
return r.new_password_marked_by_site;
}
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 f0f8abfdea2..943acf02b1b 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
@@ -37,7 +37,6 @@ void CreateTestFieldDataPredictions(const std::string& signature,
void CreateTestPasswordFormFillData(PasswordFormFillData* fill_data) {
fill_data->form_renderer_id = 1234;
- fill_data->name = base::ASCIIToUTF16("TestName");
fill_data->origin = GURL("https://foo.com/");
fill_data->action = GURL("https://foo.com/login");
test::CreateTestSelectField("TestUsernameFieldLabel", "TestUsernameFieldName",
@@ -60,7 +59,6 @@ void CreateTestPasswordFormFillData(PasswordFormFillData* fill_data) {
fill_data->additional_logins[name] = pr;
fill_data->wait_for_username = true;
- fill_data->is_possible_change_password_form = false;
}
void CreateTestPasswordForm(PasswordForm* form) {
@@ -84,10 +82,8 @@ void CreateTestPasswordForm(PasswordForm* form) {
form->form_has_autofilled_value = true;
form->password_element = base::ASCIIToUTF16("password");
form->password_value = base::ASCIIToUTF16("test");
- form->password_value_is_default = true;
form->new_password_element = base::ASCIIToUTF16("new_password");
form->new_password_value = base::ASCIIToUTF16("new_password_value");
- form->new_password_value_is_default = false;
form->new_password_marked_by_site = false;
form->new_password_element = base::ASCIIToUTF16("confirmation_password");
form->preferred = false;
@@ -157,7 +153,6 @@ void CreatePasswordGenerationUIData(
void CheckEqualPasswordFormFillData(const PasswordFormFillData& expected,
const PasswordFormFillData& actual) {
EXPECT_EQ(expected.form_renderer_id, actual.form_renderer_id);
- EXPECT_EQ(expected.name, actual.name);
EXPECT_EQ(expected.origin, actual.origin);
EXPECT_EQ(expected.action, actual.action);
EXPECT_EQ(expected.username_field, actual.username_field);
@@ -181,8 +176,6 @@ void CheckEqualPasswordFormFillData(const PasswordFormFillData& expected,
}
EXPECT_EQ(expected.wait_for_username, actual.wait_for_username);
- EXPECT_EQ(expected.is_possible_change_password_form,
- actual.is_possible_change_password_form);
}
void CheckEqualPasswordFormGenerationData(
diff --git a/chromium/components/autofill/content/renderer/BUILD.gn b/chromium/components/autofill/content/renderer/BUILD.gn
index 94cc1648850..f0b3b85b830 100644
--- a/chromium/components/autofill/content/renderer/BUILD.gn
+++ b/chromium/components/autofill/content/renderer/BUILD.gn
@@ -2,16 +2,18 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-static_library("renderer") {
+import("//build/config/jumbo.gni")
+
+jumbo_static_library("renderer") {
sources = [
"autofill_agent.cc",
"autofill_agent.h",
+ "field_data_manager.cc",
+ "field_data_manager.h",
"form_autofill_util.cc",
"form_autofill_util.h",
"form_cache.cc",
"form_cache.h",
- "form_classifier.cc",
- "form_classifier.h",
"form_tracker.cc",
"form_tracker.h",
"html_based_username_detector.cc",
@@ -56,6 +58,7 @@ static_library("renderer") {
"//services/service_manager/public/cpp",
"//skia",
"//third_party/blink/public:blink",
+ "//third_party/blink/public/common",
"//third_party/re2",
"//ui/base",
]
@@ -64,7 +67,7 @@ static_library("renderer") {
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"test_password_autofill_agent.cc",
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index 2476e264b9f..759abc427a3 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -45,6 +45,7 @@
#include "content/public/renderer/render_view.h"
#include "net/cert/cert_status_flags.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_console_message.h"
@@ -132,7 +133,7 @@ AutofillAgent::ShowSuggestionsOptions::ShowSuggestionsOptions()
AutofillAgent::AutofillAgent(content::RenderFrame* render_frame,
PasswordAutofillAgent* password_autofill_agent,
PasswordGenerationAgent* password_generation_agent,
- service_manager::BinderRegistry* registry)
+ blink::AssociatedInterfaceRegistry* registry)
: content::RenderFrameObserver(render_frame),
form_cache_(render_frame->GetWebFrame()),
password_autofill_agent_(password_autofill_agent),
@@ -158,7 +159,7 @@ AutofillAgent::~AutofillAgent() {
RemoveFormObserver(this);
}
-void AutofillAgent::BindRequest(mojom::AutofillAgentRequest request) {
+void AutofillAgent::BindRequest(mojom::AutofillAgentAssociatedRequest request) {
binding_.Bind(std::move(request));
}
@@ -417,18 +418,22 @@ void AutofillAgent::DoAcceptDataListSuggestion(
void AutofillAgent::TriggerRefillIfNeeded(const FormData& form) {
if (!base::FeatureList::IsEnabled(features::kAutofillDynamicForms))
return;
+
+ ReplaceElementIfNowInvalid(form);
+
FormFieldData field;
FormData updated_form;
if (form_util::FindFormAndFieldForFormControlElement(element_, &updated_form,
&field) &&
- !form.DynamicallySameFormAs(updated_form)) {
+ (!element_.IsAutofilled() || !form.DynamicallySameFormAs(updated_form))) {
base::TimeTicks forms_seen_timestamp = base::TimeTicks::Now();
WebLocalFrame* frame = render_frame()->GetWebFrame();
std::vector<FormData> forms;
forms.push_back(updated_form);
// Always communicate to browser process for topmost frame.
- if (!forms.empty() || !frame->Parent())
+ if (!forms.empty() || !frame->Parent()) {
GetAutofillDriver()->FormsSeen(forms, forms_seen_timestamp);
+ }
}
}
@@ -1029,11 +1034,62 @@ void AutofillAgent::OnFormNoLongerSubmittable() {
submitted_forms_.clear();
}
+bool AutofillAgent::FindTheUniqueNewVersionOfOldElement(
+ WebVector<WebFormControlElement>& elements,
+ bool& element_found,
+ const WebString& original_element_section,
+ const WebFormControlElement& original_element) {
+ for (const WebFormControlElement& current_element : elements) {
+ if (current_element.IsFocusable() &&
+ original_element.NameForAutofill() ==
+ current_element.NameForAutofill()) {
+ if (!element_found) {
+ element_ = current_element;
+ element_found = true;
+ } else if (current_element.AutofillSection() ==
+ element_.AutofillSection() ||
+ (current_element.AutofillSection() !=
+ original_element_section &&
+ element_.AutofillSection() != original_element_section)) {
+ // If there are two elements that share the same name with the element_,
+ // and the section can't tell them apart, we can't decide between the
+ // two.
+ element_ = original_element;
+ return false;
+ } else if (current_element.AutofillSection() ==
+ original_element_section) {
+ // If the current element has the right section, update the element_.
+ element_ = current_element;
+ }
+ }
+ }
+ return true;
+}
+
void AutofillAgent::ReplaceElementIfNowInvalid(const FormData& original_form) {
// If the document is invalid, bail out.
if (element_.GetDocument().IsNull())
return;
+ WebVector<WebFormElement> forms;
+ WebVector<WebFormControlElement> elements;
+
+ if (original_form.name.empty()) {
+ // If the form has no name, check all the forms.
+ bool element_found = false;
+ element_.GetDocument().Forms(forms);
+ for (const WebFormElement& form : forms) {
+ form.GetFormControlElements(elements);
+ // If finding a unique element is impossible, return.
+ if (!FindTheUniqueNewVersionOfOldElement(
+ elements, element_found, element_.AutofillSection(), element_))
+ return;
+ }
+ // If the element is not found, we should still check for unowned elements.
+ if (element_found)
+ return;
+ }
+
if (!element_.Form().IsNull()) {
// If |element_|'s parent form has no elements, |element_| is now invalid
// and should be updated.
@@ -1043,29 +1099,32 @@ void AutofillAgent::ReplaceElementIfNowInvalid(const FormData& original_form) {
return;
}
- // Try to find the new version of the form.
WebFormElement form_element;
- WebVector<WebFormElement> forms;
- element_.GetDocument().Forms(forms);
- for (const WebFormElement& form : forms) {
- if (original_form.name == form.GetName().Utf16() ||
- original_form.name == form.GetAttribute("id").Utf16()) {
- form_element = form;
- break;
+ if (!original_form.name.empty()) {
+ // Try to find the new version of the form.
+ element_.GetDocument().Forms(forms);
+ for (const WebFormElement& form : forms) {
+ if (original_form.name == form.GetName().Utf16() ||
+ original_form.name == form.GetAttribute("id").Utf16()) {
+ form_element = form;
+ break;
+ }
}
}
- WebVector<WebFormControlElement> elements;
if (form_element.IsNull()) {
// Could not find the new version of the form, get all the unowned elements.
std::vector<WebElement> fieldsets;
elements = form_util::GetUnownedAutofillableFormFieldElements(
element_.GetDocument().All(), &fieldsets);
- } else {
- // Get all the elements of the new version of the form.
- form_element.GetFormControlElements(elements);
+ bool element_found = false;
+ FindTheUniqueNewVersionOfOldElement(elements, element_found,
+ element_.AutofillSection(), element_);
+ return;
}
-
+ // This is the case for owned fields that belong to the right named form.
+ // Get all the elements of the new version of the form.
+ form_element.GetFormControlElements(elements);
// Try to find the new version of the last interacted element.
for (const WebFormControlElement& element : elements) {
if (element_.NameForAutofill() == element.NameForAutofill()) {
@@ -1075,9 +1134,9 @@ void AutofillAgent::ReplaceElementIfNowInvalid(const FormData& original_form) {
}
}
-const mojom::AutofillDriverPtr& AutofillAgent::GetAutofillDriver() {
+const mojom::AutofillDriverAssociatedPtr& AutofillAgent::GetAutofillDriver() {
if (!autofill_driver_) {
- render_frame()->GetRemoteInterfaces()->GetInterface(
+ render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
mojo::MakeRequest(&autofill_driver_));
}
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.h b/chromium/components/autofill/content/renderer/autofill_agent.h
index ba36f73adfb..8da5c3c5025 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/autofill_agent.h
@@ -19,8 +19,8 @@
#include "components/autofill/content/renderer/form_cache.h"
#include "components/autofill/content/renderer/form_tracker.h"
#include "content/public/renderer/render_frame_observer.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_form_control_element.h"
#include "third_party/blink/public/web/web_form_element.h"
@@ -29,6 +29,10 @@
namespace blink {
class WebNode;
class WebView;
+class WebString;
+class WebFormControlElement;
+template <typename T>
+class WebVector;
}
namespace autofill {
@@ -57,12 +61,12 @@ class AutofillAgent : public content::RenderFrameObserver,
AutofillAgent(content::RenderFrame* render_frame,
PasswordAutofillAgent* password_autofill_manager,
PasswordGenerationAgent* password_generation_agent,
- service_manager::BinderRegistry* registry);
+ blink::AssociatedInterfaceRegistry* registry);
~AutofillAgent() override;
- void BindRequest(mojom::AutofillAgentRequest request);
+ void BindRequest(mojom::AutofillAgentAssociatedRequest request);
- const mojom::AutofillDriverPtr& GetAutofillDriver();
+ const mojom::AutofillDriverAssociatedPtr& GetAutofillDriver();
const mojom::PasswordManagerDriverAssociatedPtr& GetPasswordManagerDriver();
@@ -266,6 +270,15 @@ class AutofillAgent : public content::RenderFrameObserver,
// cleared in this method.
void OnFormNoLongerSubmittable();
+ // For no name forms, and unowned elements, try to see if there is a unique
+ // element in the updated form that corresponds to the old |element_|.
+ // Returns false if more than one element matches the |element_|.
+ bool FindTheUniqueNewVersionOfOldElement(
+ blink::WebVector<blink::WebFormControlElement>& elements,
+ bool& element_found,
+ const blink::WebString& original_element_section,
+ const blink::WebFormControlElement& original_element);
+
// Check whether |element_| was removed or replaced dynamically on the page.
// If so, looks for the same element in the updated |form| and replaces the
// |element_| with it if it's found.
@@ -354,9 +367,9 @@ class AutofillAgent : public content::RenderFrameObserver,
// Whether or not we delay focus handling until scrolling occurs.
bool focus_requires_scroll_ = true;
- mojo::Binding<mojom::AutofillAgent> binding_;
+ mojo::AssociatedBinding<mojom::AutofillAgent> binding_;
- mojom::AutofillDriverPtr autofill_driver_;
+ mojom::AutofillDriverAssociatedPtr autofill_driver_;
bool was_last_action_fill_ = false;
diff --git a/chromium/components/autofill/content/renderer/field_data_manager.cc b/chromium/components/autofill/content/renderer/field_data_manager.cc
new file mode 100644
index 00000000000..46d6e7d35b4
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/field_data_manager.cc
@@ -0,0 +1,84 @@
+// 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/content/renderer/field_data_manager.h"
+
+#include "base/i18n/case_conversion.h"
+#include "base/logging.h"
+#include "third_party/blink/public/web/web_form_control_element.h"
+
+namespace autofill {
+
+FieldDataManager::FieldDataManager() = default;
+
+FieldDataManager::~FieldDataManager() = default;
+
+void FieldDataManager::ClearData() {
+ field_value_and_properties_map_.clear();
+}
+
+bool FieldDataManager::HasFieldData(uint32_t id) const {
+ return field_value_and_properties_map_.find(id) !=
+ field_value_and_properties_map_.end();
+}
+
+base::string16 FieldDataManager::GetUserTypedValue(uint32_t id) const {
+ DCHECK(HasFieldData(id));
+ return field_value_and_properties_map_.at(id).first.value_or(
+ base::string16());
+}
+
+FieldPropertiesMask FieldDataManager::GetFieldPropertiesMask(
+ uint32_t id) const {
+ DCHECK(HasFieldData(id));
+ return field_value_and_properties_map_.at(id).second;
+}
+
+bool FieldDataManager::FindMachedValue(const base::string16& value) const {
+ constexpr size_t kMinMatchSize = 3u;
+ const auto lowercase = base::i18n::ToLower(value);
+ for (const auto& map_key : field_value_and_properties_map_) {
+ const base::string16 typed_from_key =
+ map_key.second.first.value_or(base::string16());
+ if (typed_from_key.empty())
+ continue;
+ if (typed_from_key.size() >= kMinMatchSize &&
+ lowercase.find(base::i18n::ToLower(typed_from_key)) !=
+ base::string16::npos)
+ return true;
+ }
+ return false;
+}
+
+void FieldDataManager::UpdateFieldDataMap(
+ const blink::WebFormControlElement& element,
+ const base::string16& value,
+ FieldPropertiesMask mask) {
+ uint32_t id = element.UniqueRendererFormControlId();
+ if (HasFieldData(id)) {
+ field_value_and_properties_map_.at(id).first =
+ base::Optional<base::string16>(value);
+ field_value_and_properties_map_.at(id).second |= mask;
+ } else {
+ field_value_and_properties_map_[id] =
+ std::make_pair(base::Optional<base::string16>(value), mask);
+ }
+ // Reset USER_TYPED and AUTOFILLED flags if the value is empty.
+ if (value.empty()) {
+ field_value_and_properties_map_.at(id).second &=
+ ~(FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED);
+ }
+}
+
+void FieldDataManager::UpdateFieldDataMapWithNullValue(
+ const blink::WebFormControlElement& element,
+ FieldPropertiesMask mask) {
+ uint32_t id = element.UniqueRendererFormControlId();
+ if (HasFieldData(id))
+ field_value_and_properties_map_.at(id).second |= mask;
+ else
+ field_value_and_properties_map_[id] = std::make_pair(base::nullopt, mask);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/field_data_manager.h b/chromium/components/autofill/content/renderer/field_data_manager.h
new file mode 100644
index 00000000000..c00f6f69638
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/field_data_manager.h
@@ -0,0 +1,56 @@
+// 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_CONTENT_RENDERER_FIELD_DATA_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_FIELD_DATA_MANAGER_H_
+
+#include <map>
+
+#include "base/optional.h"
+#include "base/strings/string16.h"
+#include "components/autofill/core/common/form_field_data.h"
+
+namespace blink {
+class WebFormControlElement;
+}
+
+namespace autofill {
+
+// This class provides the meathods to update and get the field data (the pair
+// of user typed value and field properties mask).
+class FieldDataManager {
+ public:
+ FieldDataManager();
+ ~FieldDataManager();
+
+ void ClearData();
+ bool HasFieldData(uint32_t id) const;
+
+ // Updates the field value associated with the key |element| in
+ // |field_value_and_properties_map_|.
+ // Flags in |mask| are added with bitwise OR operation.
+ // If |value| is empty, USER_TYPED and AUTOFILLED should be cleared.
+ void UpdateFieldDataMap(const blink::WebFormControlElement& element,
+ const base::string16& value,
+ FieldPropertiesMask mask);
+ // Only update FieldPropertiesMask when value is null.
+ void UpdateFieldDataMapWithNullValue(
+ const blink::WebFormControlElement& element,
+ FieldPropertiesMask mask);
+
+ base::string16 GetUserTypedValue(uint32_t id) const;
+ FieldPropertiesMask GetFieldPropertiesMask(uint32_t id) const;
+
+ // Check if the string |value| is saved in |field_value_and_properties_map_|.
+ bool FindMachedValue(const base::string16& value) const;
+
+ private:
+ std::map<uint32_t,
+ std::pair<base::Optional<base::string16>, FieldPropertiesMask>>
+ field_value_and_properties_map_;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_FIELD_DATA_MANAGER_H_
diff --git a/chromium/components/autofill/content/renderer/field_data_manager_browsertest.cc b/chromium/components/autofill/content/renderer/field_data_manager_browsertest.cc
new file mode 100644
index 00000000000..1c40aae9916
--- /dev/null
+++ b/chromium/components/autofill/content/renderer/field_data_manager_browsertest.cc
@@ -0,0 +1,113 @@
+// 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/content/renderer/field_data_manager.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/render_view_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_element_collection.h"
+#include "third_party/blink/public/web/web_form_control_element.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+
+namespace autofill {
+
+class FieldDataManagerTest : public content::RenderViewTest {
+ public:
+ FieldDataManagerTest() {}
+ ~FieldDataManagerTest() override {}
+
+ protected:
+ void SetUp() override {
+ RenderViewTest::SetUp();
+
+ LoadHTML(
+ "<input type='text' id='name1' value='first'>"
+ "<input type='password' id='name2' value=''>");
+ blink::WebLocalFrame* web_frame = GetMainFrame();
+ blink::WebElementCollection inputs =
+ web_frame->GetDocument().GetElementsByHTMLTagName("input");
+ for (blink::WebElement element = inputs.FirstItem(); !element.IsNull();
+ element = inputs.NextItem()) {
+ control_elements_.push_back(element.To<blink::WebFormControlElement>());
+ }
+ }
+
+ void TearDown() override {
+ control_elements_.clear();
+ RenderViewTest::TearDown();
+ }
+
+ std::vector<blink::WebFormControlElement> control_elements_;
+};
+
+TEST_F(FieldDataManagerTest, UpdateFieldDataMap) {
+ FieldDataManager field_data_manager;
+ field_data_manager.UpdateFieldDataMap(control_elements_[0],
+ control_elements_[0].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
+ const uint32_t id = control_elements_[0].UniqueRendererFormControlId();
+ EXPECT_TRUE(field_data_manager.HasFieldData(id));
+ EXPECT_EQ(base::UTF8ToUTF16("first"),
+ field_data_manager.GetUserTypedValue(id));
+ EXPECT_EQ(FieldPropertiesFlags::USER_TYPED,
+ field_data_manager.GetFieldPropertiesMask(id));
+
+ field_data_manager.UpdateFieldDataMap(control_elements_[0],
+ base::UTF8ToUTF16("newvalue"),
+ FieldPropertiesFlags::AUTOFILLED);
+ EXPECT_EQ(base::UTF8ToUTF16("newvalue"),
+ field_data_manager.GetUserTypedValue(id));
+ FieldPropertiesMask mask =
+ FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED;
+ EXPECT_EQ(mask, field_data_manager.GetFieldPropertiesMask(id));
+
+ field_data_manager.UpdateFieldDataMap(control_elements_[1],
+ control_elements_[1].Value().Utf16(),
+ FieldPropertiesFlags::AUTOFILLED);
+ EXPECT_EQ(FieldPropertiesFlags::NO_FLAGS,
+ field_data_manager.GetFieldPropertiesMask(
+ control_elements_[1].UniqueRendererFormControlId()));
+
+ field_data_manager.ClearData();
+ EXPECT_FALSE(field_data_manager.HasFieldData(id));
+}
+
+TEST_F(FieldDataManagerTest, UpdateFieldDataMapWithNullValue) {
+ FieldDataManager field_data_manager;
+ field_data_manager.UpdateFieldDataMapWithNullValue(
+ control_elements_[0], FieldPropertiesFlags::USER_TYPED);
+ const uint32_t id = control_elements_[0].UniqueRendererFormControlId();
+ EXPECT_TRUE(field_data_manager.HasFieldData(id));
+ EXPECT_EQ(base::string16(), field_data_manager.GetUserTypedValue(id));
+ EXPECT_EQ(FieldPropertiesFlags::USER_TYPED,
+ field_data_manager.GetFieldPropertiesMask(id));
+
+ field_data_manager.UpdateFieldDataMapWithNullValue(
+ control_elements_[0], FieldPropertiesFlags::AUTOFILLED);
+ EXPECT_EQ(base::string16(), field_data_manager.GetUserTypedValue(id));
+ FieldPropertiesMask mask =
+ FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED;
+ EXPECT_EQ(mask, field_data_manager.GetFieldPropertiesMask(id));
+
+ field_data_manager.UpdateFieldDataMap(control_elements_[0],
+ control_elements_[0].Value().Utf16(),
+ FieldPropertiesFlags::AUTOFILLED);
+ EXPECT_EQ(base::UTF8ToUTF16("first"),
+ field_data_manager.GetUserTypedValue(id));
+}
+
+TEST_F(FieldDataManagerTest, FindMachedValue) {
+ FieldDataManager field_data_manager;
+ field_data_manager.UpdateFieldDataMap(control_elements_[0],
+ control_elements_[0].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
+ EXPECT_TRUE(
+ field_data_manager.FindMachedValue(base::UTF8ToUTF16("first_element")));
+ EXPECT_FALSE(
+ field_data_manager.FindMachedValue(base::UTF8ToUTF16("second_element")));
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.cc b/chromium/components/autofill/content/renderer/form_autofill_util.cc
index 8f11a5adb45..53c7396590d 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.cc
@@ -22,6 +22,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "components/autofill/content/renderer/field_data_manager.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_regexes.h"
@@ -876,6 +877,13 @@ void ForEachMatchingFormFieldCommon(
base::i18n::ToLower(element->Value().Utf16())))
continue;
+ // Check if we should autofill/preview/clear a select element or leave it.
+ if (!force_override && !is_initiating_element &&
+ IsSelectElement(*element) && element->UserHasEditedTheField() &&
+ base::FeatureList::IsEnabled(features::kAutofillPrefilledFields) &&
+ !SanitizedFieldIsEmpty(element->Value().Utf16()))
+ continue;
+
if (((filters & FILTER_DISABLED_ELEMENTS) && !element->IsEnabled()) ||
((filters & FILTER_READONLY_ELEMENTS) && element->IsReadOnly()) ||
// See description for FILTER_NON_FOCUSABLE_ELEMENTS.
@@ -1010,7 +1018,7 @@ void PreviewFormField(const FormFieldData& data,
// [1, kMaxParseableFields].
bool ExtractFieldsFromControlElements(
const WebVector<WebFormControlElement>& control_elements,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
std::vector<std::unique_ptr<FormFieldData>>* form_fields,
std::vector<bool>* fields_extracted,
@@ -1027,8 +1035,7 @@ bool ExtractFieldsFromControlElements(
// Create a new FormFieldData, fill it out and map it to the field's name.
auto form_field = std::make_unique<FormFieldData>();
- WebFormControlElementToFormField(control_element,
- field_value_and_properties_map,
+ WebFormControlElementToFormField(control_element, field_data_manager,
extract_mask, form_field.get());
(*element_map)[control_element] = form_field.get();
form_fields->push_back(std::move(form_field));
@@ -1115,7 +1122,7 @@ bool FormOrFieldsetsToFormData(
const blink::WebFormControlElement* form_control_element,
const std::vector<blink::WebElement>& fieldsets,
const WebVector<WebFormControlElement>& control_elements,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormData* form,
FormFieldData* field) {
@@ -1137,9 +1144,9 @@ bool FormOrFieldsetsToFormData(
// requirements and thus will be in the resulting |form|.
std::vector<bool> fields_extracted(control_elements.size(), false);
- if (!ExtractFieldsFromControlElements(
- control_elements, field_value_and_properties_map, extract_mask,
- &form_fields, &fields_extracted, &element_map)) {
+ if (!ExtractFieldsFromControlElements(control_elements, field_data_manager,
+ extract_mask, &form_fields,
+ &fields_extracted, &element_map)) {
return false;
}
@@ -1220,7 +1227,7 @@ bool UnownedFormElementsAndFieldSetsToFormData(
const std::vector<blink::WebFormControlElement>& control_elements,
const blink::WebFormControlElement* element,
const blink::WebDocument& document,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormData* form,
FormFieldData* field) {
@@ -1234,9 +1241,9 @@ bool UnownedFormElementsAndFieldSetsToFormData(
form->is_form_tag = false;
- return FormOrFieldsetsToFormData(
- nullptr, element, fieldsets, control_elements,
- field_value_and_properties_map, extract_mask, form, field);
+ return FormOrFieldsetsToFormData(nullptr, element, fieldsets,
+ control_elements, field_data_manager,
+ extract_mask, form, field);
}
// Check if a script modified username is suitable for Password Manager to
@@ -1244,7 +1251,7 @@ bool UnownedFormElementsAndFieldSetsToFormData(
bool ScriptModifiedUsernameAcceptable(
const base::string16& value,
const base::string16& typed_value,
- const FieldValueAndPropertiesMaskMap& field_value_and_properties_map) {
+ const FieldDataManager* field_data_manager) {
// The minimal size of a field value that will be substring-matched.
constexpr size_t kMinMatchSize = 3u;
const auto lowercase = base::i18n::ToLower(value);
@@ -1262,18 +1269,7 @@ bool ScriptModifiedUsernameAcceptable(
// If the page-generated value comes from user typed or autofilled values in
// other fields, that's also likely OK.
- for (const auto& map_key : field_value_and_properties_map) {
- const base::string16* typed_from_key = map_key.second.first.get();
- if (!typed_from_key)
- continue;
- if (typed_from_key->size() >= kMinMatchSize &&
- lowercase.find(base::i18n::ToLower(*typed_from_key)) !=
- base::string16::npos) {
- return true;
- }
- }
-
- return false;
+ return field_data_manager->FindMachedValue(value);
}
} // namespace
@@ -1470,7 +1466,7 @@ std::vector<WebFormControlElement> ExtractAutofillableElementsInForm(
void WebFormControlElementToFormField(
const WebFormControlElement& element,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormFieldData* field) {
DCHECK(field);
@@ -1505,12 +1501,10 @@ void WebFormControlElementToFormField(
if (element.HasAttribute(kClass))
field->css_classes = element.GetAttribute(kClass).Utf16();
- if (field_value_and_properties_map) {
- FieldValueAndPropertiesMaskMap::const_iterator it =
- field_value_and_properties_map->find(
- element.UniqueRendererFormControlId());
- if (it != field_value_and_properties_map->end())
- field->properties_mask = it->second.second;
+ if (field_data_manager &&
+ field_data_manager->HasFieldData(element.UniqueRendererFormControlId())) {
+ field->properties_mask = field_data_manager->GetFieldPropertiesMask(
+ element.UniqueRendererFormControlId());
}
if (!IsAutofillableElement(element))
@@ -1528,7 +1522,6 @@ void WebFormControlElementToFormField(
field->text_direction = GetTextDirectionForElement(element);
field->is_enabled = element.IsEnabled();
field->is_readonly = element.IsReadOnly();
- field->is_default = element.GetAttribute("value") == element.Value();
}
if (IsAutofillableInputElement(input_element)) {
@@ -1576,24 +1569,22 @@ void WebFormControlElementToFormField(
field->value = value;
// If the field was autofilled or the user typed into it, check the value
- // stored in |field_value_and_properties_map| against the value property of
- // the DOM element. If they differ, then the scripts on the website modified
- // the value afterwards. Store the original value as the |typed_value|, unless
+ // stored in |field_data_manager| against the value property of the DOM
+ // element. If they differ, then the scripts on the website modified the
+ // value afterwards. Store the original value as the |typed_value|, unless
// this is one of recognised situations when the site-modified value is more
// useful for filling.
- if (field_value_and_properties_map &&
+ if (field_data_manager &&
field->properties_mask & (FieldPropertiesFlags::USER_TYPED |
FieldPropertiesFlags::AUTOFILLED)) {
- const base::string16 typed_value =
- *field_value_and_properties_map
- ->at(element.UniqueRendererFormControlId())
- .first;
+ const base::string16 typed_value = field_data_manager->GetUserTypedValue(
+ element.UniqueRendererFormControlId());
// The typed value is preserved for all passwords. It is also preserved for
// potential usernames, as long as the |value| is not deemed acceptable.
if (field->form_control_type == "password" ||
!ScriptModifiedUsernameAcceptable(value, typed_value,
- *field_value_and_properties_map)) {
+ field_data_manager)) {
field->typed_value = typed_value;
}
}
@@ -1602,7 +1593,7 @@ void WebFormControlElementToFormField(
bool WebFormElementToFormData(
const blink::WebFormElement& form_element,
const blink::WebFormControlElement& form_control_element,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormData* form,
FormFieldData* field) {
@@ -1631,7 +1622,7 @@ bool WebFormElementToFormData(
std::vector<blink::WebElement> dummy_fieldset;
return FormOrFieldsetsToFormData(
&form_element, &form_control_element, dummy_fieldset, control_elements,
- field_value_and_properties_map, extract_mask, form, field);
+ field_data_manager, extract_mask, form, field);
}
std::vector<WebFormControlElement> GetUnownedFormFieldElements(
@@ -1765,13 +1756,13 @@ bool UnownedPasswordFormElementsAndFieldSetsToFormData(
const std::vector<blink::WebFormControlElement>& control_elements,
const blink::WebFormControlElement* element,
const blink::WebDocument& document,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormData* form,
FormFieldData* field) {
return UnownedFormElementsAndFieldSetsToFormData(
- fieldsets, control_elements, element, document,
- field_value_and_properties_map, extract_mask, form, field);
+ fieldsets, control_elements, element, document, field_data_manager,
+ extract_mask, form, field);
}
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.h b/chromium/components/autofill/content/renderer/form_autofill_util.h
index ab69b3fbfca..429005bcb98 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.h
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.h
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/strings/string16.h"
-#include "components/autofill/content/renderer/password_form_conversion_utils.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/password_form_field_prediction_map.h"
#include "third_party/blink/public/platform/web_vector.h"
@@ -22,6 +21,8 @@
class GURL;
namespace blink {
+enum class WebAutofillState;
+
class WebDocument;
class WebElement;
class WebFormControlElement;
@@ -36,6 +37,8 @@ namespace autofill {
struct FormData;
struct FormFieldData;
+class FieldDataManager;
+
namespace form_util {
// A bit field mask to extract data from WebFormControlElement.
@@ -137,11 +140,11 @@ std::vector<blink::WebFormControlElement> ExtractAutofillableElementsInForm(
// Fills out a FormField object from a given WebFormControlElement.
// |extract_mask|: See the enum ExtractMask above for details. Field properties
-// will be copied from |field_value_and_properties_map|, if the argument is not
-// null and has entry for |element| (see properties in FieldPropertiesFlags).
+// will be copied from |field_data_manager|, if the argument is not null and
+// has entry for |element| (see properties in FieldPropertiesFlags).
void WebFormControlElementToFormField(
const blink::WebFormControlElement& element,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormFieldData* field);
@@ -150,12 +153,12 @@ void WebFormControlElementToFormField(
// corresponding to the |form_control_element|. |extract_mask| controls what
// data is extracted. Returns true if |form| is filled out. Also returns false
// if there are no fields or too many fields in the |form|. Field properties
-// will be copied from |field_value_and_properties_map|, if the argument is not
-// null and has entry for |element| (see properties in FieldPropertiesFlags).
+// will be copied from |field_data_manager|, if the argument is not null and
+// has entry for |element| (see properties in FieldPropertiesFlags).
bool WebFormElementToFormData(
const blink::WebFormElement& form_element,
const blink::WebFormControlElement& form_control_element,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormData* form,
FormFieldData* field);
@@ -192,14 +195,14 @@ bool UnownedCheckoutFormElementsAndFieldSetsToFormData(
// Same as above, but without the requirement that the elements only be
// related to checkout. Field properties of |control_elements| will be copied
-// from |field_value_and_properties_map|, if the argument is not null and has
-// corresponding entries (see properties in FieldPropertiesFlags).
+// from |field_data_manager|, if the argument is not null and has corresponding
+// entries (see properties in FieldPropertiesFlags).
bool UnownedPasswordFormElementsAndFieldSetsToFormData(
const std::vector<blink::WebElement>& fieldsets,
const std::vector<blink::WebFormControlElement>& control_elements,
const blink::WebFormControlElement* element,
const blink::WebDocument& document,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
ExtractMask extract_mask,
FormData* form,
FormFieldData* field);
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 ac1f4085c65..29879265288 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -344,55 +344,6 @@ TEST_F(FormAutofillUtilsTest, IsReadonly) {
}
}
-TEST_F(FormAutofillUtilsTest, IsDefault) {
- LoadHTML(
- "<input type='text' id='name1' value='123'>"
- "<input type='password' id='name2'>"
- "<input type='password' id='name3'>"
- "<input type='text' id='name4' value='321'>");
-
- const std::vector<blink::WebElement> dummy_fieldsets;
-
- WebLocalFrame* web_frame = GetMainFrame();
- ASSERT_TRUE(web_frame);
-
- web_frame->GetDocument()
- .GetElementById("name1")
- .To<blink::WebInputElement>()
- .SetAutofillValue("abc");
- web_frame->GetDocument()
- .GetElementById("name3")
- .To<blink::WebInputElement>()
- .SetAutofillValue("abc");
-
- std::vector<blink::WebFormControlElement> control_elements;
- blink::WebElementCollection inputs =
- web_frame->GetDocument().GetElementsByHTMLTagName("input");
- for (blink::WebElement element = inputs.FirstItem(); !element.IsNull();
- element = inputs.NextItem()) {
- control_elements.push_back(element.To<blink::WebFormControlElement>());
- }
-
- autofill::FormData target;
- EXPECT_TRUE(
- autofill::form_util::UnownedPasswordFormElementsAndFieldSetsToFormData(
- dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
- nullptr, autofill::form_util::EXTRACT_NONE, &target, nullptr));
- const struct {
- const char* const name;
- bool is_default;
- } kExpectedFields[] = {
- {"name1", false}, {"name2", true}, {"name3", false}, {"name4", true},
- };
- const size_t number_of_cases = arraysize(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),
- target.fields[i].name);
- EXPECT_EQ(kExpectedFields[i].is_default, target.fields[i].is_default);
- }
-}
-
TEST_F(FormAutofillUtilsTest, IsFocusable) {
LoadHTML(
"<input type='text' id='name1' value='123'>"
diff --git a/chromium/components/autofill/content/renderer/form_classifier.cc b/chromium/components/autofill/content/renderer/form_classifier.cc
deleted file mode 100644
index 7ab47ad4f6c..00000000000
--- a/chromium/components/autofill/content/renderer/form_classifier.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/content/renderer/form_classifier.h"
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "components/autofill/content/renderer/form_autofill_util.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/public/web/web_form_control_element.h"
-#include "third_party/blink/public/web/web_input_element.h"
-
-using autofill::form_util::WebFormControlElementToFormField;
-using blink::WebFormControlElement;
-using blink::WebInputElement;
-using blink::WebString;
-using blink::WebVector;
-
-namespace autofill {
-
-namespace {
-
-// The words that frequently appear in attribute values of signin forms.
-const char* const kSigninTextFeatures[] = {"signin", "login", "logon", "auth"};
-constexpr size_t kNumberOfSigninFeatures = arraysize(kSigninTextFeatures);
-
-// The words that frequently appear in attribute values of signup forms.
-const char* const kSignupTextFeatures[] = {"signup", "regist", "creat"};
-constexpr size_t kNumberOfSignupFeatures = arraysize(kSignupTextFeatures);
-
-// The words that frequently appear in attribute values of captcha elements.
-const char* const kCaptchaFeatures[] = {"captcha", "security", "code"};
-constexpr size_t kNumberOfCaptchaFeatures = arraysize(kCaptchaFeatures);
-
-// Minimal number of input fields to classify form as signup or change password
-// form. If at least one of the listed thresholds is reached or exceeded, the
-// form is classified as a form where password generation should be available.
-constexpr size_t MINIMAL_NUMBER_OF_TEXT_FIELDS = 2;
-constexpr size_t MINIMAL_NUMBER_OF_PASSWORD_FIELDS = 2;
-constexpr size_t MINIMAL_NUMBER_OF_CHECKBOX_FIELDS = 3;
-constexpr size_t MINIMAL_NUMBER_OF_OTHER_FIELDS = 2;
-
-// Removes some characters from attribute value.
-void ClearAttributeValue(std::string* value) {
- value->erase(std::remove_if(value->begin(), value->end(),
- [](char x) { return x == '-' || x == '_'; }),
- value->end());
-}
-
-// Find |features| in |element|'s attribute values. Returns true if at least one
-// text feature was found.
-bool FindTextFeaturesForClass(const blink::WebElement& element,
- const char* const features[],
- size_t number_of_features) {
- DCHECK(features);
-
- for (unsigned i = 0; i < element.AttributeCount(); ++i) {
- std::string filtered_value =
- base::ToLowerASCII(element.AttributeValue(i).Utf8());
- ClearAttributeValue(&filtered_value);
-
- if (filtered_value.empty())
- continue;
- for (size_t j = 0; j < number_of_features; ++j) {
- if (filtered_value.find(features[j]) != std::string::npos)
- return true;
- }
- }
- return false;
-}
-
-// Returns true if at least one captcha feature was found in |element|'s
-// attribute values.
-bool IsCaptchaInput(const blink::WebInputElement& element) {
- return FindTextFeaturesForClass(element, kCaptchaFeatures,
- kNumberOfCaptchaFeatures);
-}
-
-// Finds <img>'s inside |form| and checks if <img>'s attributes contains captcha
-// text features. Returns true, if at least one occurrence was found.
-bool FindCaptchaInImgElements(const blink::WebElement& form,
- bool ingnore_invisible) {
- CR_DEFINE_STATIC_LOCAL(WebString, kImageTag, ("img"));
-
- blink::WebElementCollection img_elements =
- form.GetElementsByHTMLTagName(kImageTag);
- for (blink::WebElement element = img_elements.FirstItem(); !element.IsNull();
- element = img_elements.NextItem()) {
- if (ingnore_invisible && !form_util::IsWebElementVisible(element))
- continue;
- if (FindTextFeaturesForClass(element, kCaptchaFeatures,
- kNumberOfCaptchaFeatures)) {
- return true;
- }
- }
- return false;
-}
-
-// Finds signin and signup features in |element|'s attribute values. Sets to
-// true |found_signin_text_features| or |found_signup_text_features| if
-// appropriate features were found.
-void FindTextFeaturesInElement(const blink::WebElement& element,
- bool* found_signin_text_features,
- bool* found_signup_text_features) {
- DCHECK(found_signin_text_features);
- DCHECK(found_signup_text_features);
-
- if (!*found_signin_text_features) {
- *found_signin_text_features = FindTextFeaturesForClass(
- element, kSigninTextFeatures, kNumberOfSigninFeatures);
- }
- if (!*found_signup_text_features) {
- *found_signup_text_features = FindTextFeaturesForClass(
- element, kSignupTextFeatures, kNumberOfSignupFeatures);
- }
-}
-
-// Returns true if |element| has type "button" or "image".
-bool IsButtonOrImageElement(const WebFormControlElement& element) {
- CR_DEFINE_STATIC_LOCAL(WebString, kButton, ("button"));
- CR_DEFINE_STATIC_LOCAL(WebString, kImage, ("image"));
-
- return element.FormControlTypeForAutofill() == kButton ||
- element.FormControlTypeForAutofill() == kImage;
-}
-
-// Returns true if |element| has type "submit".
-bool IsSubmitElement(const WebFormControlElement& element) {
- CR_DEFINE_STATIC_LOCAL(WebString, kSubmit, ("submit"));
-
- return element.FormControlTypeForAutofill() == kSubmit;
-}
-
-// Returns true if |element| has type "hidden";
-bool IsHiddenElement(const WebFormControlElement& element) {
- CR_DEFINE_STATIC_LOCAL(WebString, kHidden, ("hidden"));
-
- return element.FormControlTypeForAutofill() == kHidden;
-}
-
-// Returns true if |element| has type "select-multiple" or "select-one".
-bool IsSelectElement(const WebFormControlElement& element) {
- CR_DEFINE_STATIC_LOCAL(WebString, kSelectOne, ("select-one"));
- CR_DEFINE_STATIC_LOCAL(WebString, kSelectMultiple, ("select-multiple"));
-
- return element.FormControlTypeForAutofill() == kSelectOne ||
- element.FormControlTypeForAutofill() == kSelectMultiple;
-}
-
-// Return true if |form| contains at least one visible password element.
-bool FormContainsVisiblePasswordFields(const blink::WebFormElement& form) {
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
- for (auto& control_element : control_elements) {
- const WebInputElement* input_element = ToWebInputElement(&control_element);
- if (!input_element)
- continue;
- if (input_element->IsPasswordFieldForAutofill() &&
- form_util::IsWebElementVisible(*input_element)) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
-bool ClassifyFormAndFindGenerationField(const blink::WebFormElement& form,
- base::string16* generation_field) {
- DCHECK(generation_field);
-
- if (form.IsNull())
- return false;
-
- bool ignore_invisible_elements = FormContainsVisiblePasswordFields(form);
-
- bool found_signin_text_features = false;
- bool found_signup_text_features = false;
- size_t number_of_text_input_fields = 0;
- size_t number_of_password_input_fields = 0;
- size_t number_of_checkbox_input_fields = 0;
- size_t number_of_other_input_fields = 0;
- bool found_captcha =
- FindCaptchaInImgElements(form, ignore_invisible_elements);
-
- FindTextFeaturesInElement(form, &found_signin_text_features,
- &found_signup_text_features);
-
- std::vector<WebInputElement> passwords;
- WebVector<WebFormControlElement> control_elements;
- form.GetFormControlElements(control_elements);
-
- for (const WebFormControlElement& control_element : control_elements) {
- if (IsHiddenElement(control_element))
- continue;
- if (ignore_invisible_elements) {
- if (!form_util::IsWebElementVisible(control_element))
- continue;
- }
-
- // If type="button" or "image", skip them, because it might be a link
- // to another form.
- if (IsButtonOrImageElement(control_element))
- continue;
-
- FindTextFeaturesInElement(control_element, &found_signin_text_features,
- &found_signup_text_features);
-
- // Since <select> is not WebInputElement, but WebSelectElement, process
- // them as a special case.
- if (IsSelectElement(control_element)) {
- number_of_other_input_fields++;
- } else {
- const WebInputElement* input_element =
- ToWebInputElement(&control_element);
- if (!input_element)
- continue;
-
- if (input_element->IsTextField()) {
- if (input_element->IsPasswordFieldForAutofill()) {
- ++number_of_password_input_fields;
- passwords.push_back(*input_element);
- } else {
- ++number_of_text_input_fields;
- found_captcha = found_captcha || IsCaptchaInput(*input_element);
- }
- } else { // Non-text fields.
- if (input_element->IsCheckbox())
- ++number_of_checkbox_input_fields;
- else if (!IsSubmitElement(*input_element))
- ++number_of_other_input_fields;
- }
- }
- }
-
- if (number_of_password_input_fields == 0 ||
- number_of_password_input_fields > 3)
- return false;
-
- if ((number_of_text_input_fields - found_captcha >=
- MINIMAL_NUMBER_OF_TEXT_FIELDS ||
- number_of_password_input_fields >= MINIMAL_NUMBER_OF_PASSWORD_FIELDS ||
- number_of_checkbox_input_fields >= MINIMAL_NUMBER_OF_CHECKBOX_FIELDS ||
- number_of_other_input_fields >= MINIMAL_NUMBER_OF_OTHER_FIELDS) ||
- (found_signup_text_features && !found_signin_text_features)) {
- WebInputElement password_creation_field;
-
- // TODO(crbug.com/618309): Improve local classifier to distinguish password
- // creation and password usage fields on the change password forms.
- if (passwords.size() == 3)
- password_creation_field = passwords[1];
- else
- password_creation_field = passwords[0];
-
- *generation_field = password_creation_field.NameForAutofill().Utf16();
- return true;
- }
- return false;
-}
-}
diff --git a/chromium/components/autofill/content/renderer/form_classifier.h b/chromium/components/autofill/content/renderer/form_classifier.h
deleted file mode 100644
index 9de893adb86..00000000000
--- a/chromium/components/autofill/content/renderer/form_classifier.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 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_FORM_CLASSIFIER_H_
-#define COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
-
-#include "third_party/blink/public/web/web_form_element.h"
-
-namespace autofill {
-
-// Checks if |form| is eligible for password generation. If yes, sets the name
-// of the generation field to |generation_field| and returns true. Otherwise,
-// returns false (w/o any changes of |generation_field|).
-bool ClassifyFormAndFindGenerationField(const blink::WebFormElement& form,
- base::string16* generation_field);
-}
-
-#endif // COMPONENTS_AUTOFILL_CONTENT_RENDERER_FORM_CLASSIFIER_H_
diff --git a/chromium/components/autofill/content/renderer/form_tracker.h b/chromium/components/autofill/content/renderer/form_tracker.h
index 8ae1d54dbf3..19a0a41555d 100644
--- a/chromium/components/autofill/content/renderer/form_tracker.h
+++ b/chromium/components/autofill/content/renderer/form_tracker.h
@@ -112,7 +112,7 @@ class FormTracker : public content::RenderFrameObserver {
void ResetLastInteractedElements();
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
bool ignore_control_changes_ = false;
bool user_gesture_required_ = true;
blink::WebFormElement last_interacted_form_;
diff --git a/chromium/components/autofill/content/renderer/html_based_username_detector.cc b/chromium/components/autofill/content/renderer/html_based_username_detector.cc
index 350bfc6e824..c681e5c2c29 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector.cc
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector.cc
@@ -10,6 +10,7 @@
#include "base/containers/flat_set.h"
#include "base/i18n/case_conversion.h"
#include "base/macros.h"
+#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
@@ -209,14 +210,10 @@ void RemoveFieldsWithNegativeWords(
kNegativeLatin, kNegativeLatinSize, kNegativeNonLatin,
kNegativeNonLatinSize};
- possible_usernames_data->erase(
- std::remove_if(possible_usernames_data->begin(),
- possible_usernames_data->end(),
- [](const UsernameFieldData& possible_username) {
- return ContainsWordFromCategory(possible_username,
- kNegativeCategory);
- }),
- possible_usernames_data->end());
+ base::EraseIf(
+ *possible_usernames_data, [](const UsernameFieldData& possible_username) {
+ return ContainsWordFromCategory(possible_username, kNegativeCategory);
+ });
}
// Check if any word from the given category (|category|) appears in fields from
@@ -240,12 +237,9 @@ void FindWordsFromCategoryInForm(
}
}
- if (fields_found > 0 && fields_found <= 2) {
- if (std::find(username_predictions->begin(), username_predictions->end(),
- chosen_field) == username_predictions->end()) {
+ if (fields_found > 0 && fields_found <= 2)
+ if (!base::ContainsValue(*username_predictions, chosen_field))
username_predictions->push_back(chosen_field);
- }
- }
}
// Find username elements if there is no cached result for the given form and
diff --git a/chromium/components/autofill/content/renderer/page_passwords_analyser.cc b/chromium/components/autofill/content/renderer/page_passwords_analyser.cc
index c94d0c35b35..1bcc3d84849 100644
--- a/chromium/components/autofill/content/renderer/page_passwords_analyser.cc
+++ b/chromium/components/autofill/content/renderer/page_passwords_analyser.cc
@@ -197,9 +197,8 @@ std::vector<FormInputCollection> ExtractFormsForAnalysis(
// to be username or password fields.
if (input.TagName() == "INPUT" &&
(!input.HasAttribute("type") ||
- std::find(std::begin(kTypeAttributes), std::end(kTypeAttributes),
- input.GetAttribute("type").Utf8()) !=
- std::end(kTypeAttributes))) {
+ base::ContainsValue(kTypeAttributes,
+ input.GetAttribute("type").Utf8()))) {
form_input_collections.back().AddInput(input);
inputs_with_forms.insert(input);
}
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index 900a507d742..cfe77748b73 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -56,10 +56,19 @@
#include "ui/events/keycodes/keyboard_codes.h"
#include "url/gurl.h"
+using blink::ToWebInputElement;
using blink::WebAutofillState;
using blink::WebDocument;
-using blink::WebInputElement;
+using blink::WebElement;
+using blink::WebElementCollection;
+using blink::WebFormElement;
using blink::WebFormControlElement;
+using blink::WebFrame;
+using blink::WebInputElement;
+using blink::WebLocalFrame;
+using blink::WebString;
+using blink::WebVector;
+using blink::WebView;
namespace autofill {
namespace {
@@ -70,8 +79,13 @@ const size_t kMaximumTextSizeForAutocomplete = 1000;
const char kDummyUsernameField[] = "anonymous_username";
const char kDummyPasswordField[] = "anonymous_password";
+// Names of HTML attributes to show form and field signatures for debugging.
+const char kDebugAttributeForFormSignature[] = "form_signature";
+const char kDebugAttributeForFieldSignature[] = "field_signature";
+const char kDebugAttributeForParserAnnotations[] = "pm_parser_annotation";
+
// Maps element names to the actual elements to simplify form filling.
-typedef std::map<base::string16, blink::WebInputElement> FormInputElementMap;
+typedef std::map<base::string16, WebInputElement> FormInputElementMap;
// Use the shorter name when referencing SavePasswordProgressLogger::StringID
// values to spare line breaks. The code provides enough context for that
@@ -166,13 +180,13 @@ bool IsFieldPasswordField(const FormFieldData& field) {
// either |autocomplete='current-password'| or |autocomplete='new-password'|
// attribute.
bool HasPasswordWithAutocompleteAttribute(
- const std::vector<blink::WebFormControlElement>& control_elements) {
- for (const blink::WebFormControlElement& control_element : control_elements) {
+ const std::vector<WebFormControlElement>& control_elements) {
+ for (const WebFormControlElement& control_element : control_elements) {
if (!control_element.HasHTMLTagName("input"))
continue;
- const blink::WebInputElement input_element =
- control_element.ToConst<blink::WebInputElement>();
+ const WebInputElement input_element =
+ control_element.ToConst<WebInputElement>();
const AutocompleteFlag flag = AutocompleteFlagForElement(input_element);
if (input_element.IsPasswordFieldForAutofill() &&
(flag == AutocompleteFlag::CURRENT_PASSWORD ||
@@ -195,7 +209,7 @@ base::string16 FieldName(const FormFieldData& field,
: field.name;
}
-bool IsUnownedPasswordFormVisible(const blink::WebInputElement& input_element) {
+bool IsUnownedPasswordFormVisible(const WebInputElement& input_element) {
return !input_element.IsNull() &&
form_util::IsWebElementVisible(input_element);
}
@@ -205,7 +219,7 @@ bool IsUnownedPasswordFormVisible(const blink::WebInputElement& input_element) {
// |true|. Otherwise clears the references from each |HTMLInputElement| from
// |result| and returns |false|.
bool FindFormInputElement(
- const std::vector<blink::WebFormControlElement>& control_elements,
+ const std::vector<WebFormControlElement>& control_elements,
const FormFieldData& field,
bool ambiguous_or_empty_names,
FormInputElementMap* result) {
@@ -218,7 +232,7 @@ bool FindFormInputElement(
does_password_field_has_ambigous_or_empty_name &&
HasPasswordWithAutocompleteAttribute(control_elements);
base::string16 field_name = FieldName(field, ambiguous_or_empty_names);
- for (const blink::WebFormControlElement& control_element : control_elements) {
+ for (const WebFormControlElement& control_element : control_elements) {
if (!ambiguous_or_empty_names &&
control_element.NameForAutofill().Utf16() != field_name) {
continue;
@@ -229,8 +243,8 @@ bool FindFormInputElement(
// Only fill saved passwords into password fields and usernames into text
// fields.
- const blink::WebInputElement input_element =
- control_element.ToConst<blink::WebInputElement>();
+ const WebInputElement input_element =
+ control_element.ToConst<WebInputElement>();
if (!input_element.IsTextField() ||
input_element.IsPasswordFieldForAutofill() != is_password_field)
continue;
@@ -280,7 +294,7 @@ bool FindFormInputElement(
// Helper to search through |control_elements| for the specified input elements
// in |data|, and add results to |result|.
bool FindFormInputElements(
- const std::vector<blink::WebFormControlElement>& control_elements,
+ const std::vector<WebFormControlElement>& control_elements,
const PasswordFormFillData& data,
bool ambiguous_or_empty_names,
FormInputElementMap* result) {
@@ -298,23 +312,23 @@ void FindFormElements(content::RenderFrame* render_frame,
FormElementsList* results) {
DCHECK(results);
- blink::WebDocument doc = render_frame->GetWebFrame()->GetDocument();
+ WebDocument doc = render_frame->GetWebFrame()->GetDocument();
if (GetSignOnRealm(data.origin) !=
GetSignOnRealm(form_util::GetCanonicalOriginForDocument(doc)))
return;
- blink::WebVector<blink::WebFormElement> forms;
+ WebVector<WebFormElement> forms;
doc.Forms(forms);
for (size_t i = 0; i < forms.size(); ++i) {
- blink::WebFormElement fe = forms[i];
+ WebFormElement fe = forms[i];
// Action URL must match.
if (data.action != form_util::GetCanonicalActionForForm(fe))
continue;
- std::vector<blink::WebFormControlElement> control_elements =
+ std::vector<WebFormControlElement> control_elements =
form_util::ExtractAutofillableElementsInForm(fe);
FormInputElementMap cur_map;
if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
@@ -326,7 +340,7 @@ void FindFormElements(content::RenderFrame* render_frame,
if (data.action != data.origin)
return;
- std::vector<blink::WebFormControlElement> control_elements =
+ std::vector<WebFormControlElement> control_elements =
form_util::GetUnownedAutofillableFormFieldElements(doc.All(), nullptr);
FormInputElementMap unowned_elements_map;
if (FindFormInputElements(control_elements, data, ambiguous_or_empty_names,
@@ -334,7 +348,7 @@ void FindFormElements(content::RenderFrame* render_frame,
results->push_back(unowned_elements_map);
}
-bool IsElementEditable(const blink::WebInputElement& element) {
+bool IsElementEditable(const WebInputElement& element) {
return element.IsEnabled() && !element.IsReadOnly();
}
@@ -348,7 +362,7 @@ bool DoUsernamesMatch(const base::string16& potential_suggestion,
}
// Returns whether the given |element| is editable.
-bool IsElementAutocompletable(const blink::WebInputElement& element) {
+bool IsElementAutocompletable(const WebInputElement& element) {
return IsElementEditable(element);
}
@@ -358,7 +372,7 @@ bool IsElementAutocompletable(const blink::WebInputElement& element) {
// |username_element| is user-defined (i.e., non-empty and non-autofilled), then
// this function returns false. This is a precaution, to not override the field
// if it has been classified as username by accident.
-bool IsUsernameAmendable(const blink::WebInputElement& username_element,
+bool IsUsernameAmendable(const WebInputElement& username_element,
bool is_password_field_selected) {
return !username_element.IsNull() &&
IsElementAutocompletable(username_element) &&
@@ -369,7 +383,7 @@ bool IsUsernameAmendable(const blink::WebInputElement& username_element,
// Log a message including the name, method and action of |form|.
void LogHTMLForm(SavePasswordProgressLogger* logger,
SavePasswordProgressLogger::StringID message_id,
- const blink::WebFormElement& form) {
+ const WebFormElement& form) {
logger->LogHTMLForm(message_id, form.GetName().Utf8(),
GURL(form.Action().Utf8()));
}
@@ -400,38 +414,6 @@ bool CanShowSuggestion(const PasswordFormFillData& fill_data,
return false;
}
-// Updates the value (i.e. the pair of elements's value |value| and field
-// properties |added_flags|) associated with the key |element| in
-// |field_value_and_properties_map|.
-// Flags in |added_flags| are added with bitwise OR operation.
-// If |value| is null, the value is neither updated nor added.
-// If |*value| is empty, USER_TYPED and AUTOFILLED should be cleared.
-void UpdateFieldValueAndPropertiesMaskMap(
- const blink::WebFormControlElement& element,
- const base::string16* value,
- FieldPropertiesMask added_flags,
- FieldValueAndPropertiesMaskMap* field_value_and_properties_map) {
- FieldValueAndPropertiesMaskMap::iterator it =
- field_value_and_properties_map->find(
- element.UniqueRendererFormControlId());
- if (it != field_value_and_properties_map->end()) {
- if (value)
- it->second.first.reset(new base::string16(*value));
- it->second.second |= added_flags;
- } else {
- (*field_value_and_properties_map)[element.UniqueRendererFormControlId()] =
- std::make_pair(
- value ? std::make_unique<base::string16>(*value) : nullptr,
- added_flags);
- }
- // Reset USER_TYPED and AUTOFILLED flags if the value is empty.
- if (value && value->empty()) {
- (*field_value_and_properties_map)[element.UniqueRendererFormControlId()]
- .second &=
- ~(FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED);
- }
-}
-
// This function attempts to find the matching credentials for the
// |current_username| by scanning |fill_data|. The result is written in
// |username| and |password| parameters.
@@ -509,73 +491,95 @@ bool IsPublicSuffixDomainMatch(const std::string& url1,
}
// Helper function that calculates form signature for |password_form| and
-// returns it as blink::WebString.
-blink::WebString GetFormSignatureAsWebString(
- const PasswordForm& password_form) {
- return blink::WebString::FromUTF8(
+// returns it as WebString.
+WebString GetFormSignatureAsWebString(const PasswordForm& password_form) {
+ return WebString::FromUTF8(
base::NumberToString(CalculateFormSignature(password_form.form_data)));
}
+// Add parser annotations saved in |password_form| to |element|.
+void AddParserAnnotations(PasswordForm* password_form,
+ blink::WebFormControlElement* element) {
+ base::string16 element_name = element->NameForAutofill().Utf16();
+ std::string attribute_value;
+ if (password_form->username_element == element_name) {
+ attribute_value = "username_element";
+ } else if (password_form->password_element == element_name) {
+ attribute_value = "password_element";
+ } else if (password_form->new_password_element == element_name) {
+ attribute_value = "new_password_element";
+ } else if (password_form->confirmation_password_element == element_name) {
+ attribute_value = "confirmation_password_element";
+ }
+ element->SetAttribute(
+ blink::WebString::FromASCII(kDebugAttributeForParserAnnotations),
+ attribute_value.empty() ? blink::WebString()
+ : blink::WebString::FromASCII(attribute_value));
+}
+
// Annotate |fields| with field signatures and form signature as HTML
// attributes.
void AnnotateFieldsWithSignatures(
std::vector<blink::WebFormControlElement>* fields,
- const blink::WebString& form_signature) {
+ const blink::WebString& form_signature,
+ PasswordForm* password_form) {
for (blink::WebFormControlElement& control_element : *fields) {
FieldSignature field_signature = CalculateFieldSignatureByNameAndType(
control_element.NameForAutofill().Utf16(),
control_element.FormControlTypeForAutofill().Utf8());
control_element.SetAttribute(
- blink::WebString::FromASCII(kDebugAttributeForFieldSignature),
- blink::WebString::FromUTF8(base::NumberToString(field_signature)));
+ WebString::FromASCII(kDebugAttributeForFieldSignature),
+ WebString::FromUTF8(base::NumberToString(field_signature)));
control_element.SetAttribute(
blink::WebString::FromASCII(kDebugAttributeForFormSignature),
form_signature);
+ if (password_form)
+ AddParserAnnotations(password_form, &control_element);
}
}
// Annotate |forms| and all fields in the |frame| with form and field signatures
// as HTML attributes.
-void AnnotateFormsAndFieldsWithSignatures(
- blink::WebLocalFrame* frame,
- blink::WebVector<blink::WebFormElement>* forms) {
- for (blink::WebFormElement& form : *forms) {
+void AnnotateFormsAndFieldsWithSignatures(WebLocalFrame* frame,
+ WebVector<WebFormElement>* forms) {
+ for (WebFormElement& form : *forms) {
std::unique_ptr<PasswordForm> password_form(
CreatePasswordFormFromWebForm(form, nullptr, nullptr, nullptr));
- blink::WebString form_signature;
+ WebString form_signature;
if (password_form) {
form_signature = GetFormSignatureAsWebString(*password_form);
- form.SetAttribute(
- blink::WebString::FromASCII(kDebugAttributeForFormSignature),
- form_signature);
+ form.SetAttribute(WebString::FromASCII(kDebugAttributeForFormSignature),
+ form_signature);
}
- std::vector<blink::WebFormControlElement> form_fields =
+ std::vector<WebFormControlElement> form_fields =
form_util::ExtractAutofillableElementsInForm(form);
- AnnotateFieldsWithSignatures(&form_fields, form_signature);
+ AnnotateFieldsWithSignatures(&form_fields, form_signature,
+ password_form ? password_form.get() : nullptr);
}
- std::vector<blink::WebFormControlElement> unowned_elements =
+ std::vector<WebFormControlElement> unowned_elements =
form_util::GetUnownedAutofillableFormFieldElements(
frame->GetDocument().All(), nullptr);
std::unique_ptr<PasswordForm> password_form(
CreatePasswordFormFromUnownedInputElements(*frame, nullptr, nullptr,
nullptr));
- blink::WebString form_signature;
+ WebString form_signature;
if (password_form)
form_signature = GetFormSignatureAsWebString(*password_form);
- AnnotateFieldsWithSignatures(&unowned_elements, form_signature);
+ AnnotateFieldsWithSignatures(&unowned_elements, form_signature,
+ password_form ? password_form.get() : nullptr);
}
// Returns true iff there is a password field in |frame|.
-bool HasPasswordField(const blink::WebLocalFrame& frame) {
- CR_DEFINE_STATIC_LOCAL(blink::WebString, kPassword, ("password"));
+bool HasPasswordField(const WebLocalFrame& frame) {
+ CR_DEFINE_STATIC_LOCAL(WebString, kPassword, ("password"));
- const blink::WebElementCollection elements = frame.GetDocument().All();
- for (blink::WebElement element = elements.FirstItem(); !element.IsNull();
+ const WebElementCollection elements = frame.GetDocument().All();
+ for (WebElement element = elements.FirstItem(); !element.IsNull();
element = elements.NextItem()) {
if (element.IsFormControlElement()) {
- const blink::WebFormControlElement& control =
- element.To<blink::WebFormControlElement>();
+ const WebFormControlElement& control =
+ element.To<WebFormControlElement>();
if (control.FormControlTypeForAutofill() == kPassword)
return true;
}
@@ -586,28 +590,28 @@ bool HasPasswordField(const blink::WebLocalFrame& frame) {
// Returns the closest visible autocompletable non-password text element
// preceding the |password_element| either in a form, if it belongs to one, or
// in the |frame|.
-blink::WebInputElement FindUsernameElementPrecedingPasswordElement(
- blink::WebLocalFrame* frame,
- const blink::WebInputElement& password_element) {
+WebInputElement FindUsernameElementPrecedingPasswordElement(
+ WebLocalFrame* frame,
+ const WebInputElement& password_element) {
DCHECK(!password_element.IsNull());
- std::vector<blink::WebFormControlElement> elements;
+ std::vector<WebFormControlElement> elements;
if (password_element.Form().IsNull()) {
elements = form_util::GetUnownedAutofillableFormFieldElements(
frame->GetDocument().All(), nullptr);
} else {
- blink::WebVector<blink::WebFormControlElement> web_control_elements;
+ WebVector<WebFormControlElement> web_control_elements;
password_element.Form().GetFormControlElements(web_control_elements);
elements.assign(web_control_elements.begin(), web_control_elements.end());
}
auto iter = std::find(elements.begin(), elements.end(), password_element);
if (iter == elements.end())
- return blink::WebInputElement();
+ return WebInputElement();
for (auto begin = elements.begin(); iter != begin;) {
--iter;
- const blink::WebInputElement* input = blink::ToWebInputElement(&*iter);
+ const WebInputElement* input = ToWebInputElement(&*iter);
if (input && input->IsTextField() && !input->IsPasswordFieldForAutofill() &&
IsElementAutocompletable(*input) &&
form_util::IsWebElementVisible(*input)) {
@@ -615,7 +619,7 @@ blink::WebInputElement FindUsernameElementPrecedingPasswordElement(
}
}
- return blink::WebInputElement();
+ return WebInputElement();
}
PasswordForm::SubmissionIndicatorEvent ToSubmissionIndicatorEvent(
@@ -637,7 +641,7 @@ PasswordForm::SubmissionIndicatorEvent ToSubmissionIndicatorEvent(
WebInputElement ConvertToWebInput(const WebFormControlElement& element) {
if (element.IsNull())
return WebInputElement();
- const WebInputElement* input = blink::ToWebInputElement(&element);
+ const WebInputElement* input = ToWebInputElement(&element);
return input ? *input : WebInputElement();
}
@@ -646,12 +650,9 @@ WebInputElement ConvertToWebInput(const WebFormControlElement& element) {
////////////////////////////////////////////////////////////////////////////////
// PasswordAutofillAgent, public:
-const char kDebugAttributeForFormSignature[] = "form_signature";
-const char kDebugAttributeForFieldSignature[] = "field_signature";
-
PasswordAutofillAgent::PasswordAutofillAgent(
content::RenderFrame* render_frame,
- service_manager::BinderRegistry* registry)
+ blink::AssociatedInterfaceRegistry* registry)
: content::RenderFrameObserver(render_frame),
last_supplied_password_info_iter_(web_input_to_password_info_.end()),
logging_state_active_(false),
@@ -659,6 +660,7 @@ PasswordAutofillAgent::PasswordAutofillAgent(
password_autofill_state_(WebAutofillState::kNotFilled),
sent_request_to_store_(false),
checked_safe_browsing_reputation_(false),
+ focus_state_notifier_(this),
binding_(this) {
registry->AddInterface(
base::Bind(&PasswordAutofillAgent::BindRequest, base::Unretained(this)));
@@ -671,7 +673,7 @@ PasswordAutofillAgent::~PasswordAutofillAgent() {
}
void PasswordAutofillAgent::BindRequest(
- mojom::PasswordAutofillAgentRequest request) {
+ mojom::PasswordAutofillAgentAssociatedRequest request) {
binding_.Bind(std::move(request));
}
@@ -688,6 +690,26 @@ void PasswordAutofillAgent::SetPasswordGenerationAgent(
password_generation_agent_ = generation_agent;
}
+PasswordAutofillAgent::FocusStateNotifier::FocusStateNotifier(
+ PasswordAutofillAgent* agent)
+ : was_fillable_(false), was_password_field_(false), agent_(agent) {}
+
+PasswordAutofillAgent::FocusStateNotifier::~FocusStateNotifier() = default;
+
+void PasswordAutofillAgent::FocusStateNotifier::FocusedInputChanged(
+ bool is_fillable,
+ bool is_password_field) {
+ // Forward the request, if the field is valid or the request is different.
+ if (!is_fillable && !was_fillable_ && !is_password_field &&
+ !was_password_field_) {
+ return; // A previous request already reported this exact state.
+ }
+ was_fillable_ = is_fillable;
+ was_password_field_ = is_password_field;
+ agent_->GetPasswordManagerDriver()->FocusedInputChanged(is_fillable,
+ is_password_field);
+}
+
PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper()
: was_user_gesture_seen_(false) {
}
@@ -696,7 +718,7 @@ PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() {
}
void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement(
- blink::WebInputElement* element) {
+ WebInputElement* element) {
if (was_user_gesture_seen_)
ShowValue(element);
else
@@ -709,7 +731,7 @@ void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() {
was_user_gesture_seen_ = true;
- for (blink::WebInputElement& element : elements_)
+ for (WebInputElement& element : elements_)
ShowValue(&element);
elements_.clear();
@@ -721,7 +743,7 @@ void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() {
}
void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
- blink::WebInputElement* element) {
+ WebInputElement* element) {
if (!element->IsNull() && !element->SuggestedValue().IsEmpty()) {
element->SetAutofillValue(element->SuggestedValue());
element->SetAutofillState(WebAutofillState::kAutofilled);
@@ -729,9 +751,9 @@ void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
}
bool PasswordAutofillAgent::TextDidChangeInTextField(
- const blink::WebInputElement& element) {
+ const WebInputElement& element) {
// TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
- blink::WebInputElement mutable_element = element; // We need a non-const.
+ WebInputElement mutable_element = element; // We need a non-const.
mutable_element.SetAutofillState(WebAutofillState::kNotFilled);
WebInputToPasswordInfoMap::iterator iter =
@@ -745,15 +767,14 @@ bool PasswordAutofillAgent::TextDidChangeInTextField(
}
void PasswordAutofillAgent::UpdateStateForTextChange(
- const blink::WebInputElement& element) {
+ const WebInputElement& element) {
// TODO(vabr): Get a mutable argument instead. http://crbug.com/397083
- blink::WebInputElement mutable_element = element; // We need a non-const.
+ WebInputElement mutable_element = element; // We need a non-const.
if (element.IsTextField()) {
const base::string16 element_value = element.Value().Utf16();
- UpdateFieldValueAndPropertiesMaskMap(element, &element_value,
- FieldPropertiesFlags::USER_TYPED,
- &field_value_and_properties_map_);
+ field_data_manager_.UpdateFieldDataMap(element, element_value,
+ FieldPropertiesFlags::USER_TYPED);
}
ProvisionallySavePassword(element.Form(), element, RESTRICTION_NONE);
@@ -773,16 +794,16 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
}
bool PasswordAutofillAgent::FillSuggestion(
- const blink::WebFormControlElement& control_element,
+ const WebFormControlElement& control_element,
const base::string16& username,
const base::string16& password) {
// The element in context of the suggestion popup.
- const blink::WebInputElement* element = ToWebInputElement(&control_element);
+ const WebInputElement* element = ToWebInputElement(&control_element);
if (!element)
return false;
- blink::WebInputElement username_element;
- blink::WebInputElement password_element;
+ WebInputElement username_element;
+ WebInputElement password_element;
PasswordInfo* password_info = nullptr;
if (!FindPasswordInfoForElement(*element, &username_element,
@@ -810,7 +831,7 @@ bool PasswordAutofillAgent::FillSuggestion(
FillPasswordFieldAndSave(&password_element, password);
- blink::WebInputElement mutable_filled_element = *element;
+ WebInputElement mutable_filled_element = *element;
mutable_filled_element.SetSelectionRange(element->Value().length(),
element->Value().length());
@@ -837,19 +858,18 @@ void PasswordAutofillAgent::FillIntoFocusedField(
std::move(callback).Run(autofill::FillingStatus::SUCCESS);
}
-void PasswordAutofillAgent::FillField(blink::WebInputElement* input,
+void PasswordAutofillAgent::FillField(WebInputElement* input,
const base::string16& credential) {
DCHECK(input);
DCHECK(!input->IsNull());
- input->SetAutofillValue(blink::WebString::FromUTF16(credential));
+ input->SetAutofillValue(WebString::FromUTF16(credential));
input->SetAutofillState(WebAutofillState::kAutofilled);
- UpdateFieldValueAndPropertiesMaskMap(
- *input, &credential, FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER,
- &field_value_and_properties_map_);
+ field_data_manager_.UpdateFieldDataMap(
+ *input, credential, FieldPropertiesFlags::AUTOFILLED_ON_USER_TRIGGER);
}
void PasswordAutofillAgent::FillPasswordFieldAndSave(
- blink::WebInputElement* password_input,
+ WebInputElement* password_input,
const base::string16& credential) {
DCHECK(password_input);
DCHECK(password_input->IsPasswordFieldForAutofill());
@@ -859,16 +879,16 @@ void PasswordAutofillAgent::FillPasswordFieldAndSave(
}
bool PasswordAutofillAgent::PreviewSuggestion(
- const blink::WebFormControlElement& control_element,
- const blink::WebString& username,
- const blink::WebString& password) {
+ const WebFormControlElement& control_element,
+ const WebString& username,
+ const WebString& password) {
// The element in context of the suggestion popup.
- const blink::WebInputElement* element = ToWebInputElement(&control_element);
+ const WebInputElement* element = ToWebInputElement(&control_element);
if (!element)
return false;
- blink::WebInputElement username_element;
- blink::WebInputElement password_element;
+ WebInputElement username_element;
+ WebInputElement password_element;
PasswordInfo* password_info;
if (!FindPasswordInfoForElement(*element, &username_element,
@@ -896,13 +916,13 @@ bool PasswordAutofillAgent::PreviewSuggestion(
}
bool PasswordAutofillAgent::DidClearAutofillSelection(
- const blink::WebFormControlElement& control_element) {
- const blink::WebInputElement* element = ToWebInputElement(&control_element);
+ const WebFormControlElement& control_element) {
+ const WebInputElement* element = ToWebInputElement(&control_element);
if (!element)
return false;
- blink::WebInputElement username_element;
- blink::WebInputElement password_element;
+ WebInputElement username_element;
+ WebInputElement password_element;
PasswordInfo* password_info;
if (!FindPasswordInfoForElement(*element, &username_element,
@@ -915,9 +935,9 @@ bool PasswordAutofillAgent::DidClearAutofillSelection(
}
bool PasswordAutofillAgent::FindPasswordInfoForElement(
- const blink::WebInputElement& element,
- blink::WebInputElement* username_element,
- blink::WebInputElement* password_element,
+ const WebInputElement& element,
+ WebInputElement* username_element,
+ WebInputElement* password_element,
PasswordInfo** password_info) {
DCHECK(username_element && password_element && password_info);
username_element->Reset();
@@ -972,7 +992,7 @@ bool PasswordAutofillAgent::FindPasswordInfoForElement(
}
bool PasswordAutofillAgent::IsUsernameOrPasswordField(
- const blink::WebInputElement& element) {
+ const WebInputElement& element) {
// Note: A site may use a Password field to collect a CVV or a Credit Card
// number, but showing a slightly misleading warning here is better than
// showing no warning at all.
@@ -1000,18 +1020,17 @@ bool PasswordAutofillAgent::IsUsernameOrPasswordField(
return (password_form->username_element == element.NameForAutofill().Utf16());
}
-bool PasswordAutofillAgent::ShowSuggestions(
- const blink::WebInputElement& element,
- bool show_all,
- bool generation_popup_showing) {
- blink::WebInputElement username_element;
- blink::WebInputElement password_element;
+bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
+ bool show_all,
+ bool generation_popup_showing) {
+ WebInputElement username_element;
+ WebInputElement password_element;
PasswordInfo* password_info;
if (!FindPasswordInfoForElement(element, &username_element, &password_element,
&password_info)) {
if (IsUsernameOrPasswordField(element)) {
- blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+ WebLocalFrame* frame = render_frame()->GetWebFrame();
GURL frame_url = GURL(frame->GetDocument().Url());
#if defined(SAFE_BROWSING_DB_LOCAL)
if (!checked_safe_browsing_reputation_) {
@@ -1071,8 +1090,10 @@ bool PasswordAutofillAgent::ShowSuggestions(
bool PasswordAutofillAgent::FrameCanAccessPasswordManager() {
// about:blank or about:srcdoc frames should not be allowed to use password
// manager. See https://crbug.com/756587.
- blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
- if (frame->GetDocument().Url().ProtocolIs(url::kAboutScheme))
+ WebLocalFrame* frame = render_frame()->GetWebFrame();
+ blink::WebURL url = frame->GetDocument().Url();
+ if (url.ProtocolIs(url::kAboutScheme) || url.ProtocolIs(url::kBlobScheme) ||
+ url.ProtocolIs(url::kFileSystemScheme))
return false;
return frame->GetSecurityOrigin().CanAccessPasswordManager();
}
@@ -1090,7 +1111,7 @@ void PasswordAutofillAgent::FireSubmissionIfFormDisappear(
// Prompt to save only if the form is now gone, either invisible or
// removed from the DOM.
- blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+ WebLocalFrame* frame = render_frame()->GetWebFrame();
const auto& password_form = provisionally_saved_form_.password_form();
// TODO(crbug.com/720347): This method could be called often and checking form
// visibility could be expesive. Add performance metrics for this.
@@ -1124,7 +1145,7 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
logger->LogBoolean(Logger::STRING_ONLY_VISIBLE, only_visible);
}
- blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+ WebLocalFrame* frame = render_frame()->GetWebFrame();
// Make sure that this security origin is allowed to use password manager.
blink::WebSecurityOrigin origin = frame->GetDocument().GetSecurityOrigin();
@@ -1146,7 +1167,7 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
return;
}
- blink::WebVector<blink::WebFormElement> forms;
+ WebVector<WebFormElement> forms;
frame->GetDocument().Forms(forms);
if (IsShowAutofillSignaturesEnabled())
@@ -1155,7 +1176,7 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
logger->LogNumber(Logger::STRING_NUMBER_OF_ALL_FORMS, forms.size());
std::vector<PasswordForm> password_forms;
- for (const blink::WebFormElement& form : forms) {
+ for (const WebFormElement& form : forms) {
if (only_visible) {
bool is_form_visible = form_util::AreFormContentsVisible(form);
if (logger) {
@@ -1184,7 +1205,7 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
// password submission.
bool add_unowned_inputs = true;
if (only_visible) {
- std::vector<blink::WebFormControlElement> control_elements =
+ std::vector<WebFormControlElement> control_elements =
form_util::GetUnownedAutofillableFormFieldElements(
frame->GetDocument().All(), nullptr);
add_unowned_inputs =
@@ -1210,7 +1231,7 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
// Send the PasswordFormsRendered message regardless of whether
// |password_forms| is empty. The empty |password_forms| are a possible
// signal to the browser that a pending login attempt succeeded.
- blink::WebFrame* main_frame = render_frame()->GetWebFrame()->Top();
+ WebFrame* main_frame = render_frame()->GetWebFrame()->Top();
bool did_stop_loading = !main_frame || !main_frame->IsLoading();
GetPasswordManagerDriver()->PasswordFormsRendered(password_forms,
did_stop_loading);
@@ -1282,8 +1303,7 @@ void PasswordAutofillAgent::OnFrameDetached() {
FrameClosing();
}
-void PasswordAutofillAgent::OnWillSubmitForm(
- const blink::WebFormElement& form) {
+void PasswordAutofillAgent::OnWillSubmitForm(const WebFormElement& form) {
std::unique_ptr<RendererSavePasswordProgressLogger> logger;
if (logging_state_active_) {
logger.reset(new RendererSavePasswordProgressLogger(
@@ -1346,16 +1366,16 @@ void PasswordAutofillAgent::FocusedNodeChanged(const blink::WebNode& node) {
focused_input_element_.Reset();
if (node.IsNull() || // |node| is null <==> focus outside of frame.
- !node.IsElementNode()) { // Not a valid blink::WebElement.
- GetPasswordManagerDriver()->FocusedInputChanged(
+ !node.IsElementNode()) { // Not a valid WebElement.
+ focus_state_notifier_.FocusedInputChanged(
/*is_fillable=*/false, /*is_password_field=*/false);
return;
}
- blink::WebElement web_element = node.ToConst<blink::WebElement>();
+ WebElement web_element = node.ToConst<WebElement>();
const WebInputElement* input = ToWebInputElement(&web_element);
if (!input) {
- GetPasswordManagerDriver()->FocusedInputChanged(
+ focus_state_notifier_.FocusedInputChanged(
/*is_fillable=*/false, /*is_password_field=*/false);
return; // If the node isn't an element, don't even try to convert.
}
@@ -1365,7 +1385,7 @@ void PasswordAutofillAgent::FocusedNodeChanged(const blink::WebNode& node) {
focused_input_element_ = *input;
is_password = focused_input_element_.IsPasswordFieldForAutofill();
}
- GetPasswordManagerDriver()->FocusedInputChanged(is_fillable, is_password);
+ focus_state_notifier_.FocusedInputChanged(is_fillable, is_password);
}
void PasswordAutofillAgent::OnDestruct() {
@@ -1382,7 +1402,7 @@ void PasswordAutofillAgent::DidStartProvisionalLoad(
logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD);
}
- blink::WebLocalFrame* navigated_frame = render_frame()->GetWebFrame();
+ WebLocalFrame* navigated_frame = render_frame()->GetWebFrame();
if (navigated_frame->Parent()) {
if (logger)
logger->LogMessage(Logger::STRING_FRAME_NOT_MAIN_FRAME);
@@ -1443,7 +1463,7 @@ void PasswordAutofillAgent::FillUsingRendererIDs(
StoreDataForFillOnAccountSelect(key, form_data, username_element,
password_element);
FillFormOnPasswordReceived(form_data, username_element, password_element,
- &field_value_and_properties_map_, logger.get());
+ &field_data_manager_, logger.get());
}
// mojom::PasswordAutofillAgent:
@@ -1455,7 +1475,7 @@ void PasswordAutofillAgent::FillPasswordForm(
return;
}
- std::vector<blink::WebInputElement> elements;
+ std::vector<WebInputElement> elements;
std::unique_ptr<RendererSavePasswordProgressLogger> logger;
if (logging_state_active_) {
logger.reset(new RendererSavePasswordProgressLogger(
@@ -1470,17 +1490,15 @@ void PasswordAutofillAgent::FillPasswordForm(
return;
for (auto element : elements) {
- blink::WebInputElement username_element =
- !element.IsPasswordFieldForAutofill() ? element
- : password_to_username_[element];
- blink::WebInputElement password_element =
+ WebInputElement username_element = !element.IsPasswordFieldForAutofill()
+ ? element
+ : password_to_username_[element];
+ WebInputElement password_element =
element.IsPasswordFieldForAutofill()
? element
: web_input_to_password_info_[element].password_field;
- FillFormOnPasswordReceived(
- form_data, username_element, password_element,
- &field_value_and_properties_map_,
- logger.get());
+ FillFormOnPasswordReceived(form_data, username_element, password_element,
+ &field_data_manager_, logger.get());
}
}
@@ -1488,7 +1506,7 @@ void PasswordAutofillAgent::GetFillableElementFromFormData(
int key,
const PasswordFormFillData& form_data,
RendererSavePasswordProgressLogger* logger,
- std::vector<blink::WebInputElement>* elements) {
+ std::vector<WebInputElement>* elements) {
DCHECK(elements);
bool ambiguous_or_empty_names =
DoesFormContainAmbiguousOrEmptyNames(form_data);
@@ -1522,8 +1540,8 @@ void PasswordAutofillAgent::GetFillableElementFromFormData(
}
// Attach autocomplete listener to enable selecting alternate logins.
- blink::WebInputElement username_element;
- blink::WebInputElement password_element;
+ WebInputElement username_element;
+ WebInputElement password_element;
// Check whether the password form has a username input field.
if (!username_field_name.empty()) {
@@ -1544,7 +1562,7 @@ void PasswordAutofillAgent::GetFillableElementFromFormData(
password_element = it->second;
}
- blink::WebInputElement main_element =
+ WebInputElement main_element =
username_element.IsNull() ? password_element : username_element;
if (elements)
elements->push_back(main_element);
@@ -1558,21 +1576,20 @@ void PasswordAutofillAgent::GetFillableElementFromFormData(
void PasswordAutofillAgent::FocusedNodeHasChanged(const blink::WebNode& node) {
if (node.IsNull() || !node.IsElementNode())
return;
- const blink::WebElement web_element = node.ToConst<blink::WebElement>();
+ const WebElement web_element = node.ToConst<WebElement>();
if (!web_element.IsFormControlElement())
return;
- const blink::WebFormControlElement control_element =
- web_element.ToConst<blink::WebFormControlElement>();
- UpdateFieldValueAndPropertiesMaskMap(control_element, nullptr,
- FieldPropertiesFlags::HAD_FOCUS,
- &field_value_and_properties_map_);
+ const WebFormControlElement control_element =
+ web_element.ToConst<WebFormControlElement>();
+ field_data_manager_.UpdateFieldDataMapWithNullValue(
+ control_element, FieldPropertiesFlags::HAD_FOCUS);
}
std::unique_ptr<PasswordForm> PasswordAutofillAgent::GetPasswordFormFromWebForm(
- const blink::WebFormElement& web_form) {
- return CreatePasswordFormFromWebForm(
- web_form, &field_value_and_properties_map_, &form_predictions_,
- &username_detector_cache_);
+ const WebFormElement& web_form) {
+ return CreatePasswordFormFromWebForm(web_form, &field_data_manager_,
+ &form_predictions_,
+ &username_detector_cache_);
}
std::unique_ptr<PasswordForm>
@@ -1584,11 +1601,11 @@ PasswordAutofillAgent::GetPasswordFormFromUnownedInputElements() {
content::RenderFrame* frame = render_frame();
if (!frame)
return nullptr;
- blink::WebLocalFrame* web_frame = frame->GetWebFrame();
+ WebLocalFrame* web_frame = frame->GetWebFrame();
if (!web_frame)
return nullptr;
return CreatePasswordFormFromUnownedInputElements(
- *web_frame, &field_value_and_properties_map_, &form_predictions_,
+ *web_frame, &field_data_manager_, &form_predictions_,
&username_detector_cache_);
}
@@ -1606,10 +1623,10 @@ void PasswordAutofillAgent::FindFocusedPasswordForm(
FindFocusedPasswordFormCallback callback) {
std::unique_ptr<PasswordForm> password_form;
- blink::WebElement element =
+ WebElement element =
render_frame()->GetWebFrame()->GetDocument().FocusedElement();
if (!element.IsNull() && element.HasHTMLTagName("input")) {
- blink::WebInputElement input = element.To<blink::WebInputElement>();
+ WebInputElement input = element.To<WebInputElement>();
if (input.IsPasswordFieldForAutofill()) {
if (!input.Form().IsNull()) {
password_form = GetPasswordFormFromWebForm(input.Form());
@@ -1639,15 +1656,15 @@ void PasswordAutofillAgent::FindFocusedPasswordForm(
bool PasswordAutofillAgent::ShowSuggestionPopup(
const PasswordInfo& password_info,
- const blink::WebInputElement& user_input,
+ const WebInputElement& user_input,
bool show_all,
bool show_on_password_field) {
DCHECK(!user_input.IsNull());
- blink::WebFrame* frame = user_input.GetDocument().GetFrame();
+ WebFrame* frame = user_input.GetDocument().GetFrame();
if (!frame)
return false;
- blink::WebView* webview = frame->View();
+ WebView* webview = frame->View();
if (!webview)
return false;
@@ -1683,7 +1700,7 @@ void PasswordAutofillAgent::FrameClosing() {
password_to_username_.clear();
last_supplied_password_info_iter_ = web_input_to_password_info_.end();
provisionally_saved_form_.Reset();
- field_value_and_properties_map_.clear();
+ field_data_manager_.ClearData();
username_autofill_state_ = WebAutofillState::kNotFilled;
password_autofill_state_ = WebAutofillState::kNotFilled;
sent_request_to_store_ = false;
@@ -1696,23 +1713,22 @@ void PasswordAutofillAgent::FrameClosing() {
#endif
}
-void PasswordAutofillAgent::ClearPreview(
- blink::WebInputElement* username,
- blink::WebInputElement* password) {
+void PasswordAutofillAgent::ClearPreview(WebInputElement* username,
+ WebInputElement* password) {
if (!username->IsNull() && !username->SuggestedValue().IsEmpty()) {
- username->SetSuggestedValue(blink::WebString());
+ username->SetSuggestedValue(WebString());
username->SetAutofillState(username_autofill_state_);
username->SetSelectionRange(username_query_prefix_.length(),
username->Value().length());
}
if (!password->SuggestedValue().IsEmpty()) {
- password->SetSuggestedValue(blink::WebString());
+ password->SetSuggestedValue(WebString());
password->SetAutofillState(password_autofill_state_);
}
}
void PasswordAutofillAgent::ProvisionallySavePassword(
- const blink::WebFormElement& form,
- const blink::WebInputElement& element,
+ const WebFormElement& form,
+ const WebInputElement& element,
ProvisionallySaveRestriction restriction) {
DCHECK(!form.IsNull() || !element.IsNull());
@@ -1744,12 +1760,12 @@ void PasswordAutofillAgent::ProvisionallySavePassword(
}
bool PasswordAutofillAgent::FillUserNameAndPassword(
- blink::WebInputElement* username_element,
- blink::WebInputElement* password_element,
+ WebInputElement* username_element,
+ WebInputElement* password_element,
const PasswordFormFillData& fill_data,
bool exact_username_match,
bool username_may_use_prefilled_placeholder,
- FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ FieldDataManager* field_data_manager,
RendererSavePasswordProgressLogger* logger) {
if (logger)
logger->LogMessage(Logger::STRING_FILL_USERNAME_AND_PASSWORD_METHOD);
@@ -1816,8 +1832,7 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
IsElementAutocompletable(*username_element)) {
if (!username.empty() && (username_element->Value().IsEmpty() ||
prefilled_placeholder_username)) {
- username_element->SetSuggestedValue(
- blink::WebString::FromUTF16(username));
+ username_element->SetSuggestedValue(WebString::FromUTF16(username));
gatekeeper_.RegisterElement(username_element);
if (prefilled_placeholder_username) {
LogPrefilledUsernameFillOutcome(
@@ -1825,11 +1840,9 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
kPrefilledPlaceholderUsernameOverridden);
}
}
-
- UpdateFieldValueAndPropertiesMaskMap(
- *username_element, &username,
- FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD,
- field_value_and_properties_map);
+ field_data_manager->UpdateFieldDataMap(
+ *username_element, username,
+ FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD);
username_element->SetAutofillState(WebAutofillState::kAutofilled);
if (logger)
logger->LogElementName(Logger::STRING_USERNAME_FILLED, *username_element);
@@ -1839,11 +1852,10 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
// sure that we do not fill in the DOM with a password until we believe the
// user is intentionally interacting with the page.
if (password_element->Value().Utf16() != password)
- password_element->SetSuggestedValue(blink::WebString::FromUTF16(password));
- UpdateFieldValueAndPropertiesMaskMap(
- *password_element, &password,
- FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD,
- field_value_and_properties_map);
+ password_element->SetSuggestedValue(WebString::FromUTF16(password));
+ field_data_manager->UpdateFieldDataMap(
+ *password_element, password,
+ FieldPropertiesFlags::AUTOFILLED_ON_PAGELOAD);
ProvisionallySavePassword(password_element->Form(), *password_element,
RESTRICTION_NONE);
gatekeeper_.RegisterElement(password_element);
@@ -1865,15 +1877,14 @@ void PasswordAutofillAgent::LogPrefilledUsernameFillOutcome(
bool PasswordAutofillAgent::FillFormOnPasswordReceived(
const PasswordFormFillData& fill_data,
- blink::WebInputElement username_element,
- blink::WebInputElement password_element,
- FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ WebInputElement username_element,
+ WebInputElement password_element,
+ FieldDataManager* field_data_manager,
RendererSavePasswordProgressLogger* logger) {
// Do not fill if the password field is in a chain of iframes not having
// identical origin.
- blink::WebFrame* cur_frame = password_element.GetDocument().GetFrame();
- blink::WebString bottom_frame_origin =
- cur_frame->GetSecurityOrigin().ToString();
+ WebFrame* cur_frame = password_element.GetDocument().GetFrame();
+ WebString bottom_frame_origin = cur_frame->GetSecurityOrigin().ToString();
DCHECK(cur_frame);
@@ -1895,19 +1906,19 @@ bool PasswordAutofillAgent::FillFormOnPasswordReceived(
// match for read-only username fields.
return FillUserNameAndPassword(
&username_element, &password_element, fill_data, exact_username_match,
- fill_data.username_may_use_prefilled_placeholder,
- field_value_and_properties_map, logger);
+ fill_data.username_may_use_prefilled_placeholder, field_data_manager,
+ logger);
}
void PasswordAutofillAgent::OnProvisionallySaveForm(
- const blink::WebFormElement& form,
- const blink::WebFormControlElement& element,
+ const WebFormElement& form,
+ const WebFormControlElement& element,
ElementChangeSource source) {
// PasswordAutofillAgent isn't interested in SELECT control change.
if (source == ElementChangeSource::SELECT_CHANGED)
return;
- blink::WebInputElement input_element;
+ WebInputElement input_element;
if (!element.IsNull() && element.HasHTMLTagName("input"))
input_element = *ToWebInputElement(&element);
@@ -1936,7 +1947,7 @@ void PasswordAutofillAgent::OnProvisionallySaveForm(
RESTRICTION_NON_EMPTY_PASSWORD);
}
-void PasswordAutofillAgent::OnFormSubmitted(const blink::WebFormElement& form) {
+void PasswordAutofillAgent::OnFormSubmitted(const WebFormElement& form) {
OnWillSubmitForm(form);
}
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.h b/chromium/components/autofill/content/renderer/password_autofill_agent.h
index a284a03bb42..e25ca05d87d 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.h
@@ -7,6 +7,7 @@
#include <map>
#include <memory>
+#include <utility>
#include <vector>
#include "base/macros.h"
@@ -15,9 +16,9 @@
#include "components/autofill/content/common/autofill_agent.mojom.h"
#include "components/autofill/content/common/autofill_driver.mojom.h"
#include "components/autofill/content/renderer/autofill_agent.h"
+#include "components/autofill/content/renderer/field_data_manager.h"
#include "components/autofill/content/renderer/form_tracker.h"
#include "components/autofill/content/renderer/html_based_username_detector.h"
-#include "components/autofill/content/renderer/password_form_conversion_utils.h"
#include "components/autofill/content/renderer/provisionally_saved_password_form.h"
#include "components/autofill/core/common/form_data_predictions.h"
#include "components/autofill/core/common/password_form.h"
@@ -26,7 +27,7 @@
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_view_observer.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/web/web_input_element.h"
#if !defined(OS_ANDROID) && !defined(OS_IOS)
@@ -63,6 +64,7 @@ enum class PrefilledUsernameFillOutcome {
extern const char kDebugAttributeForFormSignature[];
extern const char kDebugAttributeForFieldSignature[];
+class FieldDataManager;
class RendererSavePasswordProgressLogger;
class PasswordGenerationAgent;
@@ -72,10 +74,10 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
public mojom::PasswordAutofillAgent {
public:
PasswordAutofillAgent(content::RenderFrame* render_frame,
- service_manager::BinderRegistry* registry);
+ blink::AssociatedInterfaceRegistry* registry);
~PasswordAutofillAgent() override;
- void BindRequest(mojom::PasswordAutofillAgentRequest request);
+ void BindRequest(mojom::PasswordAutofillAgentAssociatedRequest request);
void SetAutofillAgent(AutofillAgent* autofill_agent);
@@ -210,6 +212,25 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
using PasswordToLoginMap =
std::map<blink::WebInputElement, blink::WebInputElement>;
+ // This class ensures that the driver will only receive relevant signals by
+ // caching the parameters of the last message sent to the driver.
+ class FocusStateNotifier {
+ public:
+ // Creates a new notifier that uses the agent which owns it to access the
+ // real driver implementation.
+ explicit FocusStateNotifier(PasswordAutofillAgent* agent);
+ ~FocusStateNotifier();
+
+ void FocusedInputChanged(bool is_fillable, bool is_password_field);
+
+ private:
+ bool was_fillable_;
+ bool was_password_field_;
+ PasswordAutofillAgent* agent_;
+
+ DISALLOW_COPY_AND_ASSIGN(FocusStateNotifier);
+ };
+
// This class keeps track of autofilled password input elements and makes sure
// the autofilled password value is not accessible to JavaScript code until
// the user interacts with the page.
@@ -307,18 +328,17 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// This function attempts to fill |username_element| and |password_element|
// with values from |fill_data|. The |username_element| and |password_element|
// will only have the suggestedValue set. If a match is found, return true and
- // |field_value_and_properties_map| will be modified with the autofilled
- // credentials and |FieldPropertiesFlags::AUTOFILLED| flag.
+ // |field_data_manager| will be modified with the autofilled credentials and
+ // |FieldPropertiesFlags::AUTOFILLED| flag.
// If |username_may_use_prefilled_placeholder| then this function may
// overwrite the value of username field.
- bool FillUserNameAndPassword(
- blink::WebInputElement* username_element,
- blink::WebInputElement* password_element,
- const PasswordFormFillData& fill_data,
- bool exact_username_match,
- bool username_may_use_prefilled_placeholder,
- FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
- RendererSavePasswordProgressLogger* logger);
+ bool FillUserNameAndPassword(blink::WebInputElement* username_element,
+ blink::WebInputElement* password_element,
+ const PasswordFormFillData& fill_data,
+ bool exact_username_match,
+ bool username_may_use_prefilled_placeholder,
+ FieldDataManager* field_data_manager,
+ RendererSavePasswordProgressLogger* logger);
// Logs whether a username value that was prefilled by the website was
// overridden when trying to fill with an existing credential. This logs
@@ -331,12 +351,11 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// attempts to fill the password matching the already filled username, if
// such a password exists. The |password_element| will have the
// |suggestedValue| set. Returns true if the password is filled.
- bool FillFormOnPasswordReceived(
- const PasswordFormFillData& fill_data,
- blink::WebInputElement username_element,
- blink::WebInputElement password_element,
- FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
- RendererSavePasswordProgressLogger* logger);
+ bool FillFormOnPasswordReceived(const PasswordFormFillData& fill_data,
+ blink::WebInputElement username_element,
+ blink::WebInputElement password_element,
+ FieldDataManager* field_data_manager,
+ RendererSavePasswordProgressLogger* logger);
// Helper function called when form submission is successful.
void FireSubmissionIfFormDisappear(
@@ -388,7 +407,7 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// changes them.
// 2) Field properties mask, i.e. whether the field was autofilled, modified
// by user, etc. (see FieldPropertiesMask).
- FieldValueAndPropertiesMaskMap field_value_and_properties_map_;
+ FieldDataManager field_data_manager_;
PasswordValueGatekeeper gatekeeper_;
@@ -423,6 +442,10 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
// username predictions.
UsernameDetectorCache username_detector_cache_;
+ // This notifier is used to avoid sending redundant messages to the password
+ // manager driver mojo interface.
+ FocusStateNotifier focus_state_notifier_;
+
base::WeakPtr<AutofillAgent> autofill_agent_;
PasswordGenerationAgent* password_generation_agent_; // Weak reference.
@@ -433,7 +456,7 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
mojom::PasswordManagerDriverAssociatedPtr password_manager_driver_;
- mojo::Binding<mojom::PasswordAutofillAgent> binding_;
+ mojo::AssociatedBinding<mojom::PasswordAutofillAgent> binding_;
bool prefilled_username_metrics_logged_ = 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 68e02e38c21..36ddc614ccb 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -799,7 +799,6 @@ bool GetPasswordForm(
password_form->new_password_element =
FieldName(new_password, "anonymous_new_password");
password_form->new_password_value = new_password->value;
- password_form->new_password_value_is_default = new_password->is_default;
if (autocomplete_cache.RetrieveFor(new_password) ==
AutocompleteFlag::NEW_PASSWORD) {
password_form->new_password_marked_by_site = true;
@@ -917,7 +916,7 @@ bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form) {
std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
const WebFormElement& web_form,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache) {
if (web_form.IsNull())
@@ -936,10 +935,10 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
if (control_elements.empty())
return nullptr;
- if (!WebFormElementToFormData(
- web_form, blink::WebFormControlElement(),
- field_value_and_properties_map, form_util::EXTRACT_VALUE,
- &password_form->form_data, nullptr /* FormFieldData */)) {
+ if (!WebFormElementToFormData(web_form, blink::WebFormControlElement(),
+ field_data_manager, form_util::EXTRACT_VALUE,
+ &password_form->form_data,
+ nullptr /* FormFieldData */)) {
return nullptr;
}
@@ -954,7 +953,7 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
const WebLocalFrame& frame,
- const FieldValueAndPropertiesMaskMap* field_value_and_properties_map,
+ const FieldDataManager* field_data_manager,
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache) {
std::vector<blink::WebElement> fieldsets;
@@ -967,7 +966,7 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
auto password_form = std::make_unique<PasswordForm>();
if (!UnownedPasswordFormElementsAndFieldSetsToFormData(
fieldsets, control_elements, nullptr, frame.GetDocument(),
- field_value_and_properties_map, form_util::EXTRACT_VALUE,
+ field_data_manager, form_util::EXTRACT_VALUE,
&password_form->form_data, nullptr /* FormFieldData */)) {
return nullptr;
}
diff --git a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
index 50b49e45a86..390db0b8c40 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -32,6 +32,8 @@ namespace autofill {
struct PasswordForm;
+class FieldDataManager;
+
enum UsernameDetectionMethod {
NO_USERNAME_DETECTED,
BASE_HEURISTIC,
@@ -64,26 +66,19 @@ bool IsGaiaReauthenticationForm(const blink::WebFormElement& form);
// Tests whether the given form is a GAIA form with a skip password argument.
bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form);
-// TODO(https://crbug.com/849291): Create separate class for keeping information
-// from FieldValueAndPropertiesMaskMap.
-using FieldValueAndPropertiesMaskMap =
- std::map<uint32_t,
- std::pair<std::unique_ptr<base::string16>, FieldPropertiesMask>>;
-
// Create a PasswordForm from DOM form. Webkit doesn't allow storing
// custom metadata to DOM nodes, so we have to do this every time an event
// happens with a given form and compare against previously Create'd forms
// to identify..which sucks.
-// If an element of |form| has an entry in |nonscript_modified_values|, the
-// associated string is used instead of the element's value to create
-// the PasswordForm.
+// If an element of |form| has an entry in |field_data_manager|, the associated
+// string is used instead of the element's value to create the PasswordForm.
// |form_predictions| is Autofill server response, if present it's used for
// overwriting default username element selection.
// |username_detector_cache| is used by the built-in HTML based username
// detector to cache results. Can be null.
std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
const blink::WebFormElement& form,
- const FieldValueAndPropertiesMaskMap* nonscript_modified_values,
+ const FieldDataManager* field_data_manager,
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache);
@@ -91,7 +86,7 @@ std::unique_ptr<PasswordForm> CreatePasswordFormFromWebForm(
// enclosed in <form> element.
std::unique_ptr<PasswordForm> CreatePasswordFormFromUnownedInputElements(
const blink::WebLocalFrame& frame,
- const FieldValueAndPropertiesMaskMap* nonscript_modified_values,
+ const FieldDataManager* field_data_manager,
const FormsPredictionsMap* form_predictions,
UsernameDetectorCache* username_detector_cache);
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 732fb63e59c..c8d18963ccf 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
@@ -13,6 +13,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
+#include "components/autofill/content/renderer/field_data_manager.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/password_form_conversion_utils.h"
#include "components/autofill/core/browser/form_structure.h"
@@ -214,21 +215,20 @@ class MAYBE_PasswordFormConversionUtilsTest : public content::RenderViewTest {
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
- FieldValueAndPropertiesMaskMap user_input;
+ FieldDataManager field_data_manager;
for (size_t i = 0; i < control_elements.size(); ++i) {
WebInputElement* input_element = ToWebInputElement(&control_elements[i]);
if (input_element->HasAttribute("set-activated-submit"))
input_element->SetActivatedSubmit(true);
if (with_user_input) {
- const base::string16 element_value = input_element->Value().Utf16();
- user_input[control_elements[i].UniqueRendererFormControlId()] =
- std::make_pair(std::make_unique<base::string16>(element_value),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[i],
+ input_element->Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
}
}
return CreatePasswordFormFromWebForm(
- form, with_user_input ? &user_input : nullptr, predictions,
+ form, with_user_input ? &field_data_manager : nullptr, predictions,
&username_detector_cache_);
}
@@ -741,18 +741,16 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
// A user typed only into "id" and "password" fields. So, the prediction for
// "email" field should be ignored despite it is more reliable than prediction
// for "id" field.
- FieldValueAndPropertiesMaskMap user_input;
- user_input[control_elements[2].UniqueRendererFormControlId()] =
- std::make_pair( // id
- std::make_unique<base::string16>(control_elements[2].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
- user_input[control_elements[3].UniqueRendererFormControlId()] =
- std::make_pair( // password
- std::make_unique<base::string16>(control_elements[3].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ FieldDataManager field_data_manager;
+ field_data_manager.UpdateFieldDataMap(
+ control_elements[2], control_elements[2].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED); // id
+ field_data_manager.UpdateFieldDataMap(
+ control_elements[3], control_elements[3].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED); // password
std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &user_input, nullptr, &username_detector_cache);
+ form, &field_data_manager, nullptr, &username_detector_cache);
ASSERT_TRUE(password_form);
EXPECT_EQ(base::UTF8ToUTF16("id"), password_form->username_element);
@@ -1579,23 +1577,21 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, UserInput) {
WebFormElement form;
LoadWebFormFromHTML(html, &form, nullptr);
- FieldValueAndPropertiesMaskMap user_input;
+ FieldDataManager field_data_manager;
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
ASSERT_EQ("nonvisible_text", control_elements[0].NameForAutofill().Utf8());
- user_input[control_elements[0].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(control_elements[0].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[0],
+ control_elements[0].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
ASSERT_EQ("nonvisible_password",
control_elements[2].NameForAutofill().Utf8());
- user_input[control_elements[2].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(control_elements[2].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[2],
+ control_elements[2].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
- std::unique_ptr<PasswordForm> password_form =
- CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
+ std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
+ form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
EXPECT_FALSE(password_form->only_for_fallback_saving);
@@ -1638,24 +1634,22 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
WebFormElement form;
LoadWebFormFromHTML(html, &form, nullptr);
- FieldValueAndPropertiesMaskMap user_input;
+ FieldDataManager field_data_manager;
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
ASSERT_EQ("password_with_user_input1",
control_elements[9].NameForAutofill().Utf8());
- user_input[control_elements[9].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(control_elements[9].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[9],
+ control_elements[9].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
ASSERT_EQ("password_with_user_input2",
control_elements[10].NameForAutofill().Utf8());
- user_input[control_elements[10].UniqueRendererFormControlId()] =
- std::make_pair(std::make_unique<base::string16>(
- control_elements[10].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[10],
+ control_elements[10].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
- std::unique_ptr<PasswordForm> password_form =
- CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
+ std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
+ form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
EXPECT_FALSE(password_form->only_for_fallback_saving);
@@ -1698,24 +1692,22 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
WebFormElement form;
LoadWebFormFromHTML(html, &form, nullptr);
- FieldValueAndPropertiesMaskMap user_input;
+ FieldDataManager field_data_manager;
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
ASSERT_EQ("password_with_user_input1",
control_elements[7].NameForAutofill().Utf8());
- user_input[control_elements[7].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(control_elements[7].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[7],
+ control_elements[7].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
ASSERT_EQ("password_with_user_input2",
control_elements[9].NameForAutofill().Utf8());
- user_input[control_elements[9].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(control_elements[9].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[9],
+ control_elements[9].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
- std::unique_ptr<PasswordForm> password_form =
- CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
+ std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
+ form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
EXPECT_FALSE(password_form->only_for_fallback_saving);
@@ -1863,22 +1855,19 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
LoadWebFormFromHTML(html, &form, nullptr);
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
- FieldValueAndPropertiesMaskMap user_input;
+ FieldDataManager field_data_manager;
FieldPropertiesMask mask = FieldPropertiesFlags::AUTOFILLED;
if (autofilled_value_was_modified_by_user)
mask |= FieldPropertiesFlags::USER_TYPED;
- user_input[control_elements[1].UniqueRendererFormControlId()] =
- std::make_pair(std::make_unique<base::string16>(
- base::ASCIIToUTF16("autofilled_value")),
- mask);
- user_input[control_elements[2].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(base::ASCIIToUTF16("user_value")),
- FieldPropertiesFlags::USER_TYPED);
-
- std::unique_ptr<PasswordForm> password_form(
- CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr));
+ field_data_manager.UpdateFieldDataMap(
+ control_elements[1], base::ASCIIToUTF16("autofilled_value"), mask);
+ field_data_manager.UpdateFieldDataMap(control_elements[2],
+ base::ASCIIToUTF16("user_value"),
+ FieldPropertiesFlags::USER_TYPED);
+
+ std::unique_ptr<PasswordForm> password_form(CreatePasswordFormFromWebForm(
+ form, &field_data_manager, nullptr, nullptr));
ASSERT_TRUE(password_form);
EXPECT_TRUE(password_form->form_has_autofilled_value);
}
@@ -2053,15 +2042,13 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest,
LoadWebFormFromHTML(html, &form, nullptr);
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
- FieldValueAndPropertiesMaskMap user_input;
- WebInputElement* input_element = ToWebInputElement(&control_elements[3]);
- const base::string16 element_value = input_element->Value().Utf16();
- user_input[control_elements[3].UniqueRendererFormControlId()] =
- std::make_pair(std::make_unique<base::string16>(element_value),
- FieldPropertiesFlags::USER_TYPED);
+ FieldDataManager field_data_manager;
+ field_data_manager.UpdateFieldDataMap(control_elements[3],
+ control_elements[3].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
- form, &user_input, &predictions, &username_detector_cache_);
+ form, &field_data_manager, &predictions, &username_detector_cache_);
ASSERT_TRUE(password_form);
EXPECT_EQ(base::UTF8ToUTF16("username"), password_form->username_element);
EXPECT_EQ(base::UTF8ToUTF16("JohnSmith"), password_form->username_value);
@@ -2470,34 +2457,31 @@ TEST_F(MAYBE_PasswordFormConversionUtilsTest, TypedValuePreserved) {
WebFormElement form;
LoadWebFormFromHTML(html, &form, nullptr);
- FieldValueAndPropertiesMaskMap user_input;
+ FieldDataManager field_data_manager;
WebVector<WebFormControlElement> control_elements;
form.GetFormControlElements(control_elements);
ASSERT_EQ(3u, control_elements.size());
ASSERT_EQ("fine", control_elements[0].NameForAutofill().Utf8());
control_elements[0].SetAutofillValue("same_value");
- user_input[control_elements[0].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(control_elements[0].Value().Utf16()),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[0],
+ control_elements[0].Value().Utf16(),
+ FieldPropertiesFlags::USER_TYPED);
ASSERT_EQ("mangled", control_elements[1].NameForAutofill().Utf8());
control_elements[1].SetAutofillValue("mangled_value");
- user_input[control_elements[1].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(base::UTF8ToUTF16("original_value")),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[1],
+ base::UTF8ToUTF16("original_value"),
+ FieldPropertiesFlags::USER_TYPED);
ASSERT_EQ("completed_for_user", control_elements[2].NameForAutofill().Utf8());
control_elements[2].SetAutofillValue("email@gmail.com");
- user_input[control_elements[2].UniqueRendererFormControlId()] =
- std::make_pair(
- std::make_unique<base::string16>(base::UTF8ToUTF16("email")),
- FieldPropertiesFlags::USER_TYPED);
+ field_data_manager.UpdateFieldDataMap(control_elements[2],
+ base::UTF8ToUTF16("email"),
+ FieldPropertiesFlags::USER_TYPED);
- std::unique_ptr<PasswordForm> password_form =
- CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
+ std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
+ form, &field_data_manager, nullptr, nullptr);
ASSERT_TRUE(password_form);
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index 19467682855..60d1b15c55b 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -13,8 +13,8 @@
#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
-#include "components/autofill/content/renderer/form_classifier.h"
#include "components/autofill/content/renderer/password_autofill_agent.h"
+#include "components/autofill/content/renderer/password_form_conversion_utils.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/password_form.h"
@@ -35,6 +35,10 @@
#include "ui/gfx/geometry/rect.h"
using blink::WebAutofillState;
+using blink::WebInputElement;
+using blink::WebFormControlElement;
+using blink::WebFormElement;
+using blink::WebLocalFrame;
namespace autofill {
@@ -46,31 +50,30 @@ using Logger = autofill::SavePasswordProgressLogger;
// Returns pairs of |PasswordForm| and corresponding |WebFormElement| for all
// <form>s in the frame and for unowned <input>s. The method doesn't filter out
// invalid |PasswordForm|s.
-std::vector<std::pair<std::unique_ptr<PasswordForm>, blink::WebFormElement>>
+std::vector<std::pair<std::unique_ptr<PasswordForm>, WebFormElement>>
GetAllPasswordFormsInFrame(PasswordAutofillAgent* password_agent,
- blink::WebLocalFrame* web_frame) {
- blink::WebVector<blink::WebFormElement> web_forms;
+ WebLocalFrame* web_frame) {
+ blink::WebVector<WebFormElement> web_forms;
web_frame->GetDocument().Forms(web_forms);
- std::vector<std::pair<std::unique_ptr<PasswordForm>, blink::WebFormElement>>
+ std::vector<std::pair<std::unique_ptr<PasswordForm>, WebFormElement>>
all_forms;
- for (const blink::WebFormElement& web_form : web_forms) {
+ for (const WebFormElement& web_form : web_forms) {
all_forms.emplace_back(std::make_pair(
password_agent->GetPasswordFormFromWebForm(web_form), web_form));
}
all_forms.emplace_back(
std::make_pair(password_agent->GetPasswordFormFromUnownedInputElements(),
- blink::WebFormElement()));
+ WebFormElement()));
return all_forms;
}
// Returns true if we think that this form is for account creation. Password
// field(s) of the form are pushed back to |passwords|.
bool GetAccountCreationPasswordFields(
- const std::vector<blink::WebFormControlElement>& control_elements,
- std::vector<blink::WebInputElement>* passwords) {
+ const std::vector<WebFormControlElement>& control_elements,
+ std::vector<WebInputElement>* passwords) {
for (const auto& control_element : control_elements) {
- const blink::WebInputElement* input_element =
- ToWebInputElement(&control_element);
+ const WebInputElement* input_element = ToWebInputElement(&control_element);
if (input_element && input_element->IsTextField() &&
input_element->IsPasswordFieldForAutofill()) {
passwords->push_back(*input_element);
@@ -97,11 +100,11 @@ const PasswordFormGenerationData* FindFormGenerationData(
// Returns a vector of up to 2 password fields with autocomplete attribute set
// to "new-password". These will be filled with the generated password.
-std::vector<blink::WebInputElement> FindNewPasswordElementsMarkedBySite(
- const std::vector<blink::WebInputElement>& all_password_elements) {
- std::vector<blink::WebInputElement> passwords;
+std::vector<WebInputElement> FindNewPasswordElementsMarkedBySite(
+ const std::vector<WebInputElement>& all_password_elements) {
+ std::vector<WebInputElement> passwords;
- auto is_new_password_field = [](const blink::WebInputElement& element) {
+ auto is_new_password_field = [](const WebInputElement& element) {
return AutocompleteFlagForElement(element) ==
AutocompleteFlag::NEW_PASSWORD;
};
@@ -123,14 +126,14 @@ std::vector<blink::WebInputElement> FindNewPasswordElementsMarkedBySite(
// Returns a vector of up to 2 password fields into which Chrome should fill the
// generated password. It assumes that |field_signature| describes the field
// where Chrome shows the password generation prompt.
-std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
- const std::vector<blink::WebInputElement>& all_password_elements,
+std::vector<WebInputElement> FindPasswordElementsForGeneration(
+ const std::vector<WebInputElement>& all_password_elements,
const PasswordFormGenerationData& generation_data) {
auto generation_field_iter = all_password_elements.end();
auto confirmation_field_iter = all_password_elements.end();
for (auto iter = all_password_elements.begin();
iter != all_password_elements.end(); ++iter) {
- const blink::WebInputElement& input = *iter;
+ const WebInputElement& input = *iter;
FieldSignature signature = CalculateFieldSignatureByNameAndType(
input.NameForAutofill().Utf16(),
input.FormControlTypeForAutofill().Utf8());
@@ -142,7 +145,7 @@ std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
}
}
- std::vector<blink::WebInputElement> passwords;
+ std::vector<WebInputElement> passwords;
if (generation_field_iter != all_password_elements.end()) {
passwords.push_back(*generation_field_iter);
@@ -155,9 +158,9 @@ std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
}
void CopyElementValueToOtherInputElements(
- const blink::WebInputElement* element,
- std::vector<blink::WebInputElement>* elements) {
- for (blink::WebInputElement& it : *elements) {
+ const WebInputElement* element,
+ std::vector<WebInputElement>* elements) {
+ for (WebInputElement& it : *elements) {
if (*element != it) {
it.SetAutofillValue(element->Value());
}
@@ -168,7 +171,7 @@ void CopyElementValueToOtherInputElements(
PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData(
linked_ptr<PasswordForm> password_form,
- std::vector<blink::WebInputElement> passwords)
+ std::vector<WebInputElement> passwords)
: form(password_form), password_elements(std::move(passwords)) {}
PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData(
@@ -179,7 +182,7 @@ PasswordGenerationAgent::AccountCreationFormData::~AccountCreationFormData() {}
PasswordGenerationAgent::PasswordGenerationAgent(
content::RenderFrame* render_frame,
PasswordAutofillAgent* password_agent,
- service_manager::BinderRegistry* registry)
+ blink::AssociatedInterfaceRegistry* registry)
: content::RenderFrameObserver(render_frame),
password_is_generated_(false),
is_manually_triggered_(false),
@@ -187,21 +190,20 @@ PasswordGenerationAgent::PasswordGenerationAgent(
generation_popup_shown_(false),
editing_popup_shown_(false),
enabled_(password_generation::IsPasswordGenerationEnabled()),
- form_classifier_enabled_(false),
mark_generation_element_(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kShowAutofillSignatures)),
password_agent_(password_agent),
binding_(this) {
LogBoolean(Logger::STRING_GENERATION_RENDERER_ENABLED, enabled_);
- registry->AddInterface(base::Bind(&PasswordGenerationAgent::BindRequest,
- base::Unretained(this)));
+ registry->AddInterface(base::BindRepeating(
+ &PasswordGenerationAgent::BindRequest, base::Unretained(this)));
password_agent_->SetPasswordGenerationAgent(this);
}
PasswordGenerationAgent::~PasswordGenerationAgent() {}
void PasswordGenerationAgent::BindRequest(
- mojom::PasswordGenerationAgentRequest request) {
+ mojom::PasswordGenerationAgentAssociatedRequest request) {
binding_.Bind(std::move(request));
}
@@ -209,6 +211,7 @@ void PasswordGenerationAgent::DidCommitProvisionalLoad(
bool /*is_new_navigation*/, bool is_same_document_navigation) {
if (is_same_document_navigation)
return;
+ password_is_generated_ = false;
generation_element_.Reset();
last_focused_password_element_.Reset();
}
@@ -280,26 +283,11 @@ void PasswordGenerationAgent::OnDynamicFormsSeen() {
}
void PasswordGenerationAgent::OnFieldAutofilled(
- const blink::WebInputElement& password_element) {
+ const WebInputElement& password_element) {
if (password_is_generated_ && generation_element_ == password_element)
PasswordNoLongerGenerated();
}
-void PasswordGenerationAgent::AllowToRunFormClassifier() {
- form_classifier_enabled_ = true;
-}
-
-void PasswordGenerationAgent::RunFormClassifierAndSaveVote(
- const blink::WebFormElement& web_form,
- const PasswordForm& form) {
- DCHECK(form_classifier_enabled_);
-
- base::string16 generation_field;
- ClassifyFormAndFindGenerationField(web_form, &generation_field);
- GetPasswordManagerDriver()->SaveGenerationFieldDetectedByClassifier(
- form, generation_field);
-}
-
void PasswordGenerationAgent::FindPossibleGenerationForm() {
if (!enabled_ || !render_frame())
return;
@@ -313,8 +301,8 @@ void PasswordGenerationAgent::FindPossibleGenerationForm() {
if (generation_form_data_)
return;
- blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
- std::vector<std::pair<std::unique_ptr<PasswordForm>, blink::WebFormElement>>
+ WebLocalFrame* web_frame = render_frame()->GetWebFrame();
+ std::vector<std::pair<std::unique_ptr<PasswordForm>, WebFormElement>>
all_password_forms =
GetAllPasswordFormsInFrame(password_agent_, web_frame);
for (auto& form : all_password_forms) {
@@ -332,16 +320,14 @@ void PasswordGenerationAgent::FindPossibleGenerationForm() {
if (realm == GaiaUrls::GetInstance()->gaia_login_form_realm())
continue;
- std::vector<blink::WebInputElement> passwords;
- const blink::WebFormElement& web_form = form.second;
+ std::vector<WebInputElement> passwords;
+ const WebFormElement& web_form = form.second;
if (GetAccountCreationPasswordFields(
web_form.IsNull()
? form_util::GetUnownedFormFieldElements(
web_frame->GetDocument().All(), nullptr)
: form_util::ExtractAutofillableElementsInForm(web_form),
&passwords)) {
- if (form_classifier_enabled_ && !web_form.IsNull())
- RunFormClassifierAndSaveVote(web_form, *password_form);
possible_account_creation_forms_.emplace_back(
make_linked_ptr(form.first.release()), std::move(passwords));
}
@@ -473,7 +459,7 @@ void PasswordGenerationAgent::DetermineGenerationElement() {
PasswordForm* possible_password_form = possible_form_data.form.get();
const PasswordFormGenerationData* generation_data = nullptr;
- std::vector<blink::WebInputElement> password_elements;
+ std::vector<WebInputElement> password_elements;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kLocalHeuristicsOnlyForPasswordGeneration)) {
password_elements = possible_form_data.password_elements;
@@ -529,14 +515,14 @@ bool PasswordGenerationAgent::SetUpUserTriggeredGeneration() {
if (last_focused_password_element_.IsNull() || !render_frame())
return false;
- blink::WebFormElement form = last_focused_password_element_.Form();
+ WebFormElement form = last_focused_password_element_.Form();
std::unique_ptr<PasswordForm> password_form;
- std::vector<blink::WebFormControlElement> control_elements;
+ std::vector<WebFormControlElement> control_elements;
if (!form.IsNull()) {
password_form = password_agent_->GetPasswordFormFromWebForm(form);
control_elements = form_util::ExtractAutofillableElementsInForm(form);
} else {
- const blink::WebLocalFrame& frame = *render_frame()->GetWebFrame();
+ const WebLocalFrame& frame = *render_frame()->GetWebFrame();
blink::WebDocument doc = frame.GetDocument();
if (doc.IsNull())
return false;
@@ -549,7 +535,7 @@ bool PasswordGenerationAgent::SetUpUserTriggeredGeneration() {
return false;
generation_element_ = last_focused_password_element_;
- std::vector<blink::WebInputElement> password_elements;
+ std::vector<WebInputElement> password_elements;
GetAccountCreationPasswordFields(control_elements, &password_elements);
password_elements = FindPasswordElementsForGeneration(
password_elements,
@@ -581,7 +567,7 @@ bool PasswordGenerationAgent::FocusedNodeHasChanged(
return false;
}
- const blink::WebInputElement* element = ToWebInputElement(&web_element);
+ const WebInputElement* element = ToWebInputElement(&web_element);
if (element && element->IsPasswordFieldForAutofill())
last_focused_password_element_ = *element;
if (!element || *element != generation_element_) {
@@ -614,10 +600,15 @@ bool PasswordGenerationAgent::FocusedNodeHasChanged(
}
bool PasswordGenerationAgent::TextDidChangeInTextField(
- const blink::WebInputElement& element) {
+ const WebInputElement& element) {
if (element != generation_element_) {
// Presave the username if it has been changed.
- if (password_is_generated_ &&
+ // TODO(crbug.com/879713): investigate why the following DCHECKs can be
+ // triggered.
+ DCHECK(!element.IsNull());
+ DCHECK(!password_is_generated_ || !generation_element_.IsNull());
+ if (password_is_generated_ && !element.IsNull() &&
+ !generation_element_.IsNull() &&
(element.Form() == generation_element_.Form())) {
std::unique_ptr<PasswordForm> presaved_form(
CreatePasswordFormToPresave());
@@ -710,14 +701,12 @@ void PasswordGenerationAgent::PasswordNoLongerGenerated() {
password_is_generated_ = false;
password_edited_ = false;
generation_element_.SetShouldRevealPassword(false);
- for (blink::WebInputElement& password :
- generation_form_data_->password_elements)
+ for (WebInputElement& password : generation_form_data_->password_elements)
password.SetAutofillState(WebAutofillState::kNotFilled);
password_generation::LogPasswordGenerationEvent(
password_generation::PASSWORD_DELETED);
// Clear all other password fields.
- for (blink::WebInputElement& element :
- generation_form_data_->password_elements) {
+ for (WebInputElement& element : generation_form_data_->password_elements) {
if (generation_element_ != element)
element.SetAutofillValue(blink::WebString());
}
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.h b/chromium/components/autofill/content/renderer/password_generation_agent.h
index f19f17bc18b..a5f0a8b2594 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.h
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.h
@@ -18,8 +18,8 @@
#include "components/autofill/content/common/autofill_driver.mojom.h"
#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
#include "content/public/renderer/render_frame_observer.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/web/web_input_element.h"
#include "url/gurl.h"
@@ -46,10 +46,10 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
PasswordGenerationAgent(content::RenderFrame* render_frame,
PasswordAutofillAgent* password_agent,
- service_manager::BinderRegistry* registry);
+ blink::AssociatedInterfaceRegistry* registry);
~PasswordGenerationAgent() override;
- void BindRequest(mojom::PasswordGenerationAgentRequest request);
+ void BindRequest(mojom::PasswordGenerationAgentAssociatedRequest request);
// mojom::PasswordGenerationAgent:
void FormNotBlacklisted(const PasswordForm& form) override;
@@ -60,9 +60,6 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
// generation popup at this field.
void UserTriggeredGeneratePassword() override;
- // Enables the form classifier.
- void AllowToRunFormClassifier() 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.
bool TextDidChangeInTextField(const blink::WebInputElement& element);
@@ -221,9 +218,6 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
// If this feature is enabled. Controlled by Finch.
bool enabled_;
- // If the form classifier should run.
- bool form_classifier_enabled_;
-
// True iff the generation element should be marked with special HTML
// attribute (only for experimental purposes).
bool mark_generation_element_;
@@ -234,7 +228,7 @@ class PasswordGenerationAgent : public content::RenderFrameObserver,
mojom::PasswordManagerClientAssociatedPtr password_manager_client_;
- mojo::Binding<mojom::PasswordGenerationAgent> binding_;
+ mojo::AssociatedBinding<mojom::PasswordGenerationAgent> binding_;
DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgent);
};
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 c9c75857070..f79fac872bc 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
@@ -71,10 +71,6 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
void UserModifiedPasswordField() override {}
- void SaveGenerationFieldDetectedByClassifier(
- const autofill::PasswordForm& password_form,
- const base::string16& generation_field) override {}
-
void CheckSafeBrowsingReputation(const GURL& form_action,
const GURL& frame_url) override {}
diff --git a/chromium/components/autofill/content/renderer/test_password_autofill_agent.cc b/chromium/components/autofill/content/renderer/test_password_autofill_agent.cc
index 560bbbc410d..6778b3febf6 100644
--- a/chromium/components/autofill/content/renderer/test_password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/test_password_autofill_agent.cc
@@ -8,7 +8,7 @@ namespace autofill {
TestPasswordAutofillAgent::TestPasswordAutofillAgent(
content::RenderFrame* render_frame,
- service_manager::BinderRegistry* registry)
+ blink::AssociatedInterfaceRegistry* registry)
: PasswordAutofillAgent(render_frame, registry) {}
TestPasswordAutofillAgent::~TestPasswordAutofillAgent() {}
diff --git a/chromium/components/autofill/content/renderer/test_password_autofill_agent.h b/chromium/components/autofill/content/renderer/test_password_autofill_agent.h
index 2f4add17b86..12c16dd14ba 100644
--- a/chromium/components/autofill/content/renderer/test_password_autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/test_password_autofill_agent.h
@@ -12,7 +12,7 @@ namespace autofill {
class TestPasswordAutofillAgent : public PasswordAutofillAgent {
public:
TestPasswordAutofillAgent(content::RenderFrame* render_frame,
- service_manager::BinderRegistry* registry);
+ blink::AssociatedInterfaceRegistry* registry);
~TestPasswordAutofillAgent() override;
private:
diff --git a/chromium/components/autofill/content/renderer/test_password_generation_agent.cc b/chromium/components/autofill/content/renderer/test_password_generation_agent.cc
index 4076003b313..14b5017adb8 100644
--- a/chromium/components/autofill/content/renderer/test_password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/test_password_generation_agent.cc
@@ -9,7 +9,7 @@ namespace autofill {
TestPasswordGenerationAgent::TestPasswordGenerationAgent(
content::RenderFrame* render_frame,
PasswordAutofillAgent* password_agent,
- service_manager::BinderRegistry* registry)
+ blink::AssociatedInterfaceRegistry* registry)
: PasswordGenerationAgent(render_frame, password_agent, registry) {
// Always enable when testing.
set_enabled(true);
diff --git a/chromium/components/autofill/content/renderer/test_password_generation_agent.h b/chromium/components/autofill/content/renderer/test_password_generation_agent.h
index f752803b7cc..5ae0e0c6d7a 100644
--- a/chromium/components/autofill/content/renderer/test_password_generation_agent.h
+++ b/chromium/components/autofill/content/renderer/test_password_generation_agent.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "components/autofill/content/renderer/password_generation_agent.h"
-#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
namespace autofill {
@@ -17,7 +17,7 @@ class TestPasswordGenerationAgent : public PasswordGenerationAgent {
public:
TestPasswordGenerationAgent(content::RenderFrame* render_frame,
PasswordAutofillAgent* password_agent,
- service_manager::BinderRegistry* registry);
+ blink::AssociatedInterfaceRegistry* registry);
~TestPasswordGenerationAgent() override;
// PasswordGenreationAgent implementation:
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 24528a81894..ccb84650b18 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -3,10 +3,12 @@
# found in the LICENSE file.
import("//build/config/chrome_build.gni")
+import("//build/config/jumbo.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
-static_library("browser") {
+jumbo_static_library("browser") {
sources = [
+ "account_info_getter.h",
"address.cc",
"address.h",
"address_combobox_model.cc",
@@ -115,8 +117,6 @@ static_library("browser") {
"local_card_migration_manager.h",
"name_field.cc",
"name_field.h",
- "password_generator.cc",
- "password_generator.h",
"password_requirements_spec_fetcher.h",
"password_requirements_spec_fetcher_impl.cc",
"password_requirements_spec_fetcher_impl.h",
@@ -126,9 +126,12 @@ static_library("browser") {
"payments/full_card_request.h",
"payments/payments_client.cc",
"payments/payments_client.h",
+ "payments/payments_customer_data.h",
"payments/payments_request.h",
"payments/payments_service_url.cc",
"payments/payments_service_url.h",
+ "payments/payments_util.cc",
+ "payments/payments_util.h",
"personal_data_manager.cc",
"personal_data_manager.h",
"personal_data_manager_observer.h",
@@ -176,13 +179,19 @@ static_library("browser") {
"webdata/autofill_profile_sync_difference_tracker.h",
"webdata/autofill_profile_syncable_service.cc",
"webdata/autofill_profile_syncable_service.h",
+ "webdata/autofill_sync_bridge_util.cc",
+ "webdata/autofill_sync_bridge_util.h",
"webdata/autofill_table.cc",
"webdata/autofill_table.h",
"webdata/autofill_table_encryptor.h",
"webdata/autofill_table_encryptor_factory.cc",
"webdata/autofill_table_encryptor_factory.h",
+ "webdata/autofill_wallet_metadata_sync_bridge.cc",
+ "webdata/autofill_wallet_metadata_sync_bridge.h",
"webdata/autofill_wallet_metadata_syncable_service.cc",
"webdata/autofill_wallet_metadata_syncable_service.h",
+ "webdata/autofill_wallet_sync_bridge.cc",
+ "webdata/autofill_wallet_sync_bridge.h",
"webdata/autofill_wallet_syncable_service.cc",
"webdata/autofill_wallet_syncable_service.h",
"webdata/autofill_webdata.h",
@@ -194,8 +203,6 @@ static_library("browser") {
"webdata/autofill_webdata_service_observer.h",
"webdata/system_encryptor.cc",
"webdata/system_encryptor.h",
- "webdata/web_data_model_type_controller.cc",
- "webdata/web_data_model_type_controller.h",
]
if (is_ios) {
@@ -220,6 +227,7 @@ static_library("browser") {
if (!is_android) {
sources += [
"ui/local_card_migration_bubble_controller.h",
+ "ui/local_card_migration_dialog_controller.h",
"ui/save_card_bubble_controller.h",
]
}
@@ -246,6 +254,7 @@ static_library("browser") {
"//third_party/libaddressinput",
]
deps = [
+ ":password_generator",
":password_generator_fips181",
"//base",
"//base:i18n",
@@ -290,7 +299,7 @@ static_library("browser") {
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"autofill_test_utils.cc",
@@ -331,6 +340,8 @@ static_library("test_support") {
"test_region_data_loader.h",
"test_sync_service.cc",
"test_sync_service.h",
+ "webdata/autofill_sync_bridge_test_util.cc",
+ "webdata/autofill_sync_bridge_test_util.h",
]
public_deps = [
@@ -362,6 +373,19 @@ static_library("test_support") {
]
}
+static_library("password_generator") {
+ sources = [
+ "password_generator.cc",
+ "password_generator.h",
+ ]
+ public_deps = [
+ "//components/autofill/core/browser/proto",
+ ]
+ deps = [
+ "//base",
+ ]
+}
+
static_library("password_generator_fips181") {
sources = [
"password_generator_fips181.cc",
@@ -445,6 +469,7 @@ source_set("unit_tests") {
"payments/full_card_request_unittest.cc",
"payments/payments_client_unittest.cc",
"payments/payments_service_url_unittest.cc",
+ "payments/payments_util_unittest.cc",
"personal_data_manager_unittest.cc",
"phone_field_unittest.cc",
"phone_number_i18n_unittest.cc",
@@ -459,8 +484,11 @@ source_set("unit_tests") {
"webdata/autofill_profile_sync_bridge_unittest.cc",
"webdata/autofill_profile_sync_difference_tracker_unittest.cc",
"webdata/autofill_profile_syncable_service_unittest.cc",
+ "webdata/autofill_sync_bridge_util_unittest.cc",
"webdata/autofill_table_unittest.cc",
+ "webdata/autofill_wallet_metadata_sync_bridge_unittest.cc",
"webdata/autofill_wallet_metadata_syncable_service_unittest.cc",
+ "webdata/autofill_wallet_sync_bridge_unittest.cc",
"webdata/autofill_wallet_syncable_service_unittest.cc",
"webdata/web_data_service_unittest.cc",
]
@@ -479,6 +507,7 @@ source_set("unit_tests") {
deps = [
":browser",
+ ":password_generator",
":password_generator_fips181",
":test_support",
":unit_tests_bundle_data",
@@ -543,3 +572,29 @@ fuzzer_test("password_generator_fips181_fuzzer") {
":password_generator_fips181",
]
}
+
+if (use_libfuzzer) {
+ fuzzer_test("form_structure_process_query_response_fuzzer") {
+ sources = [
+ "form_structure_process_query_response_fuzzer.cc",
+ ]
+ deps = [
+ ":browser",
+ "//base:base",
+ "//components/autofill/core/browser/proto",
+ "//components/autofill/core/common",
+ "//third_party/libprotobuf-mutator",
+ ]
+ }
+
+ fuzzer_test("password_generator_proto_fuzzer") {
+ sources = [
+ "password_generator_proto_fuzzer.cc",
+ ]
+ deps = [
+ ":password_generator",
+ "//components/autofill/core/browser/proto",
+ "//third_party/libprotobuf-mutator",
+ ]
+ }
+}
diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS
index 5bef9b837fa..f3199c0270c 100644
--- a/chromium/components/autofill/core/browser/DEPS
+++ b/chromium/components/autofill/core/browser/DEPS
@@ -6,12 +6,7 @@ include_rules = [
"+components/metrics",
"+components/policy",
"+components/security_state",
-
- # Autofill depends on //services/identity/public/cpp for its core Google
- # identity dependencies, but depends on this isolated file for recording
- # some browser-specific signin metrics.
- "+components/signin/core/browser/signin_metrics.h",
-
+ "+components/signin/core/browser",
"+components/sync",
"+components/variations",
"+components/version_info",
diff --git a/chromium/components/autofill/core/browser/account_info_getter.h b/chromium/components/autofill/core/browser/account_info_getter.h
new file mode 100644
index 00000000000..7d71b5fae99
--- /dev/null
+++ b/chromium/components/autofill/core/browser/account_info_getter.h
@@ -0,0 +1,33 @@
+// 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_ACCOUNT_INFO_GETTER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_ACCOUNT_INFO_GETTER_H_
+
+#include <string>
+
+#include "components/signin/core/browser/account_info.h"
+
+namespace autofill {
+
+// Interface to get account information in Autofill.
+class AccountInfoGetter {
+ public:
+ // Returns the account info that should be used when communicating with the
+ // Payments server. The AccountInfo could be empty if there is no account to
+ // be used by the Payments server.
+ virtual AccountInfo GetAccountInfoForPaymentsServer() const = 0;
+
+ // Returns true - When user is both signed-in and enabled sync.
+ // Returns false - When user is not signed-in or does not have sync the
+ // feature enabled.
+ virtual bool IsSyncFeatureEnabled() const = 0;
+
+ protected:
+ virtual ~AccountInfoGetter() {}
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ACCOUNT_INFO_GETTER_H_
diff --git a/chromium/components/autofill/core/browser/address_combobox_model.h b/chromium/components/autofill/core/browser/address_combobox_model.h
index f8b09f44977..a6556e41bbe 100644
--- a/chromium/components/autofill/core/browser/address_combobox_model.h
+++ b/chromium/components/autofill/core/browser/address_combobox_model.h
@@ -72,7 +72,7 @@ class AddressComboboxModel : public ui::ComboboxModel {
std::string default_selected_guid_;
// To be called when the data for the given country code was loaded.
- base::ObserverList<ui::ComboboxModelObserver> observers_;
+ base::ObserverList<ui::ComboboxModelObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(AddressComboboxModel);
};
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl.cc b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
index e4239056532..ca78af9d58a 100644
--- a/chromium/components/autofill/core/browser/address_normalizer_impl.cc
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
@@ -14,7 +14,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/address_i18n.h"
@@ -158,7 +158,7 @@ AddressNormalizerImpl::AddressNormalizerImpl(std::unique_ptr<Source> source,
// of |storage| accesses an ObserverList that lives on the current sequence.
// https://crbug.com/829122
base::PostTaskWithTraitsAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(
&CreateAddressValidator, std::move(source),
DeleteOnTaskRunnerStorageUniquePtr(
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
index d54741f0e61..fb8c47af30f 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -14,7 +14,6 @@
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/browser/validation.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/form_data.h"
#include "components/prefs/pref_service.h"
diff --git a/chromium/components/autofill/core/browser/autofill_address_policy_handler.cc b/chromium/components/autofill/core/browser/autofill_address_policy_handler.cc
index 5e930c8dee7..5afc719388c 100644
--- a/chromium/components/autofill/core/browser/autofill_address_policy_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_address_policy_handler.cc
@@ -5,7 +5,7 @@
#include "components/autofill/core/browser/autofill_address_policy_handler.h"
#include "base/values.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
@@ -26,10 +26,6 @@ void AutofillAddressPolicyHandler::ApplyPolicySettings(
if (value && value->GetAsBoolean(&autofill_profile_enabled) &&
!autofill_profile_enabled) {
prefs->SetBoolean(autofill::prefs::kAutofillProfileEnabled, false);
- } else {
- // Temporary fix for M69. If there is no policy explicitly disabling this
- // pref, it should be set to true.
- prefs->SetBoolean(autofill::prefs::kAutofillProfileEnabled, true);
}
}
diff --git a/chromium/components/autofill/core/browser/autofill_address_policy_handler_unittest.cc b/chromium/components/autofill/core/browser/autofill_address_policy_handler_unittest.cc
index dd299921092..1ea9d60740d 100644
--- a/chromium/components/autofill/core/browser/autofill_address_policy_handler_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_address_policy_handler_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/values.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
@@ -24,15 +24,8 @@ TEST_F(AutofillAddressPolicyHandlerTest, Default) {
PrefValueMap prefs;
AutofillAddressPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
-
- // Temporary fix for M69. The pref is enabled by default unless it's disabled
- // by policy.
- const base::Value* value = nullptr;
- ASSERT_TRUE(prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, &value));
- EXPECT_TRUE(value);
- bool autofill_profile_enabled = false;
- ASSERT_TRUE(value->GetAsBoolean(&autofill_profile_enabled));
- EXPECT_TRUE(autofill_profile_enabled);
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, nullptr));
}
TEST_F(AutofillAddressPolicyHandlerTest, Enabled) {
@@ -45,14 +38,9 @@ TEST_F(AutofillAddressPolicyHandlerTest, Enabled) {
AutofillAddressPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
- // Temporary fix for M69. The pref is enabled by default unless it's disabled
- // by policy.
- const base::Value* value = nullptr;
- ASSERT_TRUE(prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, &value));
- EXPECT_TRUE(value);
- bool autofill_profile_enabled = false;
- ASSERT_TRUE(value->GetAsBoolean(&autofill_profile_enabled));
- EXPECT_TRUE(autofill_profile_enabled);
+ // Enabling Autofill for profiles should not set the prefs.
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, nullptr));
}
TEST_F(AutofillAddressPolicyHandlerTest, Disabled) {
diff --git a/chromium/components/autofill/core/browser/autofill_address_util.cc b/chromium/components/autofill/core/browser/autofill_address_util.cc
index 49cd7dd25e7..d16f649137d 100644
--- a/chromium/components/autofill/core/browser/autofill_address_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_address_util.cc
@@ -77,16 +77,16 @@ void GetAddressComponents(const std::string& country_code,
std::string* components_language_code) {
DCHECK(address_components);
- i18n::addressinput::Localization localization;
+ ::i18n::addressinput::Localization localization;
localization.SetGetter(l10n_util::GetStringUTF8);
std::string not_used;
std::vector<AddressUiComponent> components =
- i18n::addressinput::BuildComponents(
+ ::i18n::addressinput::BuildComponents(
country_code, localization, ui_language_code,
components_language_code ? components_language_code : &not_used);
if (components.empty()) {
static const char kDefaultCountryCode[] = "US";
- components = i18n::addressinput::BuildComponents(
+ components = ::i18n::addressinput::BuildComponents(
kDefaultCountryCode, localization, ui_language_code,
components_language_code ? components_language_code : &not_used);
}
@@ -107,31 +107,31 @@ void GetAddressComponents(const std::string& country_code,
component->SetString(kFieldNameKey, components[i].name);
switch (components[i].field) {
- case i18n::addressinput::COUNTRY:
+ case ::i18n::addressinput::COUNTRY:
component->SetString(kFieldTypeKey, kCountryField);
break;
- case i18n::addressinput::ADMIN_AREA:
+ case ::i18n::addressinput::ADMIN_AREA:
component->SetString(kFieldTypeKey, kStateField);
break;
- case i18n::addressinput::LOCALITY:
+ case ::i18n::addressinput::LOCALITY:
component->SetString(kFieldTypeKey, kCityField);
break;
- case i18n::addressinput::DEPENDENT_LOCALITY:
+ case ::i18n::addressinput::DEPENDENT_LOCALITY:
component->SetString(kFieldTypeKey, kDependentLocalityField);
break;
- case i18n::addressinput::SORTING_CODE:
+ case ::i18n::addressinput::SORTING_CODE:
component->SetString(kFieldTypeKey, kSortingCodeField);
break;
- case i18n::addressinput::POSTAL_CODE:
+ case ::i18n::addressinput::POSTAL_CODE:
component->SetString(kFieldTypeKey, kPostalCodeField);
break;
- case i18n::addressinput::STREET_ADDRESS:
+ case ::i18n::addressinput::STREET_ADDRESS:
component->SetString(kFieldTypeKey, kAddressLineField);
break;
- case i18n::addressinput::ORGANIZATION:
+ case ::i18n::addressinput::ORGANIZATION:
component->SetString(kFieldTypeKey, kCompanyNameField);
break;
- case i18n::addressinput::RECIPIENT:
+ case ::i18n::addressinput::RECIPIENT:
component->SetString(kFieldTypeKey, kFullNameField);
break;
}
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.cc b/chromium/components/autofill/core/browser/autofill_assistant.cc
index b9f5e194572..8c630de5ff8 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant.cc
@@ -6,11 +6,11 @@
#include "base/containers/adapters.h"
#include "base/strings/string16.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
namespace autofill {
@@ -25,19 +25,20 @@ void AutofillAssistant::Reset() {
credit_card_form_data_.reset();
}
-bool AutofillAssistant::CanShowCreditCardAssist(
- const std::vector<std::unique_ptr<FormStructure>>& form_structures) {
+bool AutofillAssistant::CanShowCreditCardAssist() {
+ const auto& form_structures = autofill_manager_->form_structures();
if (form_structures.empty() || credit_card_form_data_ != nullptr ||
- !IsAutofillCreditCardAssistEnabled() ||
+ !features::IsAutofillCreditCardAssistEnabled() ||
// Context of the page is not secure or target URL is valid but not
// secure.
!(autofill_manager_->client()->IsContextSecure() &&
- (!form_structures.front()->target_url().is_valid() ||
- !form_structures.front()->target_url().SchemeIs("http")))) {
+ (!form_structures.begin()->second->target_url().is_valid() ||
+ !form_structures.begin()->second->target_url().SchemeIs("http")))) {
return false;
}
- for (auto& cur_form : base::Reversed(form_structures)) {
+ for (const auto& kv : form_structures) {
+ auto& cur_form = kv.second;
if (cur_form->IsCompleteCreditCardForm()) {
credit_card_form_data_ =
std::make_unique<FormData>(cur_form->ToFormData());
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.h b/chromium/components/autofill/core/browser/autofill_assistant.h
index 79f097f82b3..ecd60f91914 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.h
+++ b/chromium/components/autofill/core/browser/autofill_assistant.h
@@ -17,7 +17,6 @@ namespace autofill {
class AutofillManager;
class CreditCard;
-class FormStructure;
// This class encompasses the triggering rules and the logic for the autofill
// assisted filling mechanisms.
@@ -30,9 +29,9 @@ class AutofillAssistant : public payments::FullCardRequest::ResultDelegate {
void Reset();
// Returns whether a credit card assist can be shown. Will go through the
- // forms in |form_structures| and extract the credit card form.
- bool CanShowCreditCardAssist(
- const std::vector<std::unique_ptr<FormStructure>>& form_structures);
+ // forms in autofill_manager_.form_structures() and extract the credit card
+ // form.
+ bool CanShowCreditCardAssist();
// Will show an assist infobar for the previously extracted form proposing to
// autofill it. Should only be called if CanShowCreditCardAssist() returned
diff --git a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
index 342c81ed767..e22a2c240ab 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant_unittest.cc
@@ -13,7 +13,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_experiments.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"
@@ -22,6 +21,7 @@
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -47,6 +47,8 @@ class MockAutofillManager : public AutofillManager {
const CreditCard& credit_card,
const base::string16& cvc));
+ using AutofillManager::mutable_form_structures;
+
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
};
@@ -64,7 +66,8 @@ class AutofillAssistantTest : public testing::Test {
autofill_assistant_(&autofill_manager_) {}
void EnableAutofillCreditCardAssist() {
- scoped_feature_list_.InitAndEnableFeature(kAutofillCreditCardAssist);
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillCreditCardAssist);
}
// Returns a valid credit card form.
@@ -104,8 +107,7 @@ class AutofillAssistantTest : public testing::Test {
std::unique_ptr<FormStructure> CreateValidCreditCardForm() {
std::unique_ptr<FormStructure> form_structure;
form_structure.reset(new FormStructure(CreateValidCreditCardFormData()));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
return form_structure;
}
@@ -127,23 +129,25 @@ MATCHER_P(CreditCardMatches, guid, "") {
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOff) {
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist());
}
// Tests that with the feature enabled and proper input,
// CanShowCreditCardAssist() behaves as expected.
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn) {
EnableAutofillCreditCardAssist();
- std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist());
// With valid input, the function extracts the credit card form properly.
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
}
// Tests that with the feature enabled and proper input,
@@ -153,13 +157,13 @@ TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Secure) {
// Can be shown if the context is secure.
FormData form = CreateValidCreditCardFormData();
- std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ auto form_structure = std::make_unique<FormStructure>(form);
+ form_structure->DetermineHeuristicTypes();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
}
// Tests that with the feature enabled and proper input,
@@ -171,13 +175,13 @@ TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_NotSecure) {
FormData form = CreateValidCreditCardFormData();
form.origin = GURL("http://myform.com");
form.action = GURL("http://myform.com/submit");
- std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ auto form_structure = std::make_unique<FormStructure>(form);
+ form_structure->DetermineHeuristicTypes();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist());
}
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Javascript) {
@@ -187,13 +191,13 @@ TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Javascript) {
// function (which is a valid url).
FormData form = CreateValidCreditCardFormData();
form.action = GURL("javascript:alert('hello');");
- std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ auto form_structure = std::make_unique<FormStructure>(form);
+ form_structure->DetermineHeuristicTypes();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
}
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_WeirdJs) {
@@ -203,13 +207,13 @@ TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_WeirdJs) {
// function that may or may not be valid.
FormData form = CreateValidCreditCardFormData();
form.action = GURL("javascript:myFunc");
- std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ auto form_structure = std::make_unique<FormStructure>(form);
+ form_structure->DetermineHeuristicTypes();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
}
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_EmptyAction) {
@@ -218,13 +222,13 @@ TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_EmptyAction) {
// Can be shown if the context is secure and the form action is empty.
FormData form = CreateValidCreditCardFormData();
form.action = GURL();
- std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ auto form_structure = std::make_unique<FormStructure>(form);
+ form_structure->DetermineHeuristicTypes();
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
}
TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_CancelCvc) {
@@ -232,9 +236,10 @@ TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_CancelCvc) {
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
// Will extract the credit card form data.
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
// Create a valid card for the assist.
CreditCard card;
@@ -255,9 +260,10 @@ TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_SubmitCvc) {
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
// Will extract the credit card form data.
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::move(form_structure));
- EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
+ auto& form_structures = *autofill_manager_.mutable_form_structures();
+ auto signature = form_structure->form_signature();
+ form_structures[signature] = std::move(form_structure);
+ EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist());
// Create a valid card for the assist.
CreditCard card;
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index d49be23802a..6880d1b07b8 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -51,6 +51,7 @@ class AutofillWebDataService;
class CardUnmaskDelegate;
class CreditCard;
class FormStructure;
+class MigratableCreditCard;
class PersonalDataManager;
struct Suggestion;
@@ -123,8 +124,9 @@ class AutofillClient : public RiskDataLoader {
// context if possible, SECURITY_LEVEL_COUNT otherwise.
virtual security_state::SecurityLevel GetSecurityLevelForUmaHistograms() = 0;
- // Causes the Autofill settings UI to be shown.
- virtual void ShowAutofillSettings() = 0;
+ // Causes the Autofill settings UI to be shown. If |show_credit_card_settings|
+ // is true, will show the credit card specific subpage.
+ virtual void ShowAutofillSettings(bool show_credit_card_settings) = 0;
// Runs |callback| if the |profile| should be imported as personal data.
virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
@@ -137,8 +139,18 @@ class AutofillClient : public RiskDataLoader {
base::WeakPtr<CardUnmaskDelegate> delegate) = 0;
virtual void OnUnmaskVerificationResult(PaymentsRpcResult result) = 0;
- // Runs |closure| if the user accepts the migration process.
- virtual void ShowLocalCardMigrationPrompt(base::OnceClosure closure) = 0;
+ // Runs |closure| if the user accepts the card migration offer. This causes
+ // the card migration dialog to be shown.
+ virtual void ShowLocalCardMigrationDialog(
+ base::OnceClosure show_migration_dialog_closure) = 0;
+
+ // Shows a dialog with the given |legal_message|. Runs |closure| if
+ // the user would like the selected |migratable_credit_cards| to be
+ // uploaded to cloud.
+ virtual void ConfirmMigrateLocalCardToCloud(
+ std::unique_ptr<base::DictionaryValue> legal_message,
+ std::vector<MigratableCreditCard>& migratable_credit_cards,
+ base::OnceClosure start_migrating_cards_closure) = 0;
// Runs |callback| if the |card| should be imported as personal data.
// |metric_logger| can be used to log user actions.
diff --git a/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler.cc b/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler.cc
index 06b9deec8e9..9a8b1f4606a 100644
--- a/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler.cc
@@ -5,7 +5,7 @@
#include "components/autofill/core/browser/autofill_credit_card_policy_handler.h"
#include "base/values.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
@@ -26,10 +26,6 @@ void AutofillCreditCardPolicyHandler::ApplyPolicySettings(
if (value && value->GetAsBoolean(&autofill_credit_card_enabled) &&
!autofill_credit_card_enabled) {
prefs->SetBoolean(autofill::prefs::kAutofillCreditCardEnabled, false);
- } else {
- // Temporary fix for M69. If there is no policy explicitly disabling this
- // pref, it should be set to true.
- prefs->SetBoolean(autofill::prefs::kAutofillCreditCardEnabled, true);
}
}
diff --git a/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler_unittest.cc b/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler_unittest.cc
index 4f548ca1b14..a6bd1013a26 100644
--- a/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_credit_card_policy_handler_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/values.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
@@ -24,16 +24,8 @@ TEST_F(AutofillCreditCardPolicyHandlerTest, Default) {
PrefValueMap prefs;
AutofillCreditCardPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
-
- // Temporary fix for M69. The pref is enabled by default unless it's disabled
- // by policy.
- const base::Value* value = nullptr;
- ASSERT_TRUE(
- prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, &value));
- EXPECT_TRUE(value);
- bool autofill_credit_card_enabled = false;
- ASSERT_TRUE(value->GetAsBoolean(&autofill_credit_card_enabled));
- EXPECT_TRUE(autofill_credit_card_enabled);
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, nullptr));
}
TEST_F(AutofillCreditCardPolicyHandlerTest, Enabled) {
@@ -46,15 +38,9 @@ TEST_F(AutofillCreditCardPolicyHandlerTest, Enabled) {
AutofillCreditCardPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
- // Temporary fix for M69. The pref is enabled by default unless it's disabled
- // by policy.
- const base::Value* value = nullptr;
- ASSERT_TRUE(
- prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, &value));
- EXPECT_TRUE(value);
- bool autofill_credit_card_enabled = false;
- ASSERT_TRUE(value->GetAsBoolean(&autofill_credit_card_enabled));
- EXPECT_TRUE(autofill_credit_card_enabled);
+ // Enabling Autofill for credit cards should not set the prefs.
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, nullptr));
}
TEST_F(AutofillCreditCardPolicyHandlerTest, Disabled) {
@@ -72,10 +58,10 @@ TEST_F(AutofillCreditCardPolicyHandlerTest, Disabled) {
EXPECT_TRUE(
prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, &value));
ASSERT_TRUE(value);
- bool autofill_credit_card_enabled = true;
- bool result = value->GetAsBoolean(&autofill_credit_card_enabled);
+ bool autofill_credt_card_enabled = true;
+ bool result = value->GetAsBoolean(&autofill_credt_card_enabled);
ASSERT_TRUE(result);
- EXPECT_FALSE(autofill_credit_card_enabled);
+ EXPECT_FALSE(autofill_credt_card_enabled);
}
} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index 7f2b78b89e0..9bb74de20be 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -16,6 +16,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/grit/components_scaled_resources.h"
#include "components/strings/grit/components_strings.h"
#include "third_party/icu/source/common/unicode/uscript.h"
@@ -240,6 +241,21 @@ bool SplitCJKName(const std::vector<base::StringPiece16>& name_tokens,
} // namespace
+std::string TruncateUTF8(const std::string& data) {
+ std::string trimmed_value;
+ base::TruncateUTF8ToByteSize(data, AutofillTable::kMaxDataLength,
+ &trimmed_value);
+ return trimmed_value;
+}
+
+bool IsCreditCardExpirationType(ServerFieldType type) {
+ return type == CREDIT_CARD_EXP_MONTH ||
+ type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
+ type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
+ type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
+ type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
+}
+
bool IsCJKName(base::StringPiece16 name) {
// The name is considered to be a CJK name if it is only CJK characters,
// spaces, and "middle dot" separators, with at least one CJK character, and
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.h b/chromium/components/autofill/core/browser/autofill_data_util.h
index 863b99d54ec..ee3ede76fc8 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.h
+++ b/chromium/components/autofill/core/browser/autofill_data_util.h
@@ -9,6 +9,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece_forward.h"
+#include "components/autofill/core/browser/field_types.h"
namespace autofill {
@@ -22,6 +23,12 @@ struct NameParts {
base::string16 family;
};
+// Truncates a string to the nearest UTF-8 character that will leave
+// the string less than or equal to the specified byte size.
+std::string TruncateUTF8(const std::string& data);
+
+bool IsCreditCardExpirationType(ServerFieldType type);
+
// Used to map Chrome card issuer networks to Payment Request API basic card
// payment spec issuer networks and icons.
// https://w3c.github.io/webpayments-methods-card/#method-id
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc
index 6c2fa15f626..1903d2e6ea2 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc
@@ -12,6 +12,8 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
@@ -24,7 +26,6 @@
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/variations/net/variations_http_headers.h"
@@ -42,7 +43,7 @@ namespace autofill {
namespace {
const size_t kMaxQueryGetSize = 1400; // 1.25KB
-const size_t kMaxFormCacheSize = 16;
+const size_t kAutofillDownloadManagerMaxFormCacheSize = 16;
const size_t kMaxFieldsPerQueryRequest = 100;
const net::BackoffEntry::Policy kAutofillBackoffPolicy = {
@@ -76,6 +77,9 @@ const char kDefaultAutofillServerURL[] =
// Returns the base URL for the autofill server.
GURL GetAutofillServerURL() {
+ // If a valid autofill server URL is specified on the command line, then the
+ // AutofillDownlaodManager will use it, and assume that server communication
+ // is enabled.
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kAutofillServerURL)) {
@@ -83,63 +87,100 @@ GURL GetAutofillServerURL() {
if (url.is_valid())
return url;
- LOG(ERROR) << "Invalid URL given for --" << switches::kAutofillServerURL
- << ". Using default value.";
+ LOG(ERROR) << "Invalid URL value for --" << switches::kAutofillServerURL
+ << ": "
+ << command_line.GetSwitchValueASCII(
+ switches::kAutofillServerURL);
}
- GURL default_url(kDefaultAutofillServerURL);
- DCHECK(default_url.is_valid());
- return default_url;
+ // If communication is disabled, leave the autofill server URL unset.
+ if (!base::FeatureList::IsEnabled(features::kAutofillServerCommunication))
+ return GURL();
+
+ // Server communication is enabled. If there's an autofill server url param
+ // use it, otherwise use the default.
+ const std::string autofill_server_url_str =
+ base::FeatureParam<std::string>(&features::kAutofillServerCommunication,
+ switches::kAutofillServerURL,
+ kDefaultAutofillServerURL)
+ .Get();
+
+ GURL autofill_server_url(autofill_server_url_str);
+
+ if (!autofill_server_url.is_valid()) {
+ LOG(ERROR) << "Invalid URL param for "
+ << features::kAutofillServerCommunication.name << "/"
+ << switches::kAutofillServerURL << ": "
+ << autofill_server_url_str;
+ return GURL();
+ }
+
+ return autofill_server_url;
}
-// Helper to log the HTTP |response_code| received for |request_type| to UMA.
-void LogHttpResponseCode(AutofillDownloadManager::RequestType request_type,
- int response_code) {
- const char* name = nullptr;
+// Helper to log the HTTP |response_code| and other data received for
+// |request_type| to UMA.
+void LogHttpResponseData(AutofillDownloadManager::RequestType request_type,
+ int response_code,
+ int net_error,
+ base::TimeDelta request_duration) {
+ int response_or_error_code =
+ (net_error == net::OK || net_error == net::ERR_FAILED) ? response_code
+ : net_error;
switch (request_type) {
case AutofillDownloadManager::REQUEST_QUERY:
- name = "Autofill.Query.HttpResponseCode";
+ base::UmaHistogramSparse("Autofill.Query.HttpResponseOrErrorCode",
+ response_or_error_code);
+ UMA_HISTOGRAM_TIMES("Autofill.Query.RequestDuration", request_duration);
break;
case AutofillDownloadManager::REQUEST_UPLOAD:
- name = "Autofill.Upload.HttpResponseCode";
+ base::UmaHistogramSparse("Autofill.Upload.HttpResponseOrErrorCode",
+ response_or_error_code);
+ UMA_HISTOGRAM_TIMES("Autofill.Upload.RequestDuration", request_duration);
break;
default:
NOTREACHED();
- name = "Autofill.Unknown.HttpResponseCode";
+ base::UmaHistogramSparse("Autofill.Unknown.HttpResponseOrErrorCode",
+ response_or_error_code);
+ UMA_HISTOGRAM_TIMES("Autofill.Unknown.RequestDuration", request_duration);
}
-
- if (response_code < 100 || response_code > 599)
- response_code = 0;
-
- // An expanded version of UMA_HISTOGRAM_ENUMERATION that supports using
- // a different name with each invocation.
- base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
- name, 1, 599, 600, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(response_code);
}
// Helper to log, to UMA, the |num_bytes| sent for a failing instance of
// |request_type|.
void LogFailingPayloadSize(AutofillDownloadManager::RequestType request_type,
size_t num_bytes) {
- const char* name = nullptr;
switch (request_type) {
case AutofillDownloadManager::REQUEST_QUERY:
- name = "Autofill.Query.FailingPayloadSize";
+ UMA_HISTOGRAM_COUNTS_100000("Autofill.Query.FailingPayloadSize",
+ num_bytes);
break;
case AutofillDownloadManager::REQUEST_UPLOAD:
- name = "Autofill.Upload.FailingPayloadSize";
+ UMA_HISTOGRAM_COUNTS_100000("Autofill.Upload.FailingPayloadSize",
+ num_bytes);
break;
default:
NOTREACHED();
- name = "Autofill.Unknown.FailingPayloadSize";
+ UMA_HISTOGRAM_COUNTS_100000("Autofill.Unknown.FailingPayloadSize",
+ num_bytes);
}
+}
- // An expanded version of UMA_HISTOGRAM_COUNTS_100000 that supports using
- // a different name with each invocation.
- base::HistogramBase* histogram = base::Histogram::FactoryGet(
- name, 1, 100000, 50, base::HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(num_bytes);
+// Helper to log, to UMA, the |delay| caused by exponential backoff.
+void LogExponentialBackoffDelay(
+ AutofillDownloadManager::RequestType request_type,
+ base::TimeDelta delay) {
+ switch (request_type) {
+ case AutofillDownloadManager::REQUEST_QUERY:
+ UMA_HISTOGRAM_MEDIUM_TIMES("Autofill.Query.BackoffDelay", delay);
+ break;
+ case AutofillDownloadManager::REQUEST_UPLOAD:
+ UMA_HISTOGRAM_MEDIUM_TIMES("Autofill.Upload.BackoffDelay", delay);
+ break;
+ default:
+ NOTREACHED();
+ UMA_HISTOGRAM_MEDIUM_TIMES("Autofill.Unknown.BackoffDelay", delay);
+ }
}
net::NetworkTrafficAnnotationTag GetNetworkTrafficAnnotation(
@@ -259,8 +300,11 @@ std::ostream& operator<<(std::ostream& out,
for (const auto& field : upload.field()) {
out << "\n Field"
- << "\n signature: " << field.signature()
- << "\n autofill_type: " << field.autofill_type();
+ << "\n signature: " << field.signature() << "\n autofill_type: ["
+ << field.autofill_type(0);
+ for (int i = 1; i < field.autofill_type_size(); ++i)
+ out << ", " << field.autofill_type(i);
+ out << "]";
if (!field.name().empty())
out << "\n name: " << field.name();
if (!field.autocomplete().empty())
@@ -286,7 +330,7 @@ AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver,
: driver_(driver),
observer_(observer),
autofill_server_url_(GetAutofillServerURL()),
- max_form_cache_size_(kMaxFormCacheSize),
+ max_form_cache_size_(kAutofillDownloadManagerMaxFormCacheSize),
loader_backoff_(&kAutofillBackoffPolicy),
weak_factory_(this) {
DCHECK(observer_);
@@ -296,6 +340,9 @@ AutofillDownloadManager::~AutofillDownloadManager() = default;
bool AutofillDownloadManager::StartQueryRequest(
const std::vector<FormStructure*>& forms) {
+ if (!IsEnabled())
+ return false;
+
// Do not send the request if it contains more fields than the server can
// accept.
if (CountActiveFieldsInForms(forms) > kMaxFieldsPerQueryRequest)
@@ -337,6 +384,9 @@ bool AutofillDownloadManager::StartUploadRequest(
const ServerFieldTypeSet& available_field_types,
const std::string& login_form_signature,
bool observed_submission) {
+ if (!IsEnabled())
+ return false;
+
AutofillUploadContents upload;
if (!form.EncodeUploadRequest(available_field_types, form_was_autofilled,
login_form_signature, observed_submission,
@@ -429,7 +479,7 @@ bool AutofillDownloadManager::StartRequest(FormRequestData request_data) {
url_loader_factory.get(),
base::BindOnce(&AutofillDownloadManager::OnSimpleLoaderComplete,
base::Unretained(this), std::move(--url_loaders_.end()),
- std::move(request_data)));
+ std::move(request_data), base::TimeTicks::Now()));
return true;
}
@@ -488,13 +538,16 @@ std::string AutofillDownloadManager::GetCombinedSignature(
void AutofillDownloadManager::OnSimpleLoaderComplete(
std::list<std::unique_ptr<network::SimpleURLLoader>>::iterator it,
FormRequestData request_data,
+ base::TimeTicks request_start,
std::unique_ptr<std::string> response_body) {
// Move the loader out of the active loaders list.
std::unique_ptr<network::SimpleURLLoader> simple_loader = std::move(*it);
url_loaders_.erase(it);
CHECK(request_data.form_signatures.size());
- int response_code = -1;
+ // net:ERR_FAILED is not an HTTP response code, but if none is available, the
+ // UMA logging can accept this as a generic fallback as well.
+ int response_code = net::ERR_FAILED;
if (simple_loader->ResponseInfo() && simple_loader->ResponseInfo()->headers) {
response_code = simple_loader->ResponseInfo()->headers->response_code();
}
@@ -502,7 +555,9 @@ void AutofillDownloadManager::OnSimpleLoaderComplete(
const bool success = !!response_body;
loader_backoff_.InformOfRequest(success);
- LogHttpResponseCode(request_data.request_type, response_code);
+ LogHttpResponseData(request_data.request_type, response_code,
+ simple_loader->NetError(),
+ base::TimeTicks::Now() - request_start);
if (!success) {
DVLOG(1) << "AutofillDownloadManager: "
@@ -519,6 +574,9 @@ void AutofillDownloadManager::OnSimpleLoaderComplete(
if (response_code >= 400 && response_code <= 499)
return;
+ base::TimeDelta backoff = loader_backoff_.GetTimeUntilRelease();
+ LogExponentialBackoffDelay(request_data.request_type, backoff);
+
// Reschedule with the appropriate delay, ignoring return value because
// payload is already well formed.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
@@ -526,7 +584,7 @@ void AutofillDownloadManager::OnSimpleLoaderComplete(
base::BindOnce(
base::IgnoreResult(&AutofillDownloadManager::StartRequest),
weak_factory_.GetWeakPtr(), std::move(request_data)),
- loader_backoff_.GetTimeUntilRelease());
+ backoff);
return;
}
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.h b/chromium/components/autofill/core/browser/autofill_download_manager.h
index 675bb0dde30..c1b7b97b837 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.h
@@ -88,6 +88,9 @@ class AutofillDownloadManager {
const std::string& login_form_signature,
bool observed_submission);
+ // Returns true if the autofill server communication is enabled.
+ bool IsEnabled() const { return autofill_server_url_.is_valid(); }
+
private:
friend class AutofillDownloadManagerTest;
FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, QueryAndUploadTest);
@@ -132,6 +135,7 @@ class AutofillDownloadManager {
void OnSimpleLoaderComplete(
std::list<std::unique_ptr<network::SimpleURLLoader>>::iterator it,
FormRequestData request_data,
+ base::TimeTicks request_start,
std::unique_ptr<std::string> response_body);
// The AutofillDriver that this instance will use. Must not be null, and must
@@ -144,7 +148,7 @@ class AutofillDownloadManager {
// The autofill server URL root: scheme://host[:port]/path excluding the
// final path component for the request and the query params.
- GURL autofill_server_url_;
+ const GURL autofill_server_url_;
// Loaders used for the processing the requests. Invalidated after completion.
std::list<std::unique_ptr<network::SimpleURLLoader>> url_loaders_;
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 af9142ea5ac..f0e8e5ed501 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -18,7 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
@@ -281,15 +281,15 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
auto* request = GetPendingRequest(1);
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
request, responses[1]);
- histogram.ExpectBucketCount("Autofill.Upload.HttpResponseCode", net::HTTP_OK,
- 1);
+ histogram.ExpectBucketCount("Autofill.Upload.HttpResponseOrErrorCode",
+ net::HTTP_OK, 1);
// Request 2: Unsuccessful upload.
request = GetPendingRequest(2);
test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
request, network::CreateResourceResponseHead(net::HTTP_NOT_FOUND),
responses[2], network::URLLoaderCompletionStatus(net::OK));
- histogram.ExpectBucketCount("Autofill.Upload.HttpResponseCode",
+ histogram.ExpectBucketCount("Autofill.Upload.HttpResponseOrErrorCode",
net::HTTP_NOT_FOUND, 1);
// Request 0: Successful query.
@@ -298,8 +298,8 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
request, responses[0]);
EXPECT_EQ(3U, responses_.size());
histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1);
- histogram.ExpectBucketCount("Autofill.Query.HttpResponseCode", net::HTTP_OK,
- 1);
+ histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode",
+ net::HTTP_OK, 1);
// Check Request 1.
EXPECT_EQ(AutofillDownloadManagerTest::UPLOAD_SUCCESSFULL,
@@ -346,7 +346,7 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
request,
network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR),
responses[0], network::URLLoaderCompletionStatus(net::OK));
- histogram.ExpectBucketCount("Autofill.Query.HttpResponseCode",
+ histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode",
net::HTTP_INTERNAL_SERVER_ERROR, 1);
// Check Request 4.
@@ -465,7 +465,7 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Query) {
// There should not be an additional retry.
ASSERT_EQ(test_url_loader_factory_.NumPending(), 0);
- histogram.ExpectBucketCount("Autofill.Query.HttpResponseCode",
+ histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode",
net::HTTP_REQUEST_ENTITY_TOO_LARGE, 1);
auto buckets = histogram.GetAllSamples("Autofill.Query.FailingPayloadSize");
ASSERT_EQ(1U, buckets.size());
@@ -550,7 +550,7 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) {
network::CreateResourceResponseHead(net::HTTP_REQUEST_ENTITY_TOO_LARGE),
"", network::URLLoaderCompletionStatus(net::OK));
ASSERT_EQ(test_url_loader_factory_.NumPending(), 0);
- histogram.ExpectBucketCount("Autofill.Upload.HttpResponseCode",
+ histogram.ExpectBucketCount("Autofill.Upload.HttpResponseOrErrorCode",
net::HTTP_REQUEST_ENTITY_TOO_LARGE, 1);
auto buckets = histogram.GetAllSamples("Autofill.Upload.FailingPayloadSize");
ASSERT_EQ(1U, buckets.size());
@@ -750,27 +750,60 @@ TEST_F(AutofillDownloadManagerTest, CacheQueryTest) {
namespace {
-class AutofillQueryTest : public AutofillDownloadManager::Observer,
- public testing::Test {
+enum ServerCommuncationMode {
+ DISABLED,
+ FINCHED_URL,
+ COMMAND_LINE_URL,
+ DEFAULT_URL
+};
+
+class AutofillServerCommunicationTest
+ : public AutofillDownloadManager::Observer,
+ public testing::TestWithParam<ServerCommuncationMode> {
protected:
void SetUp() override {
- scoped_feature_list_.InitAndEnableFeature(
+ testing::TestWithParam<ServerCommuncationMode>::SetUp();
+
+ scoped_feature_list_1_.InitAndEnableFeature(
features::kAutofillCacheQueryResponses);
// Setup the server.
- server_.RegisterRequestHandler(base::BindRepeating(
- &AutofillQueryTest::RequestHandler, base::Unretained(this)));
+ server_.RegisterRequestHandler(
+ base::BindRepeating(&AutofillServerCommunicationTest::RequestHandler,
+ base::Unretained(this)));
ASSERT_TRUE(server_.Start());
- scoped_command_line_.GetProcessCommandLine()->AppendSwitchASCII(
- switches::kAutofillServerURL,
- server_.base_url().Resolve("/tbproxy/af/").spec().c_str());
+ GURL autofill_server_url(server_.base_url().Resolve("/tbproxy/af/"));
+ ASSERT_TRUE(autofill_server_url.is_valid());
// Intialize the autofill driver.
shared_url_loader_factory_ =
base::MakeRefCounted<network::TestSharedURLLoaderFactory>();
driver_ = std::make_unique<TestAutofillDriver>();
driver_->SetSharedURLLoaderFactory(shared_url_loader_factory_);
+
+ // Configure the autofill server communications channel.
+ switch (GetParam()) {
+ case DISABLED:
+ scoped_feature_list_2_.InitAndDisableFeature(
+ features::kAutofillServerCommunication);
+ break;
+ case FINCHED_URL:
+ scoped_feature_list_2_.InitAndEnableFeatureWithParameters(
+ features::kAutofillServerCommunication,
+ {{switches::kAutofillServerURL, autofill_server_url.spec()}});
+ break;
+ case COMMAND_LINE_URL:
+ scoped_command_line_.GetProcessCommandLine()->AppendSwitchASCII(
+ switches::kAutofillServerURL, autofill_server_url.spec());
+ FALLTHROUGH;
+ case DEFAULT_URL:
+ scoped_feature_list_2_.InitAndEnableFeature(
+ features::kAutofillServerCommunication);
+ break;
+ default:
+ ASSERT_TRUE(false);
+ }
}
void TearDown() override {
@@ -786,45 +819,78 @@ class AutofillQueryTest : public AutofillDownloadManager::Observer,
run_loop_->QuitWhenIdle();
}
+ void OnUploadedPossibleFieldTypes() override {
+ ASSERT_TRUE(run_loop_);
+ run_loop_->QuitWhenIdle();
+ }
+
std::unique_ptr<HttpResponse> RequestHandler(const HttpRequest& request) {
GURL absolute_url = server_.GetURL(request.relative_url);
++call_count_;
- if (absolute_url.path() != "/tbproxy/af/query")
- return nullptr;
+ if (absolute_url.path() == "/tbproxy/af/query") {
+ AutofillQueryResponseContents proto;
+ proto.add_field()->set_overall_type_prediction(NAME_FIRST);
+
+ auto response = std::make_unique<BasicHttpResponse>();
+ response->set_code(net::HTTP_OK);
+ response->set_content(proto.SerializeAsString());
+ response->set_content_type("text/proto");
+ response->AddCustomHeader(
+ "Cache-Control",
+ base::StringPrintf("max-age=%" PRId64,
+ base::TimeDelta::FromMilliseconds(
+ cache_expiration_in_milliseconds_)
+ .InSeconds()));
+ return response;
+ }
+
+ if (absolute_url.path() == "/tbproxy/af/upload") {
+ auto response = std::make_unique<BasicHttpResponse>();
+ response->set_code(net::HTTP_OK);
+ return response;
+ }
- AutofillQueryResponseContents proto;
- proto.add_field()->set_overall_type_prediction(NAME_FIRST);
-
- auto response = std::make_unique<BasicHttpResponse>();
- response->set_code(net::HTTP_OK);
- response->set_content(proto.SerializeAsString());
- response->set_content_type("text/proto");
- response->AddCustomHeader(
- "Cache-Control",
- base::StringPrintf(
- "max-age=%" PRId64,
- base::TimeDelta::FromMilliseconds(cache_expiration_in_milliseconds_)
- .InSeconds()));
- return response;
+ return nullptr;
}
- void SendQueryRequest(
+ bool SendQueryRequest(
const std::vector<std::unique_ptr<FormStructure>>& form_structures) {
- ASSERT_TRUE(run_loop_ == nullptr);
+ EXPECT_EQ(run_loop_, nullptr);
run_loop_ = std::make_unique<base::RunLoop>();
AutofillDownloadManager download_manager(driver_.get(), this);
- ASSERT_TRUE(download_manager.StartQueryRequest(
- ToRawPointerVector(form_structures)));
- run_loop_->Run();
+ bool succeeded =
+ download_manager.StartQueryRequest(ToRawPointerVector(form_structures));
+ if (succeeded)
+ run_loop_->Run();
run_loop_.reset();
+ return succeeded;
+ }
+
+ bool SendUploadRequest(const FormStructure& form,
+ bool form_was_autofilled,
+ const ServerFieldTypeSet& available_field_types,
+ const std::string& login_form_signature,
+ bool observed_submission) {
+ EXPECT_EQ(run_loop_, nullptr);
+ run_loop_ = std::make_unique<base::RunLoop>();
+
+ AutofillDownloadManager download_manager(driver_.get(), this);
+ bool succeeded = download_manager.StartUploadRequest(
+ form, form_was_autofilled, available_field_types, login_form_signature,
+ observed_submission);
+ if (succeeded)
+ run_loop_->Run();
+ run_loop_.reset();
+ return succeeded;
}
base::test::ScopedTaskEnvironment scoped_task_environment_{
base::test::ScopedTaskEnvironment::MainThreadType::IO};
base::test::ScopedCommandLine scoped_command_line_;
- base::test::ScopedFeatureList scoped_feature_list_;
+ base::test::ScopedFeatureList scoped_feature_list_1_;
+ base::test::ScopedFeatureList scoped_feature_list_2_;
EmbeddedTestServer server_;
int cache_expiration_in_milliseconds_ = 100000;
std::unique_ptr<base::RunLoop> run_loop_;
@@ -835,7 +901,61 @@ class AutofillQueryTest : public AutofillDownloadManager::Observer,
} // namespace
-TEST_F(AutofillQueryTest, CacheableResponse) {
+TEST_P(AutofillServerCommunicationTest, IsEnabled) {
+ AutofillDownloadManager download_manager(driver_.get(), this);
+ EXPECT_EQ(download_manager.IsEnabled(), GetParam() != DISABLED);
+}
+
+TEST_P(AutofillServerCommunicationTest, Query) {
+ FormData form;
+ FormFieldData field;
+
+ field.label = ASCIIToUTF16("First Name:");
+ field.name = ASCIIToUTF16("firstname");
+ field.form_control_type = "text";
+ form.fields.push_back(field);
+
+ std::vector<std::unique_ptr<FormStructure>> form_structures;
+ form_structures.push_back(std::make_unique<FormStructure>(form));
+
+ EXPECT_EQ(GetParam() != DISABLED, SendQueryRequest(form_structures));
+}
+
+TEST_P(AutofillServerCommunicationTest, Upload) {
+ FormData form;
+ FormFieldData field;
+
+ field.label = ASCIIToUTF16("First Name:");
+ field.name = ASCIIToUTF16("firstname");
+ field.form_control_type = "text";
+ form.fields.push_back(field);
+
+ field.label = ASCIIToUTF16("Last Name:");
+ field.name = ASCIIToUTF16("lastname");
+ field.form_control_type = "text";
+ form.fields.push_back(field);
+
+ field.label = ASCIIToUTF16("Email:");
+ field.name = ASCIIToUTF16("email");
+ field.form_control_type = "text";
+ form.fields.push_back(field);
+
+ AutofillDownloadManager download_manager(driver_.get(), this);
+ EXPECT_EQ(GetParam() != DISABLED,
+ SendUploadRequest(FormStructure(form), true, {}, "", true));
+}
+
+// Note that we omit DEFAULT_URL from the test params. We don't actually want
+// the tests to hit the production server.
+INSTANTIATE_TEST_CASE_P(All,
+ AutofillServerCommunicationTest,
+ ::testing::Values(DISABLED,
+ FINCHED_URL,
+ COMMAND_LINE_URL));
+
+using AutofillQueryTest = AutofillServerCommunicationTest;
+
+TEST_P(AutofillQueryTest, CacheableResponse) {
FormFieldData field;
field.label = ASCIIToUTF16("First Name:");
field.name = ASCIIToUTF16("firstname");
@@ -852,7 +972,7 @@ TEST_F(AutofillQueryTest, CacheableResponse) {
SCOPED_TRACE("First Query");
base::HistogramTester histogram;
call_count_ = 0;
- ASSERT_NO_FATAL_FAILURE(SendQueryRequest(form_structures));
+ ASSERT_TRUE(SendQueryRequest(form_structures));
EXPECT_EQ(1u, call_count_);
histogram.ExpectBucketCount("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -866,7 +986,7 @@ TEST_F(AutofillQueryTest, CacheableResponse) {
SCOPED_TRACE("Second Query");
base::HistogramTester histogram;
call_count_ = 0;
- ASSERT_NO_FATAL_FAILURE(SendQueryRequest(form_structures));
+ ASSERT_TRUE(SendQueryRequest(form_structures));
EXPECT_EQ(0u, call_count_);
histogram.ExpectBucketCount("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -875,7 +995,7 @@ TEST_F(AutofillQueryTest, CacheableResponse) {
}
}
-TEST_F(AutofillQueryTest, ExpiredCacheInResponse) {
+TEST_P(AutofillQueryTest, ExpiredCacheInResponse) {
FormFieldData field;
field.label = ASCIIToUTF16("First Name:");
field.name = ASCIIToUTF16("firstname");
@@ -895,7 +1015,7 @@ TEST_F(AutofillQueryTest, ExpiredCacheInResponse) {
SCOPED_TRACE("First Query");
base::HistogramTester histogram;
call_count_ = 0;
- ASSERT_NO_FATAL_FAILURE(SendQueryRequest(form_structures));
+ ASSERT_TRUE(SendQueryRequest(form_structures));
EXPECT_EQ(1u, call_count_);
histogram.ExpectBucketCount("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -916,7 +1036,7 @@ TEST_F(AutofillQueryTest, ExpiredCacheInResponse) {
SCOPED_TRACE("Second Query");
base::HistogramTester histogram;
call_count_ = 0;
- ASSERT_NO_FATAL_FAILURE(SendQueryRequest(form_structures));
+ ASSERT_TRUE(SendQueryRequest(form_structures));
EXPECT_EQ(1u, call_count_);
histogram.ExpectBucketCount("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_SENT, 1);
@@ -925,4 +1045,11 @@ TEST_F(AutofillQueryTest, ExpiredCacheInResponse) {
}
}
+// Note that we omit DEFAULT_URL from the test params. We don't actually want
+// the tests to hit the production server. We also excluded DISABLED, since
+// these tests exercise "enabled" functionality.
+INSTANTIATE_TEST_CASE_P(All,
+ AutofillQueryTest,
+ ::testing::Values(FINCHED_URL, COMMAND_LINE_URL));
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index 35548d3eea4..22d8d06286b 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -13,7 +14,7 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
@@ -26,112 +27,41 @@
namespace autofill {
-const base::Feature kAutofillAlwaysFillAddresses{
- "AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillCreateDataForTest{
- "AutofillCreateDataForTest", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillCreditCardAssist{
- "AutofillCreditCardAssist", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillScanCardholderName{
- "AutofillScanCardholderName", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillCreditCardAblationExperiment{
- "AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillCreditCardLocalCardMigration{
- "AutofillCreditCardLocalCardMigration", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillDeleteDisusedAddresses{
- "AutofillDeleteDisusedAddresses", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillDeleteDisusedCreditCards{
- "AutofillDeleteDisusedCreditCards", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillExpandedPopupViews{
- "AutofillExpandedPopupViews", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillPreferServerNamePredictions{
- "AutofillPreferServerNamePredictions", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillRationalizeFieldTypePredictions{
- "AutofillRationalizeFieldTypePredictions",
- base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate{
- "AutofillSaveCardDialogUnlabeledExpirationDate",
- base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillSuggestInvalidProfileData{
- "AutofillSuggestInvalidProfileData", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillSuppressDisusedAddresses{
- "AutofillSuppressDisusedAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillSuppressDisusedCreditCards{
- "AutofillSuppressDisusedCreditCards", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstream{"AutofillUpstream",
- base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamAllowAllEmailDomains{
- "AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamAlwaysRequestCardholderName{
- "AutofillUpstreamAlwaysRequestCardholderName",
- base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamBlankCardholderNameField{
- "AutofillUpstreamBlankCardholderNameField",
- base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamEditableCardholderName{
- "AutofillUpstreamEditableCardholderName",
- base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamSendPanFirstSix{
- "AutofillUpstreamSendPanFirstSix", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamUpdatePromptExplanation{
- "AutofillUpstreamUpdatePromptExplanation",
- base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillVoteUsingInvalidProfileData{
- "AutofillVoteUsingInvalidProfileData", base::FEATURE_ENABLED_BY_DEFAULT};
-
-const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
-
-#if defined(OS_MACOSX)
-const base::Feature kMacViewsAutofillPopup{"MacViewsAutofillPopup",
- base::FEATURE_ENABLED_BY_DEFAULT};
-#endif // defined(OS_MACOSX)
-
-bool IsAutofillEnabled(const PrefService* pref_service) {
- return pref_service->GetBoolean(prefs::kAutofillEnabled);
-}
-
-bool IsInAutofillSuggestionsDisabledExperiment() {
- std::string group_name =
- base::FieldTrialList::FindFullName("AutofillEnabled");
- return group_name == "Disabled";
-}
-
-bool IsAutofillCreditCardAssistEnabled() {
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
- return false;
-#else
- return base::FeatureList::IsEnabled(kAutofillCreditCardAssist);
-#endif
-}
-
-bool IsAutofillCreditCardLocalCardMigrationExperimentEnabled() {
- return base::FeatureList::IsEnabled(kAutofillCreditCardLocalCardMigration);
-}
-
-bool OfferStoreUnmaskedCards() {
-#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
- // Query the field trial before checking command line flags to ensure UMA
- // reports the correct group.
- std::string group_name =
- base::FieldTrialList::FindFullName("OfferStoreUnmaskedWalletCards");
-
- // The checkbox can be forced on or off with flags.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableOfferStoreUnmaskedWalletCards))
- return true;
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableOfferStoreUnmaskedWalletCards))
- return false;
-
- // Otherwise use the field trial to show the checkbox or not.
- return group_name != "Disabled";
-#endif
+#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_ANDROID)
+const base::Feature kAutofillDropdownLayoutExperiment{
+ "AutofillDropdownLayout", base::FEATURE_DISABLED_BY_DEFAULT};
+const char kAutofillDropdownLayoutParameterName[] = "variant";
+const char kAutofillDropdownLayoutParameterLeadingIcon[] = "leading-icon";
+const char kAutofillDropdownLayoutParameterTrailingIcon[] = "trailing-icon";
+#endif // !defined(OS_ANDROID)
+
+#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,
@@ -159,70 +89,129 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
return false;
// Check Payments integration user setting.
- if (!pref_service->GetBoolean(prefs::kAutofillWalletImportEnabled))
+ if (!prefs::IsPaymentsIntegrationEnabled(pref_service))
return false;
// Check that the user is logged into a supported domain.
if (user_email.empty())
return false;
+
std::string domain = gaia::ExtractDomainName(user_email);
// If the "allow all email domains" flag is off, restrict credit card upload
// only to Google Accounts with @googlemail, @gmail, @google, or @chromium
// domains.
- if (!base::FeatureList::IsEnabled(kAutofillUpstreamAllowAllEmailDomains) &&
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillUpstreamAllowAllEmailDomains) &&
!(domain == "googlemail.com" || domain == "gmail.com" ||
domain == "google.com" || domain == "chromium.org")) {
return false;
}
- return base::FeatureList::IsEnabled(kAutofillUpstream);
+ return base::FeatureList::IsEnabled(features::kAutofillUpstream);
}
-bool IsAutofillUpstreamAlwaysRequestCardholderNameExperimentEnabled() {
- return base::FeatureList::IsEnabled(
- kAutofillUpstreamAlwaysRequestCardholderName);
+bool IsInAutofillSuggestionsDisabledExperiment() {
+ std::string group_name =
+ base::FieldTrialList::FindFullName("AutofillEnabled");
+ return group_name == "Disabled";
}
-bool IsAutofillUpstreamBlankCardholderNameFieldExperimentEnabled() {
- return base::FeatureList::IsEnabled(
- kAutofillUpstreamBlankCardholderNameField);
+bool IsAutofillCreditCardAssistEnabled() {
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ return false;
+#else
+ return base::FeatureList::IsEnabled(features::kAutofillCreditCardAssist);
+#endif
}
-bool IsAutofillUpstreamEditableCardholderNameExperimentEnabled() {
- return base::FeatureList::IsEnabled(kAutofillUpstreamEditableCardholderName);
+features::LocalCardMigrationExperimentalFlag
+GetLocalCardMigrationExperimentalFlag() {
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardLocalCardMigration))
+ return features::LocalCardMigrationExperimentalFlag::kMigrationDisabled;
+
+ std::string param = base::GetFieldTrialParamValueByFeature(
+ features::kAutofillCreditCardLocalCardMigration,
+ features::kAutofillCreditCardLocalCardMigrationParameterName);
+
+ if (param ==
+ features::
+ kAutofillCreditCardLocalCardMigrationParameterWithoutSettingsPage) {
+ return features::LocalCardMigrationExperimentalFlag::
+ kMigrationWithoutSettingsPage;
+ }
+ return features::LocalCardMigrationExperimentalFlag::
+ kMigrationIncludeSettingsPage;
}
-bool IsAutofillUpstreamSendPanFirstSixExperimentEnabled() {
- return base::FeatureList::IsEnabled(kAutofillUpstreamSendPanFirstSix);
+bool IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled() {
+ return base::FeatureList::IsEnabled(
+ features::kAutofillNoLocalSaveOnUploadSuccess);
}
-bool IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled() {
- return base::FeatureList::IsEnabled(kAutofillUpstreamUpdatePromptExplanation);
-}
+bool OfferStoreUnmaskedCards() {
+#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
+ // Query the field trial before checking command line flags to ensure UMA
+ // reports the correct group.
+ std::string group_name =
+ base::FieldTrialList::FindFullName("OfferStoreUnmaskedWalletCards");
-#if defined(OS_MACOSX)
-bool IsMacViewsAutofillPopupExperimentEnabled() {
-#if BUILDFLAG(MAC_VIEWS_BROWSER)
- if (!::features::IsViewsBrowserCocoa())
+ // The checkbox can be forced on or off with flags.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableOfferStoreUnmaskedWalletCards))
return true;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableOfferStoreUnmaskedWalletCards))
+ return false;
+
+ // Otherwise use the field trial to show the checkbox or not.
+ return group_name != "Disabled";
#endif
+}
- return base::FeatureList::IsEnabled(kMacViewsAutofillPopup);
+bool ShouldUseActiveSignedInAccount() {
+ // If butter is enabled or the feature to get the Payment Identity from Sync
+ // is enabled, the account of the active signed-in user should be used.
+ return base::FeatureList::IsEnabled(
+ features::kAutofillEnableAccountWalletStorage) ||
+ base::FeatureList::IsEnabled(
+ features::kAutofillGetPaymentsIdentityFromSync);
}
-#endif // defined(OS_MACOSX)
-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
+#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)
-bool IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled() {
- return base::FeatureList::IsEnabled(
- kAutofillSaveCardDialogUnlabeledExpirationDate);
+#if !defined(OS_ANDROID)
+ForcedPopupLayoutState GetForcedPopupLayoutState() {
+ if (!base::FeatureList::IsEnabled(kAutofillDropdownLayoutExperiment))
+ return ForcedPopupLayoutState::kDefault;
+
+ std::string param = base::GetFieldTrialParamValueByFeature(
+ kAutofillDropdownLayoutExperiment, kAutofillDropdownLayoutParameterName);
+
+ if (param == kAutofillDropdownLayoutParameterLeadingIcon) {
+ return ForcedPopupLayoutState::kLeadingIcon;
+ } else if (param == kAutofillDropdownLayoutParameterTrailingIcon) {
+ return ForcedPopupLayoutState::kTrailingIcon;
+ }
+
+ // Unknown parameter value.
+ NOTREACHED();
+ return ForcedPopupLayoutState::kDefault;
}
+#endif // !defined(OS_ANDROID)
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.h b/chromium/components/autofill/core/browser/autofill_experiments.h
index 7264f45c5fe..7cada16372b 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.h
+++ b/chromium/components/autofill/core/browser/autofill_experiments.h
@@ -22,40 +22,27 @@ class SyncService;
namespace autofill {
-extern const base::Feature kAutofillAlwaysFillAddresses;
-extern const base::Feature kAutofillCreateDataForTest;
-extern const base::Feature kAutofillCreditCardAssist;
-extern const base::Feature kAutofillScanCardholderName;
-extern const base::Feature kAutofillCreditCardAblationExperiment;
-extern const base::Feature kAutofillCreditCardLocalCardMigration;
-extern const base::Feature kAutofillDeleteDisusedAddresses;
-extern const base::Feature kAutofillDeleteDisusedCreditCards;
-extern const base::Feature kAutofillExpandedPopupViews;
-extern const base::Feature kAutofillPreferServerNamePredictions;
-extern const base::Feature kAutofillRationalizeFieldTypePredictions;
-extern const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate;
-extern const base::Feature kAutofillSuggestInvalidProfileData;
-extern const base::Feature kAutofillSuppressDisusedAddresses;
-extern const base::Feature kAutofillSuppressDisusedCreditCards;
-extern const base::Feature kAutofillUpstream;
-extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
-extern const base::Feature kAutofillUpstreamAlwaysRequestCardholderName;
-extern const base::Feature kAutofillUpstreamBlankCardholderNameField;
-extern const base::Feature kAutofillUpstreamEditableCardholderName;
-extern const base::Feature kAutofillUpstreamSendPanFirstSix;
-extern const base::Feature kAutofillUpstreamUpdatePromptExplanation;
-extern const base::Feature kAutofillVoteUsingInvalidProfileData;
-extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
-extern const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[];
-extern const char kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey[];
-
-#if defined(OS_MACOSX)
-extern const base::Feature kMacViewsAutofillPopup;
-#endif // defined(OS_MACOSX)
-
-// Returns true if autofill should be enabled. See also
-// IsInAutofillSuggestionsDisabledExperiment below.
-bool IsAutofillEnabled(const PrefService* pref_service);
+// Parameterized Features (grouped with parameter name and options)
+#if !defined(OS_ANDROID)
+extern const base::Feature kAutofillDropdownLayoutExperiment;
+extern const char kAutofillDropdownLayoutParameterName[];
+extern const char kAutofillDropdownLayoutParameterLeadingIcon[];
+extern const char kAutofillDropdownLayoutParameterTrailingIcon[];
+#endif // !defined(OS_ANDROID)
+
+#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.
+bool IsCreditCardUploadEnabled(const PrefService* pref_service,
+ const syncer::SyncService* sync_service,
+ const std::string& user_email);
// Returns true if autofill suggestions are disabled via experiment. The
// disabled experiment isn't the same as disabling autofill completely since we
@@ -66,65 +53,44 @@ bool IsInAutofillSuggestionsDisabledExperiment();
// Returns whether the Autofill credit card assist infobar should be shown.
bool IsAutofillCreditCardAssistEnabled();
+// Returns whether locally saving card when credit card upload succeeds should
+// be disabled.
+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();
-// 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.
-bool IsCreditCardUploadEnabled(const PrefService* pref_service,
- const syncer::SyncService* sync_service,
- const std::string& user_email);
-
-// Returns whether Autofill credit card local card migration experiment is
-// enabled.
-bool IsAutofillCreditCardLocalCardMigrationExperimentEnabled();
-
-// For testing purposes; not to be launched. When enabled, Chrome Upstream
-// always requests that the user enters/confirms cardholder name in the
-// offer-to-save dialog, regardless of if it was present or if the user is a
-// Google Payments customer. Note that this will override the detected
-// cardholder name, if one was found.
-bool IsAutofillUpstreamAlwaysRequestCardholderNameExperimentEnabled();
-
-// For experimental purposes; not to be made available in chrome://flags. When
-// enabled and Chrome Upstream requests the cardholder name in the offer-to-save
-// dialog, the field will be blank instead of being prefilled with the name from
-// the user's Google Account.
-bool IsAutofillUpstreamBlankCardholderNameFieldExperimentEnabled();
-
-// Returns whether the experiment is enabled where Chrome Upstream can request
-// the user to enter/confirm cardholder name in the offer-to-save bubble if it
-// was not detected or was conflicting during the checkout flow and the user is
-// NOT a Google Payments customer.
-bool IsAutofillUpstreamEditableCardholderNameExperimentEnabled();
-
-// Returns whether the experiment is enabled where Chrome Upstream sends the
-// first six digits of the card PAN to Google Payments to help determine whether
-// card upload is possible.
-bool IsAutofillUpstreamSendPanFirstSixExperimentEnabled();
-
-// Returns whether the experiment is enbaled where upstream sends updated
-// prompt explanation which changes 'save this card' to 'save your card and
-// billing address.'
-bool IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled();
-
-#if defined(OS_MACOSX)
-// Returns true if whether the views autofill popup feature is enabled or the
-// we're using the views browser.
-bool IsMacViewsAutofillPopupExperimentEnabled();
-#endif // defined(OS_MACOSX)
-
-// 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();
+// 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_ANDROID)
+enum class ForcedPopupLayoutState {
+ kDefault, // No popup layout forced by experiment.
+ kLeadingIcon, // Experiment forces leading (left in LTR) icon layout.
+ kTrailingIcon, // Experiment forces trailing (right in LTR) icon layout.
+};
+// Returns kDefault if no experimental behavior is enabled for
+// kAutofillDropdownLayoutExperiment; returns kLeftIcon or kRightIcon
+// if the experiment param matches kAutofillDropdownLayoutParameterLeadingIcon
+// or kAutofillDropdownLayoutParameterTrailingIcon, respectively.
+ForcedPopupLayoutState GetForcedPopupLayoutState();
+#endif // !defined(OS_ANDROID)
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
index 7c8b01dcfd1..724db579a5c 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -6,7 +6,8 @@
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/test_sync_service.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,68 +39,68 @@ class AutofillExperimentsTest : public testing::Test {
};
TEST_F(AutofillExperimentsTest, DenyUpload_FeatureEnabled) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
EXPECT_TRUE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest, DenyUpload_FeatureDisabled) {
- scoped_feature_list_.InitAndDisableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndDisableFeature(features::kAutofillUpstream);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest, DenyUpload_SyncServiceCannotStart) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
sync_service_.SetDisableReasons(
syncer::SyncService::DISABLE_REASON_USER_CHOICE);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest, DenyUpload_AuthError) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
sync_service_.SetInAuthError(true);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest,
DenyUpload_SyncServiceDoesNotHaveAutofillProfilePreferredDataType) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
sync_service_.SetDataTypes(syncer::ModelTypeSet());
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest, DenyUpload_SyncCycleNotComplete) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
sync_service_.SetSyncCycleComplete(false);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest, DenyUpload_SyncConfigurationNotDone) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
sync_service_.SetConfigurationDone(false);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest,
DenyUpload_SyncServiceUsingSecondaryPassphrase) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
sync_service_.SetIsUsingSecondaryPassphrase(true);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest,
DenyUpload_AutofillWalletImportEnabledPrefIsDisabled) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
- pref_service_.SetBoolean(prefs::kAutofillWalletImportEnabled, false);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
+ prefs::SetPaymentsIntegrationEnabled(&pref_service_, false);
EXPECT_FALSE(IsCreditCardUploadEnabled());
}
TEST_F(AutofillExperimentsTest, DenyUpload_EmptyUserEmail) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
EXPECT_FALSE(IsCreditCardUploadEnabled(""));
}
TEST_F(AutofillExperimentsTest, AllowUpload_UserEmailWithGoogleDomain) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
EXPECT_TRUE(IsCreditCardUploadEnabled("john.smith@gmail.com"));
EXPECT_TRUE(IsCreditCardUploadEnabled("googler@google.com"));
EXPECT_TRUE(IsCreditCardUploadEnabled("old.school@googlemail.com"));
@@ -107,7 +108,7 @@ TEST_F(AutofillExperimentsTest, AllowUpload_UserEmailWithGoogleDomain) {
}
TEST_F(AutofillExperimentsTest, DenyUpload_UserEmailWithNonGoogleDomain) {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstream);
+ scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
EXPECT_FALSE(IsCreditCardUploadEnabled("cool.user@hotmail.com"));
EXPECT_FALSE(IsCreditCardUploadEnabled("john.smith@johnsmith.com"));
EXPECT_FALSE(IsCreditCardUploadEnabled("fake.googler@google.net"));
@@ -117,7 +118,9 @@ TEST_F(AutofillExperimentsTest, DenyUpload_UserEmailWithNonGoogleDomain) {
TEST_F(AutofillExperimentsTest,
AllowUpload_UserEmailWithNonGoogleDomainIfExperimentEnabled) {
scoped_feature_list_.InitWithFeatures(
- {kAutofillUpstream, kAutofillUpstreamAllowAllEmailDomains}, {});
+ {features::kAutofillUpstream,
+ features::kAutofillUpstreamAllowAllEmailDomains},
+ {});
EXPECT_TRUE(IsCreditCardUploadEnabled("cool.user@hotmail.com"));
EXPECT_TRUE(IsCreditCardUploadEnabled("john.smith@johnsmith.com"));
EXPECT_TRUE(IsCreditCardUploadEnabled("fake.googler@google.net"));
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index aca02c8f337..33184ca396f 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -12,13 +12,13 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/i18n/case_conversion.h"
+#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/popup_item_ids.h"
@@ -92,7 +92,7 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
// 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() && !autofill::ShouldUseNativeViews()) {
+ if (!suggestions.empty() && !features::ShouldUseNativeViews()) {
suggestions.push_back(Suggestion());
suggestions.back().frontend_id = POPUP_ITEM_ID_SEPARATOR;
}
@@ -223,7 +223,7 @@ void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
int position) {
if (identifier == POPUP_ITEM_ID_AUTOFILL_OPTIONS) {
// User selected 'Autofill Options'.
- manager_->ShowAutofillSettings();
+ manager_->ShowAutofillSettings(popup_type_ == PopupType::kCreditCards);
} else if (identifier == POPUP_ITEM_ID_CLEAR_FORM) {
// User selected 'Clear form'.
driver_->RendererShouldClearFilledSection();
@@ -404,14 +404,10 @@ void AutofillExternalDelegate::InsertDataListValues(
// the list of datalist values.
std::set<base::string16> data_list_set(data_list_values_.begin(),
data_list_values_.end());
- suggestions->erase(
- std::remove_if(
- suggestions->begin(), suggestions->end(),
- [&data_list_set](const Suggestion& suggestion) {
- return suggestion.frontend_id == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY &&
- base::ContainsKey(data_list_set, suggestion.value);
- }),
- suggestions->end());
+ base::EraseIf(*suggestions, [&data_list_set](const Suggestion& suggestion) {
+ return suggestion.frontend_id == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY &&
+ base::ContainsKey(data_list_set, suggestion.value);
+ });
#if !defined(OS_ANDROID)
// Insert the separator between the datalist and Autofill/Autocomplete values
@@ -434,14 +430,21 @@ void AutofillExternalDelegate::InsertDataListValues(
base::string16 AutofillExternalDelegate::GetSettingsSuggestionValue()
const {
- if (GetPopupType() == PopupType::kAddresses)
- return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE_ADDRESSES);
+ switch (GetPopupType()) {
+ case PopupType::kAddresses:
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE_ADDRESSES);
- if (GetPopupType() == PopupType::kCreditCards)
- return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE_PAYMENT_METHODS);
+ case PopupType::kCreditCards:
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE_PAYMENT_METHODS);
- DCHECK_EQ(GetPopupType(), PopupType::kPersonalInformation);
- return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE);
+ case PopupType::kPersonalInformation:
+ case PopupType::kUnspecified:
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE);
+
+ case PopupType::kPasswords:
+ NOTREACHED();
+ return base::string16();
+ }
}
} // namespace autofill
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 e35f340546a..69706bcf006 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -869,10 +869,10 @@ TEST_F(AutofillExternalDelegateUnitTest, IncludeFooterSeparatorForOldUIOnly) {
if (enabled) {
scoped_feature_list.InitAndEnableFeature(
- autofill::kAutofillExpandedPopupViews);
+ features::kAutofillExpandedPopupViews);
} else {
scoped_feature_list.InitAndDisableFeature(
- autofill::kAutofillExpandedPopupViews);
+ features::kAutofillExpandedPopupViews);
}
IssueOnQuery(kQueryId);
diff --git a/chromium/components/autofill/core/browser/autofill_field.cc b/chromium/components/autofill/core/browser/autofill_field.cc
index 0d427d70b72..53c47a7ee10 100644
--- a/chromium/components/autofill/core/browser/autofill_field.cc
+++ b/chromium/components/autofill/core/browser/autofill_field.cc
@@ -10,9 +10,9 @@
#include "base/feature_list.h"
#include "base/strings/string_number_conversions.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
+#include "components/autofill/core/common/autofill_features.h"
namespace autofill {
@@ -28,7 +28,6 @@ AutofillField::AutofillField()
only_fill_when_focused_(false),
generation_type_(AutofillUploadContents::Field::NO_GENERATION),
generated_password_changed_(false),
- form_classifier_outcome_(AutofillUploadContents::Field::NO_OUTCOME),
vote_type_(AutofillUploadContents::Field::NO_INFORMATION) {}
AutofillField::AutofillField(const FormFieldData& field,
@@ -47,7 +46,6 @@ AutofillField::AutofillField(const FormFieldData& field,
parseable_name_(field.name),
generation_type_(AutofillUploadContents::Field::NO_GENERATION),
generated_password_changed_(false),
- form_classifier_outcome_(AutofillUploadContents::Field::NO_OUTCOME),
vote_type_(AutofillUploadContents::Field::NO_INFORMATION) {}
AutofillField::~AutofillField() {}
@@ -116,7 +114,8 @@ AutofillType AutofillField::ComputedType() const {
// it might be better to fix this server-side.
// See http://crbug.com/429236 for background.
bool believe_server;
- if (base::FeatureList::IsEnabled(kAutofillPreferServerNamePredictions)) {
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillPreferServerNamePredictions)) {
believe_server = true;
} else {
believe_server = !(server_type_ == NAME_FULL &&
diff --git a/chromium/components/autofill/core/browser/autofill_field.h b/chromium/components/autofill/core/browser/autofill_field.h
index 7b616def23c..50a98cfa48c 100644
--- a/chromium/components/autofill/core/browser/autofill_field.h
+++ b/chromium/components/autofill/core/browser/autofill_field.h
@@ -133,15 +133,6 @@ class AutofillField : public FormFieldData {
return generated_password_changed_;
}
- void set_form_classifier_outcome(
- AutofillUploadContents::Field::FormClassifierOutcome outcome) {
- form_classifier_outcome_ = outcome;
- }
- AutofillUploadContents::Field::FormClassifierOutcome form_classifier_outcome()
- const {
- return form_classifier_outcome_;
- }
-
void set_vote_type(AutofillUploadContents::Field::VoteType type) {
vote_type_ = type;
}
@@ -220,9 +211,6 @@ class AutofillField : public FormFieldData {
// Whether the generated password was changed by user.
bool generated_password_changed_;
- // The outcome of HTML parsing based form classifier.
- AutofillUploadContents::Field::FormClassifierOutcome form_classifier_outcome_;
-
// The vote type, if the autofill type is USERNAME or any password vote.
// Otherwise, the field is ignored. |vote_type_| provides context as to what
// triggered the vote.
diff --git a/chromium/components/autofill/core/browser/autofill_handler.cc b/chromium/components/autofill/core/browser/autofill_handler.cc
index 04c50fa0d53..865ecd43122 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler.cc
@@ -16,7 +16,33 @@ namespace {
// Set a conservative upper bound on the number of forms we are willing to
// cache, simply to prevent unbounded memory consumption.
-const size_t kMaxFormCacheSize = 100;
+const size_t kAutofillHandlerMaxFormCacheSize = 100;
+
+// Returns the AutofillField* corresponding to |field| in |form| or nullptr,
+// if not found.
+AutofillField* FindAutofillFillField(const FormStructure& form,
+ const FormFieldData& field) {
+ for (const auto& cur_field : form) {
+ if (cur_field->SameFieldAs(field)) {
+ return cur_field.get();
+ }
+ }
+ return nullptr;
+}
+
+// Returns true if |live_form| does not match |cached_form|.
+bool CachedFormNeedsUpdate(const FormData& live_form,
+ const FormStructure& cached_form) {
+ if (live_form.fields.size() != cached_form.field_count())
+ return true;
+
+ for (size_t i = 0; i < cached_form.field_count(); ++i) {
+ if (!cached_form.field(i)->SameFieldAs(live_form.fields[i]))
+ return true;
+ }
+
+ return false;
+}
} // namespace
@@ -24,7 +50,7 @@ using base::TimeTicks;
AutofillHandler::AutofillHandler(AutofillDriver* driver) : driver_(driver) {}
-AutofillHandler::~AutofillHandler() {}
+AutofillHandler::~AutofillHandler() = default;
void AutofillHandler::OnFormSubmitted(const FormData& form,
bool known_success,
@@ -47,21 +73,38 @@ void AutofillHandler::OnFormsSeen(const std::vector<FormData>& forms,
if (forms.empty())
return;
- std::vector<FormStructure*> form_structures;
+ // Parse each of the forms. Because parsing a given FormData may invalidate
+ // and replace a form parsed before it (invalidating any pointers we might
+ // hold) we track the newly created form signatures instead of remembering
+ // the pointer values.
+ std::set<FormSignature> new_form_signatures;
for (const FormData& form : forms) {
const auto parse_form_start_time = TimeTicks::Now();
FormStructure* form_structure = nullptr;
if (!ParseForm(form, /*cached_form=*/nullptr, &form_structure))
continue;
DCHECK(form_structure);
- if (form_structure == nullptr)
- continue;
- form_structures.push_back(form_structure);
+ new_form_signatures.insert(form_structure->form_signature());
AutofillMetrics::LogParseFormTiming(TimeTicks::Now() -
parse_form_start_time);
}
- if (!form_structures.empty())
- OnFormsParsed(form_structures, timestamp);
+
+ if (new_form_signatures.empty())
+ return;
+
+ // Populate the set of newly created form structures and call the
+ // OnFormsParsed handler.
+ std::vector<FormStructure*> new_form_structures;
+ new_form_structures.reserve(new_form_signatures.size());
+ for (auto signature : new_form_signatures) {
+ FormStructure* form_structure = nullptr;
+ if (FindCachedForm(signature, &form_structure) && form_structure) {
+ new_form_structures.push_back(form_structure);
+ } else {
+ NOTREACHED();
+ }
+ }
+ OnFormsParsed(new_form_structures, timestamp);
}
void AutofillHandler::OnTextFieldDidChange(const FormData& form,
@@ -136,47 +179,84 @@ void AutofillHandler::SendFormDataToRenderer(
driver_->SendFormDataToRenderer(query_id, action, data);
}
+bool AutofillHandler::GetCachedFormAndField(const FormData& form,
+ const FormFieldData& field,
+ FormStructure** form_structure,
+ AutofillField** autofill_field) {
+ // Maybe find an existing FormStructure that corresponds to |form|.
+ FormStructure* cached_form = nullptr;
+ if (FindCachedForm(form, &cached_form)) {
+ DCHECK(cached_form);
+ if (!CachedFormNeedsUpdate(form, *cached_form)) {
+ // There is no data to return if there are no auto-fillable fields.
+ if (!cached_form->autofill_count())
+ return false;
+
+ // Return the cached form and matching field, if any.
+ *form_structure = cached_form;
+ *autofill_field = FindAutofillFillField(**form_structure, field);
+ return *autofill_field != nullptr;
+ }
+ }
+
+ // The form is new or updated, parse it and discard |cached_form|.
+ // i.e., |cached_form| is no longer valid after this call.
+ if (!ParseForm(form, std::move(cached_form), form_structure))
+ return false;
+
+ // Annotate the updated form with its predicted types.
+ driver()->SendAutofillTypePredictionsToRenderer({*form_structure});
+
+ // There is no data to return if there are no auto-fillable fields.
+ if (!(*form_structure)->autofill_count())
+ return false;
+
+ // Find the AutofillField that corresponds to |field|.
+ *autofill_field = FindAutofillFillField(**form_structure, field);
+ return *autofill_field != nullptr;
+}
+
+bool AutofillHandler::FindCachedForm(FormSignature form_signature,
+ FormStructure** form_structure) const {
+ auto it = form_structures_.find(form_signature);
+ if (it != form_structures_.end()) {
+ *form_structure = it->second.get();
+ return true;
+ }
+ return false;
+}
+
bool AutofillHandler::FindCachedForm(const FormData& form,
FormStructure** form_structure) const {
// Find the FormStructure that corresponds to |form|.
- // Scan backward through the cached |form_structures_|, as updated versions of
- // forms are added to the back of the list, whereas original versions of these
- // forms might appear toward the beginning of the list. The communication
- // protocol with the crowdsourcing server does not permit us to discard the
- // original versions of the forms.
- *form_structure = nullptr;
- const auto& form_signature = autofill::CalculateFormSignature(form);
- for (auto& cur_form : base::Reversed(form_structures_)) {
- if (cur_form->form_signature() == form_signature || *cur_form == form) {
- *form_structure = cur_form.get();
-
- // The same form might be cached with multiple field counts: in some
- // cases, non-autofillable fields are filtered out, whereas in other cases
- // they are not. To avoid thrashing the cache, keep scanning until we
- // find a cached version with the same number of fields, if there is one.
- if (cur_form->field_count() == form.fields.size())
- break;
+ if (FindCachedForm(autofill::CalculateFormSignature(form), form_structure))
+ return true;
+
+ // The form might have been modified by JavaScript which resulted in a change
+ // of form signature. Compare it to all the forms in the cache to look for a
+ // match.
+ for (const auto& it : form_structures_) {
+ if (*it.second == form) {
+ *form_structure = it.second.get();
+ return true;
}
}
- if (!(*form_structure))
- return false;
-
- return true;
+ *form_structure = nullptr;
+ return false;
}
bool AutofillHandler::ParseForm(const FormData& form,
const FormStructure* cached_form,
FormStructure** parsed_form_structure) {
DCHECK(parsed_form_structure);
- if (form_structures_.size() >= kMaxFormCacheSize)
+ if (form_structures_.size() >= kAutofillHandlerMaxFormCacheSize)
return false;
auto form_structure = std::make_unique<FormStructure>(form);
form_structure->ParseFieldTypesFromAutocompleteAttributes();
- if (!form_structure->ShouldBeParsed()) {
+ if (!form_structure->ShouldBeParsed())
return false;
- }
if (cached_form) {
// We need to keep the server data if available. We need to use them while
@@ -186,12 +266,20 @@ bool AutofillHandler::ParseForm(const FormData& form,
/*only_server_and_autofill_state=*/true);
}
+ form_structure->DetermineHeuristicTypes();
+
+ // Hold the parsed_form_structure we intend to return. We can use this to
+ // reference the form_signature when transferring ownership below.
+ *parsed_form_structure = form_structure.get();
+
// Ownership is transferred to |form_structures_| which maintains it until
- // the manager is Reset() or destroyed. It is safe to use references below
- // as long as receivers don't take ownership.
- form_structure->set_form_parsed_timestamp(TimeTicks::Now());
- form_structures_.push_back(std::move(form_structure));
- *parsed_form_structure = form_structures_.back().get();
+ // the form is parsed again or the AutofillHandler is destroyed.
+ //
+ // Note that this insert/update takes ownership of the new form structure
+ // and also destroys the previously cached form structure.
+ form_structures_[(*parsed_form_structure)->form_signature()] =
+ std::move(form_structure);
+
return true;
}
diff --git a/chromium/components/autofill/core/browser/autofill_handler.h b/chromium/components/autofill/core/browser/autofill_handler.h
index 74e76a5fa77..f228eaff880 100644
--- a/chromium/components/autofill/core/browser/autofill_handler.h
+++ b/chromium/components/autofill/core/browser/autofill_handler.h
@@ -5,14 +5,16 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_H_
+#include <map>
+#include <memory>
#include <string>
-#include <vector>
#include "base/compiler_specific.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/signatures_util.h"
#include "components/autofill/core/common/submission_source.h"
namespace gfx {
@@ -21,6 +23,7 @@ class RectF;
namespace autofill {
+class AutofillField;
struct FormData;
struct FormFieldData;
class FormStructure;
@@ -34,6 +37,9 @@ class AutofillHandler {
DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
};
+ using FormStructureMap =
+ std::map<FormSignature, std::unique_ptr<FormStructure>>;
+
virtual ~AutofillHandler();
// Invoked when the value of textfield is changed.
@@ -109,13 +115,20 @@ class AutofillHandler {
AutofillDriver::RendererFormDataAction action,
const FormData& data);
+ // Fills |form_structure| and |autofill_field| with the cached elements
+ // corresponding to |form| and |field|. This might have the side-effect of
+ // updating the cache. Returns false if the |form| is not autofillable, or if
+ // it is not already present in the cache and the cache is full.
+ bool GetCachedFormAndField(const FormData& form,
+ const FormFieldData& field,
+ FormStructure** form_structure,
+ AutofillField** autofill_field) WARN_UNUSED_RESULT;
+
// Returns the number of forms this Autofill handler is aware of.
size_t NumFormsDetected() const { return form_structures_.size(); }
// Returns the present form structures seen by Autofill handler.
- const std::vector<std::unique_ptr<FormStructure>>& form_structures() {
- return form_structures_;
- }
+ const FormStructureMap& form_structures() const { return form_structures_; }
protected:
AutofillHandler(AutofillDriver* driver);
@@ -158,17 +171,19 @@ class AutofillHandler {
virtual void OnFormsParsed(const std::vector<FormStructure*>& form_structures,
const base::TimeTicks timestamp) = 0;
- AutofillDriver* driver() { return driver_; }
+ // Fills |form_structure| with a pointer to the cached form structure
+ // corresponding to |form_signature|. Returns false if no cached form
+ // structure is found with a matching signature.
+ bool FindCachedForm(FormSignature form_signature,
+ FormStructure** form_structure) const WARN_UNUSED_RESULT;
- // Fills |form_structure| cached element corresponding to |form|.
- // Returns false if the cached element was not found.
+ // Fills |form_structure| with a pointer to the cached form structure
+ // corresponding to |form|. This will do a direct match of the form's
+ // signature as well as fuzzy match of the forms structure if no directly
+ // matching form signature is found. Returns false if no match is found.
bool FindCachedForm(const FormData& form,
FormStructure** form_structure) const WARN_UNUSED_RESULT;
- std::vector<std::unique_ptr<FormStructure>>* mutable_form_structures() {
- return &form_structures_;
- }
-
// Parses the |form| with the server data retrieved from the |cached_form|
// (if any), and writes it to the |parse_form_structure|. Adds the
// |parse_form_structure| to the |form_structures_|. Returns true if the form
@@ -177,13 +192,17 @@ class AutofillHandler {
const FormStructure* cached_form,
FormStructure** parsed_form_structure);
- private:
- // Our copy of the form data.
- std::vector<std::unique_ptr<FormStructure>> form_structures_;
+ AutofillDriver* driver() { return driver_; }
+
+ FormStructureMap* mutable_form_structures() { return &form_structures_; }
+ private:
// Provides driver-level context to the shared code of the component. Must
// outlive this object.
- AutofillDriver* driver_;
+ AutofillDriver* const driver_;
+
+ // Our copy of the form data.
+ FormStructureMap form_structures_;
DISALLOW_COPY_AND_ASSIGN(AutofillHandler);
};
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
index 1f6cc73f3ac..7ed1e4e63eb 100644
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -65,8 +65,9 @@ void AutofillHandlerProxy::OnSelectControlDidChangeImpl(
bool AutofillHandlerProxy::ShouldParseForms(const std::vector<FormData>& forms,
const base::TimeTicks timestamp) {
provider_->OnFormsSeen(this, forms, timestamp);
- // Don't use form_structure.
- return false;
+ // Need to parse the |forms| to FormStructure, so heuristic_type can be
+ // retrieved later.
+ return true;
}
void AutofillHandlerProxy::OnFormsParsed(
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 34026869008..a83084e922b 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -32,13 +32,13 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_data_model.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
@@ -59,7 +59,7 @@
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_predictions.h"
@@ -151,12 +151,17 @@ void SelectRightNameType(const ServerFieldTypeSet& old_types,
}
}
-bool IsCreditCardExpirationType(ServerFieldType type) {
- return type == CREDIT_CARD_EXP_MONTH ||
- type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
- type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
- type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
- type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
+void LogDeveloperEngagementUkm(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ FormStructure* form_structure) {
+ if (form_structure->developer_engagement_metrics()) {
+ AutofillMetrics::LogDeveloperEngagementUkm(
+ ukm_recorder, source_id, form_structure->main_frame_origin().GetURL(),
+ form_structure->IsCompleteCreditCardForm(),
+ form_structure->GetFormTypes(),
+ form_structure->developer_engagement_metrics(),
+ form_structure->form_signature());
+ }
}
} // namespace
@@ -178,41 +183,6 @@ AutofillManager::AutofillManager(
AutofillManager::~AutofillManager() {}
-// static
-void AutofillManager::RegisterProfilePrefs(
- user_prefs::PrefRegistrySyncable* registry) {
- registry->RegisterDoublePref(
- prefs::kAutofillBillingCustomerNumber, 0.0,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
- // This pref is not synced because it's for a signin promo, which by
- // definition will not be synced.
- registry->RegisterIntegerPref(
- prefs::kAutofillCreditCardSigninPromoImpressionCount, 0);
- registry->RegisterBooleanPref(
- prefs::kAutofillEnabled, true,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
- registry->RegisterBooleanPref(
- prefs::kAutofillProfileEnabled, true,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
- registry->RegisterIntegerPref(
- prefs::kAutofillLastVersionDeduped, 0,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
- registry->RegisterIntegerPref(
- prefs::kAutofillLastVersionDisusedAddressesDeleted, 0,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
- // These choices are made on a per-device basis, so they're not syncable.
- registry->RegisterBooleanPref(prefs::kAutofillWalletImportEnabled, true);
- registry->RegisterBooleanPref(
- prefs::kAutofillWalletImportStorageCheckboxState, true);
- registry->RegisterIntegerPref(
- prefs::kAutofillAcceptSaveCreditCardPromptState,
- prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE);
- registry->RegisterIntegerPref(
- prefs::kAutofillLastVersionDisusedCreditCardsDeleted, 0);
- registry->RegisterBooleanPref(prefs::kAutofillCreditCardEnabled, true);
- registry->RegisterBooleanPref(prefs::kAutofillOrphanRowsRemoved, false);
-}
-
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
@@ -221,8 +191,8 @@ void AutofillManager::SetExternalDelegate(AutofillExternalDelegate* delegate) {
autocomplete_history_manager_->SetExternalDelegate(delegate);
}
-void AutofillManager::ShowAutofillSettings() {
- client_->ShowAutofillSettings();
+void AutofillManager::ShowAutofillSettings(bool show_credit_card_settings) {
+ client_->ShowAutofillSettings(show_credit_card_settings);
}
bool AutofillManager::ShouldShowScanCreditCard(const FormData& form,
@@ -241,7 +211,7 @@ bool AutofillManager::ShouldShowScanCreditCard(const FormData& form,
bool is_scannable_name_on_card_field =
autofill_field->Type().GetStorableType() == CREDIT_CARD_NAME_FULL &&
- base::FeatureList::IsEnabled(kAutofillScanCardholderName);
+ base::FeatureList::IsEnabled(features::kAutofillScanCardholderName);
if (!is_card_number_field && !is_scannable_name_on_card_field)
return false;
@@ -426,7 +396,7 @@ bool AutofillManager::MaybeStartVoteUploadProcess(
FormStructure* raw_form = form_structure.get();
TimeTicks loaded_timestamp = forms_loaded_timestamps_[raw_form->ToFormData()];
base::PostTaskWithTraitsAndReply(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&AutofillManager::DeterminePossibleFieldTypesForUpload,
copied_profiles, copied_credit_cards, app_locale_,
raw_form),
@@ -566,7 +536,7 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
if (suggestions.empty() && !ShouldShowCreditCardSigninPromo(form, field) &&
field.should_autocomplete &&
!(context.focused_field &&
- (IsCreditCardExpirationType(
+ (autofill::data_util::IsCreditCardExpirationType(
context.focused_field->Type().GetStorableType()) ||
context.focused_field->Type().html_type() == HTML_TYPE_UNRECOGNIZED ||
context.focused_field->Type().GetStorableType() ==
@@ -949,29 +919,29 @@ void AutofillManager::SelectFieldOptionsDidChange(const FormData& form) {
FormStructure* cached_form = nullptr;
ignore_result(FindCachedForm(form, &cached_form));
- if (!ParseFormInternal(form, cached_form, &form_structure))
+ if (!ParseForm(form, cached_form, &form_structure))
return;
if (ShouldTriggerRefill(*form_structure))
- TriggerRefill(form, form_structure);
+ TriggerRefill(form);
}
void AutofillManager::OnLoadedServerPredictions(
std::string response,
const std::vector<std::string>& form_signatures) {
- // We obtain the current valid FormStructures represented by
- // |form_signatures|. We invert both lists because most recent forms are at
- // the end of the list (and reverse the resulting pointer vector).
+ // Get the current valid FormStructures represented by |form_signatures|.
std::vector<FormStructure*> queried_forms;
- for (const std::string& signature : base::Reversed(form_signatures)) {
- for (auto& cur_form : base::Reversed(form_structures())) {
- if (cur_form->FormSignatureAsStr() == signature) {
- queried_forms.push_back(cur_form.get());
- break;
- }
+ queried_forms.reserve(form_signatures.size());
+ for (const std::string& signature : form_signatures) {
+ // The |signature| is the direct string representation of the FormSignature.
+ // Convert it to a uint64_t to do the lookup.
+ FormSignature form_signature;
+ FormStructure* form_structure;
+ if (base::StringToUint64(signature, &form_signature) &&
+ FindCachedForm(form_signature, &form_structure)) {
+ queried_forms.push_back(form_structure);
}
}
- std::reverse(queried_forms.begin(), queried_forms.end());
// If there are no current forms corresponding to the queried signatures, drop
// the query response.
@@ -1041,17 +1011,17 @@ void AutofillManager::OnDidEndTextFieldEditing() {
}
bool AutofillManager::IsAutofillEnabled() const {
- return ::autofill::IsAutofillEnabled(client_->GetPrefs()) &&
+ return ::autofill::prefs::IsAutofillEnabled(client_->GetPrefs()) &&
client_->IsAutofillSupported();
}
bool AutofillManager::IsProfileAutofillEnabled() const {
- return client_->GetPrefs()->GetBoolean(prefs::kAutofillProfileEnabled) &&
+ return ::autofill::prefs::IsProfileAutofillEnabled(client_->GetPrefs()) &&
client_->IsAutofillSupported();
}
bool AutofillManager::IsCreditCardAutofillEnabled() const {
- return client_->GetPrefs()->GetBoolean(prefs::kAutofillCreditCardEnabled) &&
+ return ::autofill::prefs::IsCreditCardAutofillEnabled(client_->GetPrefs()) &&
client_->IsAutofillSupported();
}
@@ -1151,10 +1121,7 @@ AutofillManager::AutofillManager(
driver->GetURLLoaderFactory(),
client->GetPrefs(),
client->GetIdentityManager(),
- /*unmask_delegate=*/this,
- // save_delegate starts out as nullptr and is set up by the
- // CreditCardSaveManager owned by form_data_importer_.
- /*save_delegate=*/nullptr,
+ client->GetPersonalDataManager(),
driver->IsIncognito())),
app_locale_(app_locale),
personal_data_(personal_data),
@@ -1278,7 +1245,8 @@ void AutofillManager::FillOrPreviewDataModelForm(
FormData result = form;
- if (base::FeatureList::IsEnabled(kAutofillRationalizeFieldTypePredictions)) {
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillRationalizeFieldTypePredictions)) {
form_structure->RationalizePhoneNumbersInSection(autofill_field->section);
}
@@ -1345,7 +1313,8 @@ void AutofillManager::FillOrPreviewDataModelForm(
}
// Don't fill expired cards expiration date.
- if (IsCreditCardExpirationType(cached_field->Type().GetStorableType()) &&
+ if (data_util::IsCreditCardExpirationType(
+ cached_field->Type().GetStorableType()) &&
static_cast<const CreditCard*>(&data_model)
->IsExpired(AutofillClock::Now())) {
continue;
@@ -1391,59 +1360,21 @@ void AutofillManager::FillOrPreviewDataModelForm(
std::unique_ptr<FormStructure> AutofillManager::ValidateSubmittedForm(
const FormData& form) {
- std::unique_ptr<FormStructure> submitted_form(
- std::make_unique<FormStructure>(form));
- if (!ShouldUploadForm(*submitted_form))
- return std::unique_ptr<FormStructure>();
-
// Ignore forms not present in our cache. These are typically forms with
// wonky JavaScript that also makes them not auto-fillable.
FormStructure* cached_submitted_form;
- if (!FindCachedForm(form, &cached_submitted_form))
- return std::unique_ptr<FormStructure>();
+ if (!FindCachedForm(form, &cached_submitted_form) ||
+ !ShouldUploadForm(*cached_submitted_form)) {
+ return nullptr;
+ }
+ auto submitted_form = std::make_unique<FormStructure>(form);
submitted_form->RetrieveFromCache(*cached_submitted_form,
/*apply_is_autofilled=*/false,
/*only_server_and_autofill_state=*/false);
return submitted_form;
}
-bool AutofillManager::GetCachedFormAndField(const FormData& form,
- const FormFieldData& field,
- FormStructure** form_structure,
- AutofillField** autofill_field) {
- // Find the FormStructure that corresponds to |form|.
- // If we do not have this form in our cache but it is parseable, we'll add it
- // in the call to |UpdateCachedForm()|.
- if (!FindCachedForm(form, form_structure) &&
- !FormStructure(form).ShouldBeParsed()) {
- return false;
- }
-
- // Update the cached form to reflect any dynamic changes to the form data, if
- // necessary.
- if (!UpdateCachedForm(form, *form_structure, form_structure))
- return false;
-
- // No data to return if there are no auto-fillable fields.
- if (!(*form_structure)->autofill_count())
- return false;
-
- // Find the AutofillField that corresponds to |field|.
- *autofill_field = nullptr;
- for (const auto& current : **form_structure) {
- if (current->SameFieldAs(field)) {
- *autofill_field = current.get();
- break;
- }
- }
-
- // Even though we always update the cache, the field might not exist if the
- // website disables autocomplete while the user is interacting with the form.
- // See http://crbug.com/160476
- return *autofill_field != nullptr;
-}
-
AutofillField* AutofillManager::GetAutofillField(const FormData& form,
const FormFieldData& field) {
if (!personal_data_)
@@ -1472,29 +1403,6 @@ bool AutofillManager::FormHasAddressField(const FormData& form) {
return false;
}
-bool AutofillManager::UpdateCachedForm(const FormData& live_form,
- const FormStructure* cached_form,
- FormStructure** updated_form) {
- bool needs_update =
- (!cached_form || live_form.fields.size() != cached_form->field_count());
- for (size_t i = 0; !needs_update && i < cached_form->field_count(); ++i)
- needs_update = !cached_form->field(i)->SameFieldAs(live_form.fields[i]);
-
- if (!needs_update)
- return true;
-
- // Note: We _must not_ remove the original version of the cached form from
- // the list of |form_structures_|. Otherwise, we break parsing of the
- // crowdsourcing server's response to our query.
- if (!ParseFormInternal(live_form, cached_form, updated_form))
- return false;
-
- // Annotate the updated form with its predicted types.
- driver()->SendAutofillTypePredictionsToRenderer({*updated_form});
-
- return true;
-}
-
std::vector<Suggestion> AutofillManager::GetProfileSuggestions(
const FormStructure& form,
const FormFieldData& field,
@@ -1574,8 +1482,10 @@ void AutofillManager::OnFormsParsed(
std::vector<FormStructure*> queryable_forms;
std::set<FormType> form_types;
for (FormStructure* form_structure : form_structures) {
- form_structure->DetermineHeuristicTypes(client_->GetUkmRecorder(),
- client_->GetUkmSourceId());
+ // TODO(crbug.com/869482): avoid logging developer engagement multiple
+ // times for a given form if it or other forms on the page are dynamic.
+ LogDeveloperEngagementUkm(client_->GetUkmRecorder(),
+ client_->GetUkmSourceId(), form_structure);
forms_loaded_timestamps_[form_structure->ToFormData()] = timestamp;
std::set<FormType> current_form_types = form_structure->GetFormTypes();
form_types.insert(current_form_types.begin(), current_form_types.end());
@@ -1600,13 +1510,13 @@ void AutofillManager::OnFormsParsed(
if (filling_context->on_refill_timer.IsRunning())
filling_context->on_refill_timer.AbandonAndStop();
- // Can TriggerRefill get FormData from FormStructure?
+ // Start a new timer to trigger refill.
filling_context->on_refill_timer.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(kWaitTimeForDynamicFormsMs),
base::BindRepeating(&AutofillManager::TriggerRefill,
weak_ptr_factory_.GetWeakPtr(),
- form_structure->ToFormData(), form_structure));
+ form_structure->ToFormData()));
}
}
@@ -1628,8 +1538,7 @@ void AutofillManager::OnFormsParsed(
// prompt for credit card assisted filling. Upon accepting the infobar, the
// form will automatically be filled with the user's information through this
// class' FillCreditCardForm().
- if (autofill_assistant_.CanShowCreditCardAssist(
- AutofillHandler::form_structures())) {
+ if (autofill_assistant_.CanShowCreditCardAssist()) {
const std::vector<CreditCard*> cards =
personal_data_->GetCreditCardsToSuggest(
client_->AreServerCardsSupported());
@@ -1652,18 +1561,6 @@ void AutofillManager::OnFormsParsed(
}
}
-bool AutofillManager::ParseFormInternal(const FormData& form,
- const FormStructure* cached_form,
- FormStructure** parsed_form_structure) {
- if (ParseForm(form, cached_form, parsed_form_structure)) {
- (*parsed_form_structure)
- ->DetermineHeuristicTypes(client_->GetUkmRecorder(),
- client_->GetUkmSourceId());
- return true;
- }
- return false;
-}
-
int AutofillManager::BackendIDToInt(const std::string& backend_id) const {
if (!base::IsValidGUID(backend_id))
return 0;
@@ -1955,8 +1852,13 @@ bool AutofillManager::ShouldTriggerRefill(const FormStructure& form_structure) {
delta.InMilliseconds() < kLimitBeforeRefillMs;
}
-void AutofillManager::TriggerRefill(const FormData& form,
- FormStructure* form_structure) {
+void AutofillManager::TriggerRefill(const FormData& form) {
+ FormStructure* form_structure = nullptr;
+ if (!FindCachedForm(form, &form_structure))
+ return;
+
+ DCHECK(form_structure);
+
address_form_event_logger_->OnDidRefill();
auto itr =
@@ -1964,7 +1866,12 @@ void AutofillManager::TriggerRefill(const FormData& form,
DCHECK(itr != filling_contexts_map_.end());
FillingContext* filling_context = itr->second.get();
- DCHECK(!filling_context->attempted_refill);
+ // The refill attempt can happen from different paths, some of which happen
+ // after waiting for a while. Therefore, although this condition has been
+ // checked prior to calling TriggerRefill, it may not hold, when we get here.
+ if (filling_context->attempted_refill)
+ return;
+
filling_context->attempted_refill = true;
// Try to find the field from which the original field originated.
@@ -2037,7 +1944,8 @@ void AutofillManager::GetAvailableSuggestions(
&context->is_all_server_suggestions);
// Logic for disabling/ablating credit card autofill.
- if (base::FeatureList::IsEnabled(kAutofillCreditCardAblationExperiment) &&
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardAblationExperiment) &&
!suggestions->empty()) {
context->suppress_reason = SuppressReason::kCreditCardsAblation;
suggestions->clear();
@@ -2047,7 +1955,7 @@ void AutofillManager::GetAvailableSuggestions(
// On desktop, don't return non credit card related suggestions for forms or
// fields that have the "autocomplete" attribute set to off, only if the
// feature to always fill addresses is off.
- if (!base::FeatureList::IsEnabled(kAutofillAlwaysFillAddresses) &&
+ if (!base::FeatureList::IsEnabled(features::kAutofillAlwaysFillAddresses) &&
IsDesktopPlatform() && !field.should_autocomplete) {
context->suppress_reason = SuppressReason::kAutocompleteOff;
return;
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index eda55e319c2..2b7feeb4dc9 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -35,6 +35,7 @@
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/popup_types.h"
#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/signatures_util.h"
#if defined(OS_ANDROID) || defined(OS_IOS)
#include "components/autofill/core/browser/autofill_assistant.h"
@@ -44,10 +45,6 @@ namespace gfx {
class RectF;
}
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
namespace autofill {
class AutofillDataModel;
@@ -71,13 +68,9 @@ extern const int kCreditCardSigninPromoImpressionLimit;
// forms. One per frame; owned by the AutofillDriver.
class AutofillManager : public AutofillHandler,
public AutofillDownloadManager::Observer,
- public payments::PaymentsClientUnmaskDelegate,
public payments::FullCardRequest::ResultDelegate,
public payments::FullCardRequest::UIDelegate {
public:
- // Registers our Enable/Disable Autofill pref.
- static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
AutofillManager(AutofillDriver* driver,
AutofillClient* client,
const std::string& app_locale,
@@ -87,7 +80,7 @@ class AutofillManager : public AutofillHandler,
// Sets an external delegate.
void SetExternalDelegate(AutofillExternalDelegate* delegate);
- void ShowAutofillSettings();
+ void ShowAutofillSettings(bool show_credit_card_settings);
// Whether the |field| should show an entry to scan a credit card.
virtual bool ShouldShowScanCreditCard(const FormData& form,
@@ -141,6 +134,8 @@ class AutofillManager : public AutofillHandler,
return download_manager_.get();
}
+ FormDataImporter* form_data_importer() { return form_data_importer_.get(); }
+
payments::FullCardRequest* GetOrCreateFullCardRequest();
payments::FullCardRequest* CreateFullCardRequest(
@@ -336,18 +331,14 @@ class AutofillManager : public AutofillHandler,
SuppressReason suppress_reason = SuppressReason::kNotSuppressed;
};
- bool ParseFormInternal(const FormData& form,
- const FormStructure* cached_form,
- FormStructure** parsed_form_structure);
-
// AutofillDownloadManager::Observer:
void OnLoadedServerPredictions(
std::string response,
const std::vector<std::string>& form_signatures) override;
-
- // payments::PaymentsClientUnmaskDelegate:
+ // Returns the real PAN retrieved from Payments. |real_pan| will be empty on
+ // failure.
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) override;
+ const std::string& real_pan);
// payments::FullCardRequest::ResultDelegate:
void OnFullCardRequestSucceeded(
@@ -414,15 +405,6 @@ class AutofillManager : public AutofillHandler,
// or personal data.
std::unique_ptr<FormStructure> ValidateSubmittedForm(const FormData& form);
- // Fills |form_structure| and |autofill_field| with the cached elements
- // corresponding to |form| and |field|. This might have the side-effect of
- // updating the cache. Returns false if the |form| is not autofillable, or if
- // it is not already present in the cache and the cache is full.
- bool GetCachedFormAndField(const FormData& form,
- const FormFieldData& field,
- FormStructure** form_structure,
- AutofillField** autofill_field) WARN_UNUSED_RESULT;
-
// Returns the field corresponding to |form| and |field| that can be
// autofilled. Returns NULL if the field cannot be autofilled.
AutofillField* GetAutofillField(const FormData& form,
@@ -433,14 +415,6 @@ class AutofillManager : public AutofillHandler,
// |FieldTypeGroup|.
bool FormHasAddressField(const FormData& form) WARN_UNUSED_RESULT;
- // Re-parses |live_form| and adds the result to |form_structures_|.
- // |cached_form| should be a pointer to the existing version of the form, or
- // NULL if no cached version exists. The updated form is then written into
- // |updated_form|. Returns false if the cache could not be updated.
- bool UpdateCachedForm(const FormData& live_form,
- const FormStructure* cached_form,
- FormStructure** updated_form) WARN_UNUSED_RESULT;
-
// Returns a list of values from the stored profiles that match |type| and the
// value of |field| and returns the labels of the matching profiles. |labels|
// is filled with the Profile label.
@@ -519,7 +493,7 @@ class AutofillManager : public AutofillHandler,
// Attempts to refill the form that was changed dynamically. Should only be
// called if ShouldTriggerRefill returns true.
- void TriggerRefill(const FormData& form, FormStructure* form_structure);
+ void TriggerRefill(const FormData& form);
// Replaces the contents of |suggestions| with available suggestions for
// |field|. |context| will contain additional information about the
@@ -634,6 +608,7 @@ class AutofillManager : public AutofillHandler,
friend class FormStructureBrowserTest;
friend class GetMatchingTypesTest;
friend class SaveCardBubbleViewsBrowserTestBase;
+ friend class SaveCardInfobarEGTestHelper;
FRIEND_TEST_ALL_PREFIXES(ProfileMatchingTypesTest,
DeterminePossibleFieldTypesForUpload);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index 4db3f8b3dfe..18dbb5af79f 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -29,7 +29,6 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_download_manager.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#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"
@@ -48,7 +47,7 @@
#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_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
@@ -512,7 +511,7 @@ class AutofillManagerTest : public testing::Test {
void DisableCreditCardAutofill() {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillCreditCardAblationExperiment);
+ features::kAutofillCreditCardAblationExperiment);
}
// Wrappers around the TestAutofillExternalDelegate::GetSuggestions call that
@@ -745,7 +744,8 @@ TEST_F(AutofillManagerTest, GetProfileSuggestions_UnrecognizedAttribute) {
TEST_F(AutofillManagerTest,
GetProfileSuggestions_MinFieldsEnforced_NoAutocomplete) {
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForHeuristics);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
@@ -777,7 +777,8 @@ TEST_F(AutofillManagerTest,
TEST_F(AutofillManagerTest,
GetProfileSuggestions_MinFieldsEnforced_WithOneAutocomplete) {
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForHeuristics);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
@@ -883,7 +884,8 @@ TEST_F(AutofillManagerTest,
TEST_F(AutofillManagerTest,
GetProfileSuggestions_SmallFormWithTwoAutocomplete) {
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForHeuristics);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
@@ -2082,7 +2084,7 @@ TEST_F(AutofillManagerTest, FillAddressForm_UnrecognizedAttribute) {
// is disabled.
TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOffRespected) {
base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+ feature_list.InitAndDisableFeature(features::kAutofillAlwaysFillAddresses);
FormData address_form;
address_form.name = ASCIIToUTF16("MyForm");
@@ -2935,7 +2937,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_ComponentizedNumbers) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -2963,7 +2965,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_ComponentizedNumbers) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms_copy);
int page_id = 1;
@@ -3022,7 +3024,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_WholeNumbers) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3046,7 +3048,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_WholeNumbers) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms_copy);
int page_id = 1;
@@ -3115,7 +3117,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FillPartsOnceOnly) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3144,7 +3146,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FillPartsOnceOnly) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms_copy);
int page_id = 1;
@@ -3213,7 +3215,7 @@ TEST_F(AutofillManagerTest,
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3238,7 +3240,7 @@ TEST_F(AutofillManagerTest,
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms_copy);
int page_id = 1;
@@ -3299,7 +3301,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_BestEfforFilling) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3324,7 +3326,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_BestEfforFilling) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3381,7 +3383,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FocusOnSecondPhoneNumber) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3408,7 +3410,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_FocusOnSecondPhoneNumber) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3468,7 +3470,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_HiddenFieldShouldNotCount) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3492,7 +3494,7 @@ TEST_F(AutofillManagerTest, FillFirstPhoneNumber_HiddenFieldShouldNotCount) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3632,7 +3634,7 @@ TEST_F(AutofillManagerTest,
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -3684,7 +3686,7 @@ TEST_F(AutofillManagerTest,
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormsSeen(forms);
int page_id = 1;
@@ -4128,8 +4130,7 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
// Similarly, a second form.
@@ -4149,8 +4150,7 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
form2.fields.push_back(field);
TestFormStructure* form_structure2 = new TestFormStructure(form2);
- form_structure2->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2->DetermineHeuristicTypes();
autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure2));
AutofillQueryResponseContents response;
@@ -4202,8 +4202,7 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions_ResetManager) {
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
AutofillQueryResponseContents response;
@@ -4256,8 +4255,7 @@ TEST_F(AutofillManagerTest, DetermineHeuristicsWithOverallPrediction) {
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
autofill_manager_->AddSeenFormStructure(base::WrapUnique(form_structure));
AutofillQueryResponseContents response;
@@ -4324,8 +4322,7 @@ TEST_F(AutofillManagerTest, FormSubmittedServerTypes) {
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
// Clear the heuristic types, and instead set the appropriate server types.
std::vector<ServerFieldType> heuristic_types, server_types;
@@ -4584,9 +4581,9 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) {
// Enable/Disable ignoring invalid profile data for the scope of this test.
base::test::ScopedFeatureList sfl;
if (vote_using_invalid_profile_data) {
- sfl.InitAndEnableFeature(kAutofillVoteUsingInvalidProfileData);
+ sfl.InitAndEnableFeature(features::kAutofillVoteUsingInvalidProfileData);
} else {
- sfl.InitAndDisableFeature(kAutofillVoteUsingInvalidProfileData);
+ sfl.InitAndDisableFeature(features::kAutofillVoteUsingInvalidProfileData);
}
// Set up the test profiles.
@@ -5713,14 +5710,16 @@ TEST_F(AutofillManagerTest, ShouldUploadForm) {
// With min required fields enabled.
{
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
// With min required fields disabled.
{
base::test::ScopedFeatureList features;
- features.InitAndDisableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndDisableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
@@ -5731,14 +5730,16 @@ TEST_F(AutofillManagerTest, ShouldUploadForm) {
// With min required fields enabled.
{
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
// With min required fields disabled.
{
base::test::ScopedFeatureList features;
- features.InitAndDisableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndDisableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
@@ -5748,14 +5749,16 @@ TEST_F(AutofillManagerTest, ShouldUploadForm) {
// With min required fields enabled.
{
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
// With min required fields disabled.
{
base::test::ScopedFeatureList features;
- features.InitAndDisableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndDisableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
@@ -5786,22 +5789,19 @@ TEST_F(AutofillManagerTest, ShouldUploadForm) {
// With min required fields enabled.
{
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndEnableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
// With min required fields disabled.
{
base::test::ScopedFeatureList features;
- features.InitAndDisableFeature(kAutofillEnforceMinRequiredFieldsForUpload);
+ features.InitAndDisableFeature(
+ features::kAutofillEnforceMinRequiredFieldsForUpload);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
- // Has two fields which are password fields.
- test::CreateTestFormField("New Password", "new_pw", "", "password", &field);
- form.fields.push_back(field);
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
-
// Autofill disabled.
autofill_manager_->SetAutofillEnabled(false);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
@@ -5847,7 +5847,7 @@ TEST_F(AutofillManagerTest,
TEST_F(AutofillManagerTest,
DisplaySuggestions_AutocompleteOffRespected_AddressField) {
base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+ feature_list.InitAndDisableFeature(features::kAutofillAlwaysFillAddresses);
// Set up an address form.
FormData mixed_form;
@@ -5964,8 +5964,7 @@ TEST_F(AutofillManagerTest, DisplaySuggestionsForUpdatedServerTypedForm) {
form.fields.push_back(field);
auto form_structure = std::make_unique<TestFormStructure>(form);
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
// Make sure the form can not be autofilled now.
ASSERT_EQ(0u, form_structure->autofill_count());
for (size_t idx = 0; idx < form_structure->field_count(); ++idx) {
@@ -6041,6 +6040,8 @@ TEST_F(AutofillManagerTest, FormWithLongOptionValuesIsAcceptable) {
// Test that a sign-in form submission sends an upload with types matching the
// fields.
+// TODO(https://crbug.com/889472): Remove this test together with sending
+// sign-in vote.
TEST_F(AutofillManagerTest, SignInFormSubmission_Upload) {
// Set up our form data (it's already filled out with user data).
FormData form;
@@ -6074,21 +6075,15 @@ TEST_F(AutofillManagerTest, SignInFormSubmission_Upload) {
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
form_structure->set_is_signin_upload(true);
- form_structure->set_form_parsed_timestamp(base::TimeTicks::Now());
form_structure->field(1)->set_possible_types({autofill::PASSWORD});
std::string signature = form_structure->FormSignatureAsStr();
- ServerFieldTypeSet uploaded_available_types;
EXPECT_CALL(*download_manager_,
StartUploadRequest(_, false, _, std::string(), true))
- .WillOnce(DoAll(SaveArg<2>(&uploaded_available_types), Return(true)));
+ .Times(0);
autofill_manager_->MaybeStartVoteUploadProcess(std::move(form_structure),
base::TimeTicks::Now(), true);
-
- EXPECT_EQ(signature, autofill_manager_->GetSubmittedFormSignature());
- EXPECT_NE(uploaded_available_types.end(),
- uploaded_available_types.find(autofill::PASSWORD));
}
// Test that with small form upload enabled but heuristics and query disabled
@@ -6251,7 +6246,8 @@ TEST_P(OnFocusOnFormFieldTest, AddressSuggestions) {
TEST_P(OnFocusOnFormFieldTest, AddressSuggestions_AutocompleteOffNotRespected) {
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kAutofillAlwaysFillAddresses);
+ scoped_feature_list.InitAndEnableFeature(
+ features::kAutofillAlwaysFillAddresses);
FormData form;
form.name = ASCIIToUTF16("MyForm");
@@ -6278,7 +6274,8 @@ TEST_P(OnFocusOnFormFieldTest, AddressSuggestions_AutocompleteOffRespected) {
return;
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+ scoped_feature_list.InitAndDisableFeature(
+ features::kAutofillAlwaysFillAddresses);
FormData form;
form.name = ASCIIToUTF16("MyForm");
@@ -6331,7 +6328,7 @@ TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_NonSecureContext) {
TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_Ablation) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
- kAutofillCreditCardAblationExperiment);
+ features::kAutofillCreditCardAblationExperiment);
// Set up our form data.
FormData form;
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index 0695357a5fb..cbbc5c17a70 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -15,7 +15,6 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h"
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 7295ceb2f42..68666bec133 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -15,12 +15,12 @@
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/form_data.h"
#include "services/metrics/public/cpp/ukm_builders.h"
@@ -702,6 +702,11 @@ void AutofillMetrics::LogSaveCardCardholderNameWasEdited(bool edited) {
}
// static
+void AutofillMetrics::LogPaymentsCustomerDataBillingIdIsValid(bool valid) {
+ UMA_HISTOGRAM_BOOLEAN("Autofill.PaymentsCustomerDataBillingIdIsValid", valid);
+}
+
+// static
void AutofillMetrics::LogCardUploadDecisionMetrics(
int upload_decision_metrics) {
DCHECK(upload_decision_metrics);
@@ -790,6 +795,17 @@ void AutofillMetrics::LogSaveCardPromptMetricBySecurityLevel(
}
// static
+void AutofillMetrics::LogManageCardsPromptMetric(ManageCardsPromptMetric metric,
+ bool is_upload_save) {
+ DCHECK_LT(metric, NUM_MANAGE_CARDS_PROMPT_METRICS);
+ std::string destination = is_upload_save ? ".Upload" : ".Local";
+ std::string metric_with_destination =
+ "Autofill.ManageCardsPrompt" + destination;
+ base::UmaHistogramEnumeration(metric_with_destination, metric,
+ NUM_MANAGE_CARDS_PROMPT_METRICS);
+}
+
+// static
void AutofillMetrics::LogScanCreditCardPromptMetric(
ScanCreditCardPromptMetric metric) {
DCHECK_LT(metric, NUM_SCAN_CREDIT_CARD_PROMPT_METRICS);
@@ -832,6 +848,31 @@ void AutofillMetrics::LogLocalCardMigrationBubbleUserInteractionMetric(
}
// static
+void AutofillMetrics::LogLocalCardMigrationPromptMetric(
+ LocalCardMigrationOrigin local_card_migration_origin,
+ LocalCardMigrationPromptMetric metric) {
+ DCHECK_LT(metric, NUM_LOCAL_CARD_MIGRATION_PROMPT_METRICS);
+ std::string histogram_name = "Autofill.LocalCardMigrationOrigin.";
+ // Switch to different sub-histogram depending on local card migration origin.
+ switch (local_card_migration_origin) {
+ case LocalCardMigrationOrigin::UseOfLocalCard:
+ histogram_name += "UseOfLocalCard";
+ break;
+ case LocalCardMigrationOrigin::UseOfServerCard:
+ histogram_name += "UseOfServerCard";
+ break;
+ case LocalCardMigrationOrigin::SettingsPage:
+ histogram_name += "SettingsPage";
+ break;
+ default:
+ NOTREACHED();
+ return;
+ }
+ base::UmaHistogramEnumeration(histogram_name, metric,
+ NUM_LOCAL_CARD_MIGRATION_PROMPT_METRICS);
+}
+
+// static
void AutofillMetrics::LogSaveCardWithFirstAndLastNameOffered(bool is_local) {
std::string histogram_name = "Autofill.SaveCardWithFirstAndLastNameOffered.";
histogram_name += is_local ? "Local" : "Server";
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index 192a7f1219f..f556888ee54 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -18,7 +18,6 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_types.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/signatures_util.h"
#include "components/security_state/core/security_state.h"
@@ -243,6 +242,20 @@ class AutofillMetrics {
NUM_SAVE_CARD_PROMPT_METRICS,
};
+ // Metrics to measure user interaction with the Manage Cards view
+ // shown when user clicks on the save card icon after accepting
+ // to save a card.
+ enum ManageCardsPromptMetric {
+ // The manage cards promo was shown.
+ MANAGE_CARDS_SHOWN,
+ // The user clicked on [Done].
+ MANAGE_CARDS_DONE,
+ // The user clicked on [Manage cards].
+ MANAGE_CARDS_MANAGE_CARDS,
+
+ NUM_MANAGE_CARDS_PROMPT_METRICS
+ };
+
// Metrics measuring how well we predict field types. These metric values are
// logged for each field in a submitted form for:
// - the heuristic prediction
@@ -423,6 +436,30 @@ class AutofillMetrics {
NUM_LOCAL_CARD_MIGRATION_BUBBLE_USER_INTERACTION_METRICS,
};
+ // These metrics are logged for each local card migration origin. These are
+ // used to derive the conversion rate for each triggering source.
+ enum LocalCardMigrationPromptMetric {
+ // The intermediate bubble is shown to the user.
+ INTERMEDIATE_BUBBLE_SHOWN = 0,
+ // The intermediate bubble is accepted by the user.
+ INTERMEDIATE_BUBBLE_ACCEPTED = 1,
+ // The main dialog is shown to the user.
+ MAIN_DIALOG_SHOWN = 2,
+ // The main dialog is accepted by the user.
+ MAIN_DIALOG_ACCEPTED = 3,
+ NUM_LOCAL_CARD_MIGRATION_PROMPT_METRICS,
+ };
+
+ // Local card migration origin denotes from where the migration is triggered.
+ enum LocalCardMigrationOrigin {
+ // Trigger when user submitted a form using local card.
+ UseOfLocalCard,
+ // Trigger when user submitted a form using server card.
+ UseOfServerCard,
+ // Trigger from settings page.
+ SettingsPage,
+ };
+
// Each of these metrics is logged only for potentially autofillable forms,
// i.e. forms with at least three fields, etc.
// These are used to derive certain "user happiness" metrics. For example, we
@@ -812,6 +849,10 @@ class AutofillMetrics {
// from its prefilled value or not.
static void LogSaveCardCardholderNameWasEdited(bool edited);
+ // Logs whether the PaymentsCustomerData's billing ID was valid at the time of
+ // use.
+ static void LogPaymentsCustomerDataBillingIdIsValid(bool valid);
+
// |upload_decision_metrics| is a bitmask of |CardUploadDecisionMetric|.
static void LogCardUploadDecisionMetrics(int upload_decision_metrics);
static void LogCreditCardInfoBarMetric(
@@ -830,6 +871,8 @@ class AutofillMetrics {
SaveCardPromptMetric metric,
bool is_uploading,
security_state::SecurityLevel security_level);
+ static void LogManageCardsPromptMetric(ManageCardsPromptMetric metric,
+ bool is_uploading);
static void LogScanCreditCardPromptMetric(ScanCreditCardPromptMetric metric);
static void LogLocalCardMigrationBubbleOfferMetric(
LocalCardMigrationBubbleOfferMetric metric,
@@ -837,6 +880,9 @@ class AutofillMetrics {
static void LogLocalCardMigrationBubbleUserInteractionMetric(
LocalCardMigrationBubbleUserInteractionMetric metric,
bool is_reshow);
+ static void LogLocalCardMigrationPromptMetric(
+ LocalCardMigrationOrigin local_card_migration_origin,
+ LocalCardMigrationPromptMetric metric);
// Should be called when credit card scan is finished. |duration| should be
// the time elapsed between launching the credit card scanner and getting back
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index 8052cca1a87..a026ce43633 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -20,7 +20,6 @@
#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_experiments.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -38,9 +37,9 @@
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
-#include "components/ukm/ukm_source.h"
#include "components/webdata/common/web_data_results.h"
#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_source.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
@@ -1924,10 +1923,11 @@ TEST_F(AutofillMetricsTest, QualityMetrics_BasedOnAutocomplete) {
std::unique_ptr<TestFormStructure> form_structure =
std::make_unique<TestFormStructure>(form);
TestFormStructure* form_structure_ptr = form_structure.get();
- form_structure->DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
- autofill_manager_->mutable_form_structures()->push_back(
- std::move(form_structure));
+ form_structure->DetermineHeuristicTypes();
+ ASSERT_TRUE(autofill_manager_->mutable_form_structures()
+ ->emplace(form_structure_ptr->form_signature(),
+ std::move(form_structure))
+ .second);
AutofillQueryResponseContents response;
// Server response will match with autocomplete.
@@ -7401,7 +7401,13 @@ TEST_F(AutofillMetricsTest, RecordCardUploadDecisionMetric_NoUkmService) {
}
// Test the ukm recorded when Suggestion is shown.
-TEST_F(AutofillMetricsTest, AutofillSuggestionShownTest) {
+// Flaky on Win. http://crbug.com/876954
+#if defined(OS_WIN)
+#define MAYBE_AutofillSuggestionShownTest DISABLED_AutofillSuggestionShownTest
+#else
+#define MAYBE_AutofillSuggestionShownTest AutofillSuggestionShownTest
+#endif
+TEST_F(AutofillMetricsTest, MAYBE_AutofillSuggestionShownTest) {
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
@@ -7505,7 +7511,7 @@ TEST_F(AutofillMetricsTest, DynamicFormMetrics) {
AutofillMetrics::FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0);
// Trigger a refill, the refill metric should be updated.
- autofill_manager_->TriggerRefill(form, &form_structure);
+ autofill_manager_->TriggerRefill(form);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
AutofillMetrics::FORM_EVENT_DID_SEE_DYNAMIC_FORM, 2);
diff --git a/chromium/components/autofill/core/browser/autofill_policy_handler.cc b/chromium/components/autofill/core/browser/autofill_policy_handler.cc
index 38f9033999c..2f3d7ff7afc 100644
--- a/chromium/components/autofill/core/browser/autofill_policy_handler.cc
+++ b/chromium/components/autofill/core/browser/autofill_policy_handler.cc
@@ -5,7 +5,7 @@
#include "components/autofill/core/browser/autofill_policy_handler.h"
#include "base/values.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
@@ -21,10 +21,26 @@ AutofillPolicyHandler::~AutofillPolicyHandler() {}
void AutofillPolicyHandler::ApplyPolicySettings(
const policy::PolicyMap& policies,
PrefValueMap* prefs) {
+ const base::Value* autofill_credit_card_policy_value =
+ policies.GetValue(policy::key::kAutofillCreditCardEnabled);
+ const base::Value* autofill_address_policy_value =
+ policies.GetValue(policy::key::kAutofillAddressEnabled);
+ // Ignore the old policy if either of the new fine-grained policies are set.
+ if ((autofill_credit_card_policy_value &&
+ autofill_credit_card_policy_value->is_bool()) ||
+ (autofill_address_policy_value &&
+ autofill_address_policy_value->is_bool())) {
+ return;
+ }
+
const base::Value* value = policies.GetValue(policy_name());
- bool auto_fill_enabled;
- if (value && value->GetAsBoolean(&auto_fill_enabled) && !auto_fill_enabled)
- prefs->SetBoolean(autofill::prefs::kAutofillEnabled, false);
+ bool autofill_enabled;
+ if (value && value->GetAsBoolean(&autofill_enabled) && !autofill_enabled) {
+ prefs->SetBoolean(autofill::prefs::kAutofillEnabledDeprecated, false);
+ // Disable the fine-grained prefs if the master pref is disabled by policy.
+ prefs->SetBoolean(autofill::prefs::kAutofillCreditCardEnabled, false);
+ prefs->SetBoolean(autofill::prefs::kAutofillProfileEnabled, false);
+ }
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_policy_handler_unittest.cc b/chromium/components/autofill/core/browser/autofill_policy_handler_unittest.cc
index 09ccd18e9a5..a9fb41d8916 100644
--- a/chromium/components/autofill/core/browser/autofill_policy_handler_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_policy_handler_unittest.cc
@@ -4,9 +4,9 @@
#include <memory>
-#include "components/autofill/core/browser/autofill_policy_handler.h"
#include "base/values.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/browser/autofill_policy_handler.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
@@ -23,7 +23,8 @@ TEST_F(AutofillPolicyHandlerTest, Default) {
PrefValueMap prefs;
AutofillPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
- EXPECT_FALSE(prefs.GetValue(autofill::prefs::kAutofillEnabled, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillEnabledDeprecated, nullptr));
}
TEST_F(AutofillPolicyHandlerTest, Enabled) {
@@ -35,8 +36,14 @@ TEST_F(AutofillPolicyHandlerTest, Enabled) {
AutofillPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
- // Enabling Autofill should not set the pref.
- EXPECT_FALSE(prefs.GetValue(autofill::prefs::kAutofillEnabled, nullptr));
+ // Enabling Autofill should not set the pref. Profile and credit card Autofill
+ // prefs should also not get set.
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillEnabledDeprecated, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, nullptr));
}
TEST_F(AutofillPolicyHandlerTest, Disabled) {
@@ -48,14 +55,73 @@ TEST_F(AutofillPolicyHandlerTest, Disabled) {
AutofillPolicyHandler handler;
handler.ApplyPolicySettings(policy, &prefs);
- // Disabling Autofill should switch the pref to managed.
+ // Disabling Autofill by policy should set the pref.
const base::Value* value = nullptr;
- EXPECT_TRUE(prefs.GetValue(autofill::prefs::kAutofillEnabled, &value));
+ EXPECT_TRUE(
+ prefs.GetValue(autofill::prefs::kAutofillEnabledDeprecated, &value));
+ ASSERT_TRUE(value);
+ EXPECT_FALSE(value->GetBool());
+
+ // Disabling Autofill by policy should set the profile Autofill pref.
+ value = nullptr;
+ EXPECT_TRUE(prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, &value));
ASSERT_TRUE(value);
- bool autofill_enabled = true;
- bool result = value->GetAsBoolean(&autofill_enabled);
- ASSERT_TRUE(result);
- EXPECT_FALSE(autofill_enabled);
+ EXPECT_FALSE(value->GetBool());
+
+ // Disabling Autofill by policy should set the credit card Autofill pref.
+ value = nullptr;
+ EXPECT_TRUE(
+ prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, &value));
+ ASSERT_TRUE(value);
+ EXPECT_FALSE(value->GetBool());
+}
+
+TEST_F(AutofillPolicyHandlerTest, DeprecatedPolicyIgnored_AddressEnabled) {
+ policy::PolicyMap policy;
+ policy.Set(policy::key::kAutoFillEnabled, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+ std::make_unique<base::Value>(false), nullptr);
+ policy.Set(policy::key::kAutofillAddressEnabled,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
+ nullptr);
+ PrefValueMap prefs;
+ AutofillPolicyHandler handler;
+ handler.ApplyPolicySettings(policy, &prefs);
+
+ // Settings either of the fine-grained policies should cause the old policy to
+ // be ignored. The fine-grained policies should not get set by this handler
+ // either.
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillEnabledDeprecated, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, nullptr));
+}
+
+TEST_F(AutofillPolicyHandlerTest, DeprecatedPolicyIgnored_CreditCardEnabled) {
+ policy::PolicyMap policy;
+ policy.Set(policy::key::kAutoFillEnabled, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+ std::make_unique<base::Value>(false), nullptr);
+ policy.Set(policy::key::kAutofillCreditCardEnabled,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
+ nullptr);
+ PrefValueMap prefs;
+ AutofillPolicyHandler handler;
+ handler.ApplyPolicySettings(policy, &prefs);
+
+ // Settings either of the fine-grained policies should cause the old policy to
+ // be ignored. The fine-grained policies should not get set by this handler
+ // either.
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillEnabledDeprecated, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillProfileEnabled, nullptr));
+ EXPECT_FALSE(
+ prefs.GetValue(autofill::prefs::kAutofillCreditCardEnabled, nullptr));
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile.cc b/chromium/components/autofill/core/browser/autofill_profile.cc
index ede6790f6f2..2a003f14016 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile.cc
@@ -25,7 +25,6 @@
#include "components/autofill/core/browser/address.h"
#include "components/autofill/core/browser/address_i18n.h"
#include "components/autofill/core/browser/autofill_country.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_profile_comparator.h"
@@ -37,6 +36,7 @@
#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/autofill_features.h"
#include "components/autofill/core/common/autofill_l10n_util.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/strings/grit/components_strings.h"
@@ -297,8 +297,8 @@ void AutofillProfile::GetMatchingTypes(
}
for (auto type : matching_types_in_this_profile) {
if (GetValidityState(type) == INVALID) {
- bool vote_using_invalid_data =
- base::FeatureList::IsEnabled(kAutofillVoteUsingInvalidProfileData);
+ bool vote_using_invalid_data = base::FeatureList::IsEnabled(
+ features::kAutofillVoteUsingInvalidProfileData);
UMA_HISTOGRAM_BOOLEAN("Autofill.InvalidProfileData.UsedForMetrics",
vote_using_invalid_data);
if (!vote_using_invalid_data)
@@ -678,7 +678,7 @@ base::string16 AutofillProfile::ConstructInferredLabel(
std::vector<ServerFieldType> remaining_fields;
for (size_t i = 0; i < included_fields_size && num_fields_to_use > 0; ++i) {
- AddressField address_field;
+ ::i18n::addressinput::AddressField address_field;
if (!i18n::FieldForType(included_fields[i], &address_field) ||
!::i18n::addressinput::IsFieldUsed(address_field,
address_region_code) ||
diff --git a/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc b/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc
index f81dc6f0315..c7af768ddd3 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -7,6 +7,7 @@
#include "base/guid.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/field_types.h"
@@ -16,19 +17,13 @@
using base::UTF16ToUTF8;
using base::UTF8ToUTF16;
+using autofill::data_util::TruncateUTF8;
using sync_pb::AutofillProfileSpecifics;
using syncer::EntityData;
namespace autofill {
namespace {
-std::string TruncateUTF8(const std::string& data) {
- std::string trimmed_value;
- base::TruncateUTF8ToByteSize(data, AutofillTable::kMaxDataLength,
- &trimmed_value);
- return trimmed_value;
-}
-
bool IsAutofillProfileSpecificsValid(
const AutofillProfileSpecifics& specifics) {
return base::IsValidGUID(specifics.guid());
diff --git a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
index 276979c8b10..656ab3f5eb2 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -383,14 +383,13 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_Latn) {
test::kEmptyOrigin));
test::SetProfileInfo(profiles.back().get(), "Miku", "", "Hatsune",
"miku@rei.com", "Rei Inc", "Roppongi Hills Mori Tower",
- "6-10-1 Roppongi", "Minato-ku", "Tokyo", "106-6126",
+ "6-10-1 Roppongi, Minato-ku", "", "Tokyo", "106-6126",
"JP", "+81-3-6384-9000");
profiles.back()->set_language_code("ja_Latn");
static const char* kExpectedLabels[] = {
"",
"Miku Hatsune",
"Miku Hatsune, Roppongi Hills Mori Tower",
- "Miku Hatsune, Roppongi Hills Mori Tower, 6-10-1 Roppongi",
"Miku Hatsune, Roppongi Hills Mori Tower, 6-10-1 Roppongi, Minato-ku",
"Miku Hatsune, Roppongi Hills Mori Tower, 6-10-1 Roppongi, Minato-ku, "
"Tokyo",
@@ -420,24 +419,23 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_JP_ja) {
profiles.push_back(std::make_unique<AutofillProfile>(base::GenerateGUID(),
test::kEmptyOrigin));
test::SetProfileInfo(profiles.back().get(), "ミク", "", "初音",
- "miku@rei.com", "例", "六本木ヒルズ森タワー",
- "六本木 6-10-1", "港区", "東京都", "106-6126", "JP",
+ "miku@rei.com", "例", "港区六本木ヒルズ森タワー",
+ "六本木 6-10-1", "", "東京都", "106-6126", "JP",
"03-6384-9000");
profiles.back()->set_language_code("ja_JP");
static const char* kExpectedLabels[] = {
- "",
- "初音ミク",
- "六本木ヒルズ森タワー初音ミク",
- "六本木ヒルズ森タワー六本木 6-10-1初音ミク",
- "港区六本木ヒルズ森タワー六本木 6-10-1初音ミク",
- "東京都港区六本木ヒルズ森タワー六本木 6-10-1初音ミク",
- "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1初音ミク",
- "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク",
- "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク, Japan",
- "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク, Japan, "
- "miku@rei.com",
- "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク, Japan, "
- "miku@rei.com, 03-6384-9000",
+ "",
+ "初音ミク",
+ "港区六本木ヒルズ森タワー初音ミク",
+ "港区六本木ヒルズ森タワー六本木 6-10-1初音ミク",
+ "東京都港区六本木ヒルズ森タワー六本木 6-10-1初音ミク",
+ "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1初音ミク",
+ "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク",
+ "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク, Japan",
+ "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク, Japan, "
+ "miku@rei.com",
+ "〒106-6126東京都港区六本木ヒルズ森タワー六本木 6-10-1例初音ミク, Japan, "
+ "miku@rei.com, 03-6384-9000",
};
std::vector<base::string16> labels;
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 4f022dd6432..098480bbfd2 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
@@ -14,7 +14,7 @@
#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"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/grit/components_scaled_resources.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_manager.h"
@@ -96,11 +96,18 @@ base::string16 AutofillSaveCardInfoBarDelegateMobile::GetDescriptionText()
if (!IsGooglePayBrandingEnabled())
return base::string16();
- return IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled()
- ? l10n_util::GetStringUTF16(
- IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V3)
- : l10n_util::GetStringUTF16(
- IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V2);
+ if (OfferStoreUnmaskedCards() &&
+ !IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled()) {
+ return l10n_util::GetStringUTF16(
+ features::IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled()
+ ? IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V3_WITH_DEVICE
+ : IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V2_WITH_DEVICE);
+ } else {
+ return l10n_util::GetStringUTF16(
+ features::IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled()
+ ? IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V3
+ : IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_V2);
+ }
}
int AutofillSaveCardInfoBarDelegateMobile::GetIconId() const {
@@ -110,9 +117,10 @@ int AutofillSaveCardInfoBarDelegateMobile::GetIconId() const {
base::string16 AutofillSaveCardInfoBarDelegateMobile::GetMessageText() const {
return l10n_util::GetStringUTF16(
- IsGooglePayBrandingEnabled() || !upload_
+ IsGooglePayBrandingEnabled()
? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD_V3
- : IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD);
+ : upload_ ? IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_TO_CLOUD
+ : IDS_AUTOFILL_SAVE_CARD_PROMPT_TITLE_LOCAL);
}
infobars::InfoBarDelegate::InfoBarIdentifier
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 4e0dfcebea0..8295b74984b 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
@@ -38,6 +38,7 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate {
~AutofillSaveCardInfoBarDelegateMobile() override;
+ bool upload() const { return upload_; }
int issuer_icon_id() const { return issuer_icon_id_; }
const base::string16& card_label() const { return card_label_; }
const base::string16& card_sub_label() const { return card_sub_label_; }
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index 0140cc599e2..2b0efc706da 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -13,13 +13,12 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/common/autofill_constants.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/os_crypt/os_crypt_mocker.h"
@@ -37,6 +36,8 @@ namespace test {
namespace {
+const int kValidityStateBitfield = 1984;
+
std::string GetRandomCardNumber() {
const size_t length = 16;
std::string value;
@@ -56,7 +57,7 @@ std::unique_ptr<PrefService> PrefServiceForTesting() {
std::unique_ptr<PrefService> PrefServiceForTesting(
user_prefs::PrefRegistrySyncable* registry) {
- AutofillManager::RegisterProfilePrefs(registry);
+ prefs::RegisterProfilePrefs(registry);
PrefServiceFactory factory;
factory.set_user_prefs(base::MakeRefCounted<TestingPrefStore>());
@@ -102,14 +103,16 @@ void CreateTestSelectField(const std::vector<const char*>& values,
CreateTestSelectField("", "", "", values, values, values.size(), field);
}
-void CreateTestAddressFormData(FormData* form) {
+void CreateTestAddressFormData(FormData* form, const char* unique_id) {
std::vector<ServerFieldTypeSet> types;
- CreateTestAddressFormData(form, &types);
+ CreateTestAddressFormData(form, &types, unique_id);
}
void CreateTestAddressFormData(FormData* form,
- std::vector<ServerFieldTypeSet>* types) {
- form->name = ASCIIToUTF16("MyForm");
+ std::vector<ServerFieldTypeSet>* types,
+ const char* unique_id) {
+ form->name =
+ ASCIIToUTF16("MyForm") + ASCIIToUTF16(unique_id ? unique_id : "");
form->origin = GURL("http://myform.com/form.html");
form->action = GURL("http://myform.com/submit.html");
form->main_frame_origin =
@@ -175,8 +178,10 @@ void CreateTestAddressFormData(FormData* form,
types->push_back(type_set);
}
-void CreateTestPersonalInformationFormData(FormData* form) {
- form->name = ASCIIToUTF16("MyForm");
+void CreateTestPersonalInformationFormData(FormData* form,
+ const char* unique_id) {
+ form->name =
+ ASCIIToUTF16("MyForm") + ASCIIToUTF16(unique_id ? unique_id : "");
form->origin = GURL("http://myform.com/form.html");
form->action = GURL("http://myform.com/submit.html");
form->main_frame_origin =
@@ -197,8 +202,10 @@ void CreateTestPersonalInformationFormData(FormData* form) {
void CreateTestCreditCardFormData(FormData* form,
bool is_https,
bool use_month_type,
- bool split_names) {
- form->name = ASCIIToUTF16("MyForm");
+ bool split_names,
+ const char* unique_id) {
+ form->name =
+ ASCIIToUTF16("MyForm") + ASCIIToUTF16(unique_id ? unique_id : "");
if (is_https) {
form->origin = GURL("https://myform.com/form.html");
form->action = GURL("https://myform.com/submit.html");
@@ -333,6 +340,50 @@ AutofillProfile GetVerifiedProfile2() {
return profile;
}
+AutofillProfile GetServerProfile() {
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id1");
+ // Note: server profiles don't have email addresses and only have full names.
+ SetProfileInfo(&profile, "", "", "", "", "Google, Inc.", "123 Fake St.",
+ "Apt. 42", "Mountain View", "California", "94043", "US",
+ "1.800.555.1234");
+
+ profile.SetInfo(NAME_FULL, ASCIIToUTF16("John K. Doe"), "en");
+ profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX"));
+ profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ ASCIIToUTF16("Santa Clara"));
+
+ profile.set_language_code("en");
+ profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ profile.set_use_count(7);
+ profile.set_use_date(base::Time::FromTimeT(54321));
+
+ profile.GenerateServerProfileIdentifier();
+
+ return profile;
+}
+
+AutofillProfile GetServerProfile2() {
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "id2");
+ // Note: server profiles don't have email addresses.
+ SetProfileInfo(&profile, "", "", "", "", "Main, Inc.", "4323 Wrong St.",
+ "Apt. 1032", "Sunnyvale", "California", "10011", "US",
+ "+1 514-123-1234");
+
+ profile.SetInfo(NAME_FULL, ASCIIToUTF16("Jim S. Bristow"), "en");
+ profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("XEDEC"));
+ profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ ASCIIToUTF16("Santa Monica"));
+
+ profile.set_language_code("en");
+ profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ profile.set_use_count(14);
+ profile.set_use_date(base::Time::FromTimeT(98765));
+
+ profile.GenerateServerProfileIdentifier();
+
+ return profile;
+}
+
CreditCard GetCreditCard() {
CreditCard credit_card(base::GenerateGUID(), kEmptyOrigin);
SetCreditCardInfo(&credit_card, "Test User", "4111111111111111" /* Visa */,
@@ -364,6 +415,7 @@ CreditCard GetMaskedServerCard() {
test::SetCreditCardInfo(&credit_card, "Bonnie Parker",
"2109" /* Mastercard */, "12", "2020", "1");
credit_card.SetNetworkForMaskedCard(kMasterCard);
+ credit_card.set_card_type(CreditCard::CARD_TYPE_CREDIT);
return credit_card;
}
@@ -372,6 +424,7 @@ CreditCard GetMaskedServerCardAmex() {
test::SetCreditCardInfo(&credit_card, "Justin Thyme", "8431" /* Amex */, "9",
"2020", "1");
credit_card.SetNetworkForMaskedCard(kAmericanExpressCard);
+ credit_card.set_card_type(CreditCard::CARD_TYPE_PREPAID);
return credit_card;
}
@@ -529,7 +582,7 @@ void FillUploadField(AutofillUploadContents::Field* field,
field->set_type(control_type);
if (autocomplete)
field->set_autocomplete(autocomplete);
- field->set_autofill_type(autofill_type);
+ field->add_autofill_type(autofill_type);
}
void FillQueryField(AutofillQueryContents::Form::Field* field,
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.h b/chromium/components/autofill/core/browser/autofill_test_utils.h
index 38077c09d6c..f9d9ca30f4f 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.h
@@ -63,22 +63,28 @@ void CreateTestSelectField(const std::vector<const char*>& values,
// Populates |form| with data corresponding to a simple address form.
// Note that this actually appends fields to the form data, which can be useful
// for building up more complex test forms. Another version of the function is
-// provided in case the caller wants the vector of expected field |types|.
-void CreateTestAddressFormData(FormData* form);
+// provided in case the caller wants the vector of expected field |types|. Use
+// |unique_id| optionally ensure that each form has its own signature.
+void CreateTestAddressFormData(FormData* form, const char* unique_id = nullptr);
void CreateTestAddressFormData(FormData* form,
- std::vector<ServerFieldTypeSet>* types);
+ std::vector<ServerFieldTypeSet>* types,
+ const char* unique_id = nullptr);
// Populates |form| with data corresponding to a simple personal information
-// form, including name and email, but no address-related fields.
-void CreateTestPersonalInformationFormData(FormData* form);
+// form, including name and email, but no address-related fields. Use
+// |unique_id| to optionally ensure that each form has its own signature.
+void CreateTestPersonalInformationFormData(FormData* form,
+ const char* unique_id = nullptr);
// Populates |form| with data corresponding to a simple credit card form.
// Note that this actually appends fields to the form data, which can be
-// useful for building up more complex test forms.
+// useful for building up more complex test forms. Use |unique_id| to optionally
+// ensure that each form has its own signature.
void CreateTestCreditCardFormData(FormData* form,
bool is_https,
bool use_month_type,
- bool split_names = false);
+ bool split_names = false,
+ const char* unique_id = nullptr);
// Returns a full profile with valid info according to rules for Canada.
AutofillProfile GetFullValidProfileForCanada();
@@ -107,6 +113,12 @@ AutofillProfile GetVerifiedProfile();
// Returns a verified profile full of dummy info, different to the above.
AutofillProfile GetVerifiedProfile2();
+// Returns a server profile full of dummy info.
+AutofillProfile GetServerProfile();
+
+// Returns a server profile full of dummy info, different to the above.
+AutofillProfile GetServerProfile2();
+
// Returns a credit card full of dummy info.
CreditCard GetCreditCard();
diff --git a/chromium/components/autofill/core/browser/autofill_type.cc b/chromium/components/autofill/core/browser/autofill_type.cc
index 24447b2d4b1..3f2b48a3509 100644
--- a/chromium/components/autofill/core/browser/autofill_type.cc
+++ b/chromium/components/autofill/core/browser/autofill_type.cc
@@ -612,6 +612,9 @@ std::string AutofillType::ToString() const {
// static
std::string AutofillType::ServerFieldTypeToString(ServerFieldType type) {
+ // You are free to add or remove the String representation of ServerFieldType,
+ // but don't change any existing values, Android WebView presents them to
+ // Autofill Service as part of APIs.
switch (type) {
case NO_SERVER_DATA:
return "NO_SERVER_DATA";
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 575c9e43120..c7281467b2d 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
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_pref_names.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"
@@ -117,10 +117,9 @@ void AutofillWalletDataTypeController::OnUserPrefChanged() {
bool AutofillWalletDataTypeController::IsEnabled() {
DCHECK(CalledOnValidThread());
- // Require the user-visible pref to be enabled to sync Wallet data/metadata,
- // and also check that Autofill for credit cards is not disabled by policy.
- PrefService* ps = sync_client_->GetPrefService();
- return ps->GetBoolean(autofill::prefs::kAutofillWalletImportEnabled);
+ // Require the user-visible pref to be enabled to sync Wallet data/metadata.
+ return autofill::prefs::IsPaymentsIntegrationEnabled(
+ sync_client_->GetPrefService());
}
void AutofillWalletDataTypeController::DisableForPolicy() {
if (state() != NOT_RUNNING && state() != STOPPING) {
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 b6d29b62219..06df1f28eb7 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
@@ -17,10 +17,11 @@
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
+#include "components/sync/driver/configure_context.h"
#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"
@@ -85,8 +86,6 @@ class AutofillWalletDataTypeControllerTest : public testing::Test,
void SetUp() override {
prefs_.registry()->RegisterBooleanPref(
autofill::prefs::kAutofillWalletImportEnabled, true);
- prefs_.registry()->RegisterBooleanPref(
- autofill::prefs::kAutofillCreditCardEnabled, true);
web_data_service_ = base::MakeRefCounted<FakeWebDataService>(
base::ThreadTaskRunnerHandle::Get(),
@@ -124,6 +123,7 @@ class AutofillWalletDataTypeControllerTest : public testing::Test,
void Start() {
autofill_wallet_dtc_->LoadModels(
+ syncer::ConfigureContext(),
base::Bind(&AutofillWalletDataTypeControllerTest::OnLoadFinished,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -178,8 +178,7 @@ TEST_F(AutofillWalletDataTypeControllerTest, DatatypeDisabledWhileRunning) {
EXPECT_EQ(syncer::DataTypeController::RUNNING, autofill_wallet_dtc_->state());
EXPECT_FALSE(last_error_.IsSet());
EXPECT_EQ(syncer::AUTOFILL_WALLET_DATA, last_type_);
- GetPrefService()->SetBoolean(autofill::prefs::kAutofillWalletImportEnabled,
- false);
+ autofill::prefs::SetPaymentsIntegrationEnabled(GetPrefService(), false);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(last_error_.IsSet());
}
@@ -187,8 +186,7 @@ TEST_F(AutofillWalletDataTypeControllerTest, DatatypeDisabledWhileRunning) {
TEST_F(AutofillWalletDataTypeControllerTest, DatatypeDisabledAtStartup) {
SetStartExpectations();
web_data_service_->LoadDatabase();
- GetPrefService()->SetBoolean(autofill::prefs::kAutofillWalletImportEnabled,
- false);
+ autofill::prefs::SetPaymentsIntegrationEnabled(GetPrefService(), false);
EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING,
autofill_wallet_dtc_->state());
Start();
diff --git a/chromium/components/autofill/core/browser/contact_info.cc b/chromium/components/autofill/core/browser/contact_info.cc
index 105d135c28c..c5e1156704c 100644
--- a/chromium/components/autofill/core/browser/contact_info.cc
+++ b/chromium/components/autofill/core/browser/contact_info.cc
@@ -14,6 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_l10n_util.h"
namespace autofill {
@@ -240,7 +241,8 @@ void CompanyInfo::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
}
base::string16 CompanyInfo::GetRawInfo(ServerFieldType type) const {
- if (type == COMPANY_NAME)
+ if (type == COMPANY_NAME &&
+ base::FeatureList::IsEnabled(features::kAutofillEnableCompanyName))
return company_name_;
return base::string16();
diff --git a/chromium/components/autofill/core/browser/contact_info_unittest.cc b/chromium/components/autofill/core/browser/contact_info_unittest.cc
index d07dfa041f1..9fbcdb41b63 100644
--- a/chromium/components/autofill/core/browser/contact_info_unittest.cc
+++ b/chromium/components/autofill/core/browser/contact_info_unittest.cc
@@ -11,8 +11,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
@@ -397,4 +399,30 @@ INSTANTIATE_TEST_CASE_P(
NamePartsAreEmptyTestCase{"", "Mitchell", "", "", false},
NamePartsAreEmptyTestCase{"", "", "Morrison", "", false}));
+struct CompanyNameEnabledDisabledTest : public testing::TestWithParam<bool> {
+ CompanyNameEnabledDisabledTest() : feature_state(GetParam()) {
+ feature_list_.InitWithFeatureState(features::kAutofillEnableCompanyName,
+ feature_state);
+ }
+
+ const bool feature_state;
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_P(CompanyNameEnabledDisabledTest, GetInfo) {
+ SCOPED_TRACE(feature_state ? "Enabled" : "Disabled");
+ const char kCompanyName[] = "Google";
+ CompanyInfo company;
+ company.SetInfo(AutofillType(COMPANY_NAME), ASCIIToUTF16(kCompanyName),
+ "en-US");
+ EXPECT_EQ(ASCIIToUTF16(feature_state ? kCompanyName : ""),
+ company.GetInfo(AutofillType(COMPANY_NAME), "en-US"));
+}
+
+INSTANTIATE_TEST_CASE_P(ContactInfoTest,
+ CompanyNameEnabledDisabledTest,
+ testing::Bool());
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc
index bf5ff7af86e..2b9c802979a 100644
--- a/chromium/components/autofill/core/browser/credit_card.cc
+++ b/chromium/components/autofill/core/browser/credit_card.cc
@@ -28,12 +28,12 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_data_util.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_type.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/autofill_features.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/grit/components_scaled_resources.h"
@@ -46,8 +46,13 @@ using base::ASCIIToUTF16;
namespace autofill {
-const base::char16 kMidlineEllipsis[] = {0x2022, 0x2006, 0x2022, 0x2006, 0x2022,
- 0x2006, 0x2022, 0x2006, 0};
+// Unicode characters used in card number obfuscation:
+// - 0x2022 - Bullet.
+// - 0x2006 - SIX-PER-EM SPACE (small space between bullets).
+// - 0x2060 - WORD-JOINER (makes obfuscated string undivisible).
+const base::char16 kMidlineEllipsis[] = {
+ 0x2022, 0x2060, 0x2006, 0x2060, 0x2022, 0x2060, 0x2006, 0x2060, 0x2022,
+ 0x2060, 0x2006, 0x2060, 0x2022, 0x2060, 0x2006, 0x2060, 0};
namespace {
@@ -798,7 +803,7 @@ base::string16 CreditCard::AbbreviatedExpirationDateForDisplay() const {
return base::string16();
return l10n_util::GetStringFUTF16(
- IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled()
+ features::IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled()
? IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR_V2
: IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR,
month, year);
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 d0aba9954e5..58028662750 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager.cc
@@ -31,12 +31,12 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#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/validation.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
-#include "components/prefs/pref_service.h"
#include "services/identity/public/cpp/identity_manager.h"
#include "url/gurl.h"
@@ -78,11 +78,7 @@ CreditCardSaveManager::CreditCardSaveManager(
payments_client_(payments_client),
app_locale_(app_locale),
personal_data_manager_(personal_data_manager),
- weak_ptr_factory_(this) {
- if (payments_client_) {
- payments_client_->SetSaveDelegate(this);
- }
-}
+ weak_ptr_factory_(this) {}
CreditCardSaveManager::~CreditCardSaveManager() {}
@@ -104,7 +100,6 @@ void CreditCardSaveManager::AttemptToOfferCardUploadSave(
// Abort the uploading if |payments_client_| is nullptr.
if (!payments_client_)
return;
- payments_client_->SetSaveDelegate(this);
upload_request_ = payments::PaymentsClient::UploadRequestDetails();
upload_request_.card = card;
uploading_local_card_ = uploading_local_card;
@@ -156,34 +151,59 @@ void CreditCardSaveManager::AttemptToOfferCardUploadSave(
}
// Add active experiments to the request payload.
- if (IsAutofillUpstreamSendPanFirstSixExperimentEnabled()) {
+ if (features::IsAutofillUpstreamSendPanFirstSixExperimentEnabled()) {
upload_request_.active_experiments.push_back(
- kAutofillUpstreamSendPanFirstSix.name);
+ features::kAutofillUpstreamSendPanFirstSix.name);
}
- if (IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled()) {
+ if (features::IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled()) {
upload_request_.active_experiments.push_back(
- kAutofillUpstreamUpdatePromptExplanation.name);
+ features::kAutofillUpstreamUpdatePromptExplanation.name);
}
- int detected_values = GetDetectedValues();
+ // We store the detected values in the upload request, because the addresses
+ // are being possibly modified in the next code block, and we want the
+ // detected values to reflect addresses *before* they are modified.
+ upload_request_.detected_values = GetDetectedValues();
// If the user must provide cardholder name, log it and set
// |should_request_name_from_user_| so the offer-to-save dialog know to ask
// for it.
should_request_name_from_user_ = false;
- if (detected_values & DetectedValue::USER_PROVIDED_NAME) {
+ if (upload_request_.detected_values & DetectedValue::USER_PROVIDED_NAME) {
upload_decision_metrics_ |=
AutofillMetrics::USER_REQUESTED_TO_PROVIDE_CARDHOLDER_NAME;
should_request_name_from_user_ = true;
}
+ // If the relevant feature is enabled, only send the country of the
+ // recently-used addresses. We make a copy here to avoid modifying
+ // |upload_request_.profiles|, which should always have full addresses even
+ // after this function goes out of scope.
+ bool send_only_country_in_addresses = base::FeatureList::IsEnabled(
+ features::kAutofillSendOnlyCountryInGetUploadDetails);
+ std::vector<AutofillProfile> country_only_profiles;
+ if (send_only_country_in_addresses) {
+ for (const AutofillProfile& address : upload_request_.profiles) {
+ AutofillProfile country_only;
+ country_only.SetInfo(ADDRESS_HOME_COUNTRY,
+ address.GetInfo(ADDRESS_HOME_COUNTRY, app_locale_),
+ app_locale_);
+ country_only_profiles.emplace_back(std::move(country_only));
+ }
+ }
+
// All required data is available, start the upload process.
if (observer_for_testing_)
observer_for_testing_->OnDecideToRequestUploadSave();
payments_client_->GetUploadDetails(
- upload_request_.profiles, detected_values,
+ send_only_country_in_addresses ? country_only_profiles
+ : upload_request_.profiles,
+ upload_request_.detected_values,
base::UTF16ToASCII(CreditCard::StripSeparators(card.number()))
.substr(0, 6),
- upload_request_.active_experiments, app_locale_);
+ upload_request_.active_experiments, app_locale_,
+ base::BindOnce(&CreditCardSaveManager::OnDidGetUploadDetails,
+ weak_ptr_factory_.GetWeakPtr()),
+ payments::kUploadCardBillableServiceNumber);
}
bool CreditCardSaveManager::IsCreditCardUploadEnabled() {
@@ -192,7 +212,7 @@ bool CreditCardSaveManager::IsCreditCardUploadEnabled() {
return observer_for_testing_ ||
::autofill::IsCreditCardUploadEnabled(
client_->GetPrefs(), client_->GetSyncService(),
- client_->GetIdentityManager()->GetPrimaryAccountInfo().email);
+ personal_data_manager_->GetAccountInfoForPaymentsServer().email);
}
bool CreditCardSaveManager::IsUploadEnabledForNetwork(
@@ -221,7 +241,8 @@ void CreditCardSaveManager::OnDidUploadCard(
// 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 (result == AutofillClient::SUCCESS && !server_id.empty() &&
- OfferStoreUnmaskedCards()) {
+ OfferStoreUnmaskedCards() &&
+ !IsAutofillNoLocalSaveOnUploadSuccessExperimentEnabled()) {
upload_request_.card.set_record_type(CreditCard::FULL_SERVER_CARD);
upload_request_.card.SetServerStatus(CreditCard::OK);
upload_request_.card.set_server_id(server_id);
@@ -261,20 +282,20 @@ void CreditCardSaveManager::OnDidGetUploadDetails(
} else {
// If the upload details request failed and we *know* we have all possible
// information (card number, expiration, cvc, name, and address), fall back
- // to a local save. It indicates that "Payments doesn't want this card" or
- // "Payments doesn't currently support this country", in which case the
- // upload details request will consistently fail and if we don't fall back
- // to a local save, the user will never be offered *any* kind of credit card
- // save. (Note that this could intermittently backfire if there's a network
- // breakdown or Payments outage, resulting in sometimes showing upload and
- // sometimes offering local save, but such cases should be rare.)
- int detected_values = GetDetectedValues();
+ // to a local save (for new cards only). It indicates that "Payments doesn't
+ // want this card" or "Payments doesn't currently support this country", in
+ // which case the upload details request will consistently fail and if we
+ // don't fall back to a local save, the user will never be offered *any*
+ // kind of credit card save. (Note that this could intermittently backfire
+ // if there's a network breakdown or Payments outage, resulting in sometimes
+ // showing upload and sometimes offering local save, but such cases should
+ // be rare.)
bool found_name_and_postal_code_and_cvc =
- (detected_values & DetectedValue::CARDHOLDER_NAME ||
- detected_values & DetectedValue::ADDRESS_NAME) &&
- detected_values & DetectedValue::POSTAL_CODE &&
- detected_values & DetectedValue::CVC;
- if (found_name_and_postal_code_and_cvc)
+ (upload_request_.detected_values & DetectedValue::CARDHOLDER_NAME ||
+ upload_request_.detected_values & DetectedValue::ADDRESS_NAME) &&
+ upload_request_.detected_values & DetectedValue::POSTAL_CODE &&
+ upload_request_.detected_values & DetectedValue::CVC;
+ if (found_name_and_postal_code_and_cvc && !uploading_local_card_)
OfferCardLocalSave(upload_request_.card);
upload_decision_metrics_ |=
AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED;
@@ -387,20 +408,6 @@ void CreditCardSaveManager::SetProfilesForCreditCardUpload(
if (verified_zip.empty() && !candidate_profiles.empty())
upload_decision_metrics_ |= AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE;
- // If the relevant feature is enabled, only send the country of the
- // recently-used addresses.
- if (base::FeatureList::IsEnabled(
- features::kAutofillSendOnlyCountryInGetUploadDetails)) {
- for (size_t i = 0; i < candidate_profiles.size(); i++) {
- AutofillProfile country_only;
- country_only.SetInfo(
- ADDRESS_HOME_COUNTRY,
- candidate_profiles[i].GetInfo(ADDRESS_HOME_COUNTRY, app_locale_),
- app_locale_);
- candidate_profiles[i] = std::move(country_only);
- }
- }
-
// Set up |upload_request->profiles|.
upload_request->profiles.assign(candidate_profiles.begin(),
candidate_profiles.end());
@@ -461,13 +468,14 @@ int CreditCardSaveManager::GetDetectedValues() const {
}
}
- // If the billing_customer_number Priority Preference is non-zero, it means
- // the user has a Google Payments account. Include a bit for existence of this
- // account (NOT the id itself), as it will help determine if a new Payments
- // customer might need to be created when save is accepted.
- if (static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
- prefs::kAutofillBillingCustomerNumber)) != 0)
+ // If the billing_customer_number is non-zero, it means the user has a Google
+ // Payments account. Include a bit for existence of this account (NOT the id
+ // itself), as it will help determine if a new Payments customer might need to
+ // be created when save is accepted.
+ if (payments::GetBillingCustomerId(personal_data_manager_,
+ payments_client_->GetPrefService()) != 0) {
detected_values |= DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT;
+ }
// If one of the following is true, signal that cardholder name will be
// explicitly requested in the offer-to-save bubble:
@@ -478,8 +486,9 @@ int CreditCardSaveManager::GetDetectedValues() const {
if ((!(detected_values & DetectedValue::CARDHOLDER_NAME) &&
!(detected_values & DetectedValue::ADDRESS_NAME) &&
!(detected_values & DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT) &&
- IsAutofillUpstreamEditableCardholderNameExperimentEnabled()) ||
- IsAutofillUpstreamAlwaysRequestCardholderNameExperimentEnabled()) {
+ features::IsAutofillUpstreamEditableCardholderNameExperimentEnabled()) ||
+ features::
+ IsAutofillUpstreamAlwaysRequestCardholderNameExperimentEnabled()) {
detected_values |= DetectedValue::USER_PROVIDED_NAME;
}
@@ -519,15 +528,16 @@ void CreditCardSaveManager::SendUploadCardRequest() {
if (observer_for_testing_)
observer_for_testing_->OnSentUploadCardRequest();
upload_request_.app_locale = app_locale_;
- upload_request_.billing_customer_number =
- static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
- prefs::kAutofillBillingCustomerNumber));
+ upload_request_.billing_customer_number = payments::GetBillingCustomerId(
+ personal_data_manager_, payments_client_->GetPrefService());
AutofillMetrics::LogUploadAcceptedCardOriginMetric(
uploading_local_card_
? AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_LOCAL_CARD
: AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_NEW_CARD);
- payments_client_->UploadCard(upload_request_);
+ payments_client_->UploadCard(
+ upload_request_, base::BindOnce(&CreditCardSaveManager::OnDidUploadCard,
+ weak_ptr_factory_.GetWeakPtr()));
}
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 4a32e67e617..dc08f81b3b8 100644
--- a/chromium/components/autofill/core/browser/credit_card_save_manager.h
+++ b/chromium/components/autofill/core/browser/credit_card_save_manager.h
@@ -24,7 +24,7 @@ namespace autofill {
// Manages logic for determining whether upload credit card save to Google
// Payments is available as well as actioning both local and upload credit card
// save logic. Owned by FormDataImporter.
-class CreditCardSaveManager : public payments::PaymentsClientSaveDelegate {
+class CreditCardSaveManager {
public:
// Possible fields and values detected during credit card form submission, to
// be sent to Google Payments to better determine if upload credit card save
@@ -105,19 +105,24 @@ class CreditCardSaveManager : public payments::PaymentsClientSaveDelegate {
void SetAppLocale(std::string app_locale) { app_locale_ = app_locale; }
protected:
- // payments::PaymentsClientSaveDelegate:
- // Exposed for testing.
- void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
- const std::string& server_id) override;
+ // Returns the result of an upload request. If |result| ==
+ // |AutofillClient::SUCCESS|, |server_id| may, optionally, contain the opaque
+ // identifier for the card on the server. Exposed for testing.
+ virtual void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
+ const std::string& server_id);
private:
+ friend class CreditCardSaveManagerTest;
+ friend class CreditCardSaveManagerTestObserverBridge;
friend class SaveCardBubbleViewsBrowserTestBase;
- // payments::PaymentsClientSaveDelegate:
+ // 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) override;
+ std::unique_ptr<base::DictionaryValue> legal_message);
// Examines |card| and the stored profiles and if a candidate set of profiles
// is found that matches the client-side validation rules, assigns the values
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 dd186e27cfb..cdac485ca2c 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
@@ -40,14 +40,15 @@
#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/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
-#include "components/ukm/ukm_source.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_source.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -112,19 +113,16 @@ class CreditCardSaveManagerTest : public testing::Test {
autofill_driver_->SetURLRequestContext(request_context_.get());
payments_client_ = new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(), autofill_client_.GetPrefs(),
- autofill_client_.GetIdentityManager(),
- /*unmask_delegate=*/nullptr,
- // Will be set by CreditCardSaveManager's ctor
- /*save_delegate=*/nullptr);
+ autofill_client_.GetIdentityManager(), &personal_data_);
credit_card_save_manager_ =
new TestCreditCardSaveManager(autofill_driver_.get(), &autofill_client_,
payments_client_, &personal_data_);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
autofill_manager_.reset(new TestAutofillManager(
autofill_driver_.get(), &autofill_client_, &personal_data_,
std::unique_ptr<CreditCardSaveManager>(credit_card_save_manager_),
payments_client_));
autofill_manager_->SetExpectedObservedSubmission(true);
- payments_client_->SetSaveDelegate(credit_card_save_manager_);
}
void TearDown() override {
@@ -140,17 +138,18 @@ class CreditCardSaveManagerTest : public testing::Test {
}
void EnableAutofillUpstreamSendPanFirstSixExperiment() {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstreamSendPanFirstSix);
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillUpstreamSendPanFirstSix);
}
void EnableAutofillUpstreamUpdatePromptExplanationExperiment() {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamUpdatePromptExplanation);
+ features::kAutofillUpstreamUpdatePromptExplanation);
}
void DisableAutofillUpstreamUpdatePromptExplanationExperiment() {
scoped_feature_list_.InitAndDisableFeature(
- kAutofillUpstreamUpdatePromptExplanation);
+ features::kAutofillUpstreamUpdatePromptExplanation);
}
void FormsSeen(const std::vector<FormData>& forms) {
@@ -162,6 +161,10 @@ class CreditCardSaveManagerTest : public testing::Test {
form, false, SubmissionSource::FORM_SUBMISSION, base::TimeTicks::Now());
}
+ void UserHasAcceptedUpload(const base::string16& cardholder_name) {
+ credit_card_save_manager_->OnUserDidAcceptUpload(cardholder_name);
+ }
+
// Populates |form| with data corresponding to a simple credit card form.
// Note that this actually appends fields to the form data, which can be
// useful for building up more complex test forms.
@@ -347,6 +350,7 @@ class CreditCardSaveManagerTest : public testing::Test {
#define MAYBE_ImportFormDataCreditCardHTTPS ImportFormDataCreditCardHTTPS
#endif
TEST_F(CreditCardSaveManagerTest, MAYBE_ImportFormDataCreditCardHTTPS) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
TestSaveCreditCards(true);
}
@@ -358,6 +362,7 @@ TEST_F(CreditCardSaveManagerTest, MAYBE_ImportFormDataCreditCardHTTPS) {
#define MAYBE_ImportFormDataCreditCardHTTP ImportFormDataCreditCardHTTP
#endif
TEST_F(CreditCardSaveManagerTest, MAYBE_ImportFormDataCreditCardHTTP) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
TestSaveCreditCards(false);
}
@@ -371,6 +376,8 @@ TEST_F(CreditCardSaveManagerTest, MAYBE_ImportFormDataCreditCardHTTP) {
CreditCardSavedWhenAutocompleteOff
#endif
TEST_F(CreditCardSaveManagerTest, MAYBE_CreditCardSavedWhenAutocompleteOff) {
+ credit_card_save_manager_->SetCreditCardUploadEnabled(false);
+
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, false, false);
@@ -409,7 +416,6 @@ TEST_F(CreditCardSaveManagerTest, InvalidCreditCardNumberIsNotSaved) {
}
TEST_F(CreditCardSaveManagerTest, CreditCardDisabledDoesNotSave) {
- personal_data_.ClearProfiles();
autofill_manager_->SetCreditCardEnabled(false);
// Create, fill and submit an address form in order to establish a recent
@@ -446,9 +452,6 @@ TEST_F(CreditCardSaveManagerTest, CreditCardDisabledDoesNotSave) {
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FullAddresses) {
scoped_feature_list_.InitAndDisableFeature(
features::kAutofillSendOnlyCountryInGetUploadDetails);
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -478,9 +481,9 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FullAddresses) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
- EXPECT_THAT(
- payments_client_->active_experiments_in_request(),
- UnorderedElementsAre(kAutofillUpstreamUpdatePromptExplanation.name));
+ EXPECT_THAT(payments_client_->active_experiments_in_request(),
+ UnorderedElementsAre(
+ features::kAutofillUpstreamUpdatePromptExplanation.name));
// Verify that one profile was saved, and it was included in the upload
// details request to payments.
@@ -504,6 +507,13 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FullAddresses) {
// modified the profile.
histogram_tester.ExpectTotalCount(
"Autofill.DaysSincePreviousUseAtSubmission.Profile", 0);
+
+ // Simulate that the user has accepted the upload from the prompt.
+ UserHasAcceptedUpload(/*cardholder_name=*/base::ASCIIToUTF16(""));
+ // We should find that full addresses are included in the UploadCard request.
+ EXPECT_THAT(
+ payments_client_->addresses_in_upload_card(),
+ testing::UnorderedElementsAreArray({*personal_data_.GetProfiles()[0]}));
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_OnlyCountryInAddresses) {
@@ -511,9 +521,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_OnlyCountryInAddresses) {
// details request will only contain the country.
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillSendOnlyCountryInGetUploadDetails);
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -543,9 +550,9 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_OnlyCountryInAddresses) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
- EXPECT_THAT(
- payments_client_->active_experiments_in_request(),
- UnorderedElementsAre(kAutofillUpstreamUpdatePromptExplanation.name));
+ EXPECT_THAT(payments_client_->active_experiments_in_request(),
+ UnorderedElementsAre(
+ features::kAutofillUpstreamUpdatePromptExplanation.name));
// Verify that even though the full address profile was saved, only the
// country was included in the upload details request to payments.
@@ -573,15 +580,19 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_OnlyCountryInAddresses) {
// modified the profile.
histogram_tester.ExpectTotalCount(
"Autofill.DaysSincePreviousUseAtSubmission.Profile", 0);
+
+ // Simulate that the user has accepted the upload from the prompt.
+ UserHasAcceptedUpload(/*cardholder_name=*/base::ASCIIToUTF16(""));
+ // We should find that full addresses are included in the UploadCard request,
+ // even though only countries were included in GetUploadDetails.
+ EXPECT_THAT(
+ payments_client_->addresses_in_upload_card(),
+ testing::UnorderedElementsAreArray({*personal_data_.GetProfiles()[0]}));
}
// Tests that a credit card inferred from a form with a credit card first and
// last name can be uploaded.
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FirstAndLastName) {
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -612,9 +623,9 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FirstAndLastName) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
- EXPECT_THAT(
- payments_client_->active_experiments_in_request(),
- UnorderedElementsAre(kAutofillUpstreamUpdatePromptExplanation.name));
+ EXPECT_THAT(payments_client_->active_experiments_in_request(),
+ UnorderedElementsAre(
+ features::kAutofillUpstreamUpdatePromptExplanation.name));
// Server did not send a server_id, expect copy of card is not stored.
EXPECT_TRUE(personal_data_.GetCreditCards().empty());
@@ -642,10 +653,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FirstAndLastName) {
// last name can be uploaded when the last name comes before first name on the
// form.
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_LastAndFirstName) {
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -698,9 +705,9 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_LastAndFirstName) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
- EXPECT_THAT(
- payments_client_->active_experiments_in_request(),
- UnorderedElementsAre(kAutofillUpstreamUpdatePromptExplanation.name));
+ EXPECT_THAT(payments_client_->active_experiments_in_request(),
+ UnorderedElementsAre(
+ features::kAutofillUpstreamUpdatePromptExplanation.name));
// Server did not send a server_id, expect copy of card is not stored.
EXPECT_TRUE(personal_data_.GetCreditCards().empty());
@@ -725,9 +732,8 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_LastAndFirstName) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCardAndSaveCopy) {
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillNoLocalSaveOnUploadSuccess);
const char* const server_id = "InstrumentData:1234";
payments_client_->SetServerIdForCardUpload(server_id);
@@ -775,8 +781,47 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCardAndSaveCopy) {
#endif
}
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FeatureNotEnabled) {
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_DisableLocalSave) {
+ personal_data_.ClearCreditCards();
personal_data_.ClearProfiles();
+
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillNoLocalSaveOnUploadSuccess);
+
+ const char* const server_id = "InstrumentData:1234";
+ payments_client_->SetServerIdForCardUpload(server_id);
+
+ // 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.
+ const char* const card_number = "4111111111111111";
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
+ credit_card_form.fields[1].value = ASCIIToUTF16(card_number);
+ credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth());
+ credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
+ credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+ FormSubmitted(credit_card_form);
+ EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
+
+ // Don't keep a copy of the card on this device.
+ EXPECT_TRUE(personal_data_.GetCreditCards().empty());
+}
+
+TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FeatureNotEnabled) {
credit_card_save_manager_->SetCreditCardUploadEnabled(false);
// Create, fill and submit an address form in order to establish a recent
@@ -811,9 +856,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_FeatureNotEnabled) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CvcUnavailable) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -855,9 +897,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CvcUnavailable) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CvcInvalidLength) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -896,13 +935,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CvcInvalidLength) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MultipleCvcFields) {
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
- // Remove the profiles that were created in the TestPersonalDataManager
- // constructor because they would result in conflicting names that would
- // prevent the upload.
- personal_data_.ClearProfiles();
-
// 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;
@@ -958,13 +990,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_MultipleCvcFields) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoCvcFieldOnForm) {
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
- // Remove the profiles that were created in the TestPersonalDataManager
- // constructor because they would result in conflicting names that would
- // prevent the upload.
- personal_data_.ClearProfiles();
-
// 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;
@@ -1018,13 +1043,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoCvcFieldOnForm) {
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_NoCvcFieldOnForm_InvalidCvcInNonCvcField) {
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
- // Remove the profiles that were created in the TestPersonalDataManager
- // constructor because they would result in conflicting names that would
- // prevent the upload.
- personal_data_.ClearProfiles();
-
// 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;
@@ -1081,13 +1099,6 @@ TEST_F(CreditCardSaveManagerTest,
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_NoCvcFieldOnForm_CvcInNonCvcField) {
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
- // Remove the profiles that were created in the TestPersonalDataManager
- // constructor because they would result in conflicting names that would
- // prevent the upload.
- personal_data_.ClearProfiles();
-
// 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;
@@ -1146,13 +1157,6 @@ TEST_F(CreditCardSaveManagerTest,
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_NoCvcFieldOnForm_CvcInAddressField) {
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
- // Remove the profiles that were created in the TestPersonalDataManager
- // constructor because they would result in conflicting names that would
- // prevent the upload.
- personal_data_.ClearProfiles();
-
// 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;
@@ -1208,9 +1212,6 @@ TEST_F(CreditCardSaveManagerTest,
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoProfileAvailable) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Don't fill or submit an address form.
// Set up our credit card form data.
@@ -1248,9 +1249,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoRecentlyUsedProfile) {
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a profile.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
@@ -1298,9 +1296,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoRecentlyUsedProfile) {
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_CvcUnavailableAndNoProfileAvailable) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Don't fill or submit an address form.
// Set up our credit card form data.
@@ -1336,9 +1331,6 @@ TEST_F(CreditCardSaveManagerTest,
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoNameAvailable) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -1378,9 +1370,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoNameAvailable) {
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_NoNameAvailableAndNoProfileAvailable) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Don't fill or submit an address form.
// Set up our credit card form data.
@@ -1416,13 +1405,10 @@ TEST_F(CreditCardSaveManagerTest,
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ZipCodesConflict) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit two address forms with different zip codes.
FormData address_form1, address_form2;
- test::CreateTestAddressFormData(&address_form1);
- test::CreateTestAddressFormData(&address_form2);
+ test::CreateTestAddressFormData(&address_form1, "1");
+ test::CreateTestAddressFormData(&address_form2, "2");
std::vector<FormData> address_forms;
address_forms.push_back(address_form1);
@@ -1469,9 +1455,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ZipCodesConflict) {
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_ZipCodesDoNotDiscardWhitespace) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create two separate profiles with different zip codes. Must directly add
// instead of submitting a form, because they're deduped on form submit.
AutofillProfile profile1;
@@ -1519,9 +1502,6 @@ TEST_F(CreditCardSaveManagerTest,
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ZipCodesHavePrefixMatch) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit two address forms with different zip codes.
FormData address_form1, address_form2;
test::CreateTestAddressFormData(&address_form1);
@@ -1565,9 +1545,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_ZipCodesHavePrefixMatch) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoZipCodeAvailable) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -1613,9 +1590,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoZipCodeAvailable) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CCFormHasMiddleInitial) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit two address forms with different names.
FormData address_form1, address_form2;
test::CreateTestAddressFormData(&address_form1);
@@ -1658,9 +1632,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CCFormHasMiddleInitial) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoMiddleInitialInCCForm) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit two address forms with different names.
FormData address_form1, address_form2;
test::CreateTestAddressFormData(&address_form1);
@@ -1701,9 +1672,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoMiddleInitialInCCForm) {
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_CCFormHasCardholderMiddleName) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit address form without middle name.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
@@ -1742,9 +1710,6 @@ TEST_F(CreditCardSaveManagerTest,
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CCFormHasAddressMiddleName) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit address form with middle name.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
@@ -1783,9 +1748,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_CCFormHasAddressMiddleName) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NamesCanMismatch) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit two address forms with different names.
FormData address_form1, address_form2;
test::CreateTestAddressFormData(&address_form1);
@@ -1837,9 +1799,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_IgnoreOldProfiles) {
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit two address forms with different names.
FormData address_form1, address_form2;
test::CreateTestAddressFormData(&address_form1);
@@ -1886,9 +1845,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_RequestCardholderNameIfNameMissingAndNoPaymentsCustomer) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -1931,9 +1888,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_RequestCardholderNameIfNameConflictingAndNoPaymentsCustomer) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -1976,9 +1931,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_DoNotRequestCardholderNameIfNameExistsAndNoPaymentsCustomer) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -2019,9 +1972,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_DoNotRequestCardholderNameIfNameMissingAndPaymentsCustomer) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Set the billing_customer_number Priority Preference to designate existence
// of a Payments account.
@@ -2069,9 +2020,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_DoNotRequestCardholderNameIfNameConflictingAndPaymentsCustomer) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Set the billing_customer_number Priority Preference to designate existence
// of a Payments account.
@@ -2119,9 +2068,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_DoNotRequestCardholderNameIfNameMissingAndNoPaymentsCustomerExpOff) {
scoped_feature_list_.InitAndDisableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -2164,9 +2111,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_DoNotRequestCardholderNameIfNameConflictingAndNoPaymentsCustomerExpOff) {
scoped_feature_list_.InitAndDisableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -2211,9 +2156,7 @@ TEST_F(
CreditCardSaveManagerTest,
UploadCreditCard_ShouldRequestCardholderName_ResetBetweenConsecutiveSaves) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamEditableCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamEditableCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -2261,9 +2204,7 @@ TEST_F(
TEST_F(CreditCardSaveManagerTest,
UploadCreditCard_RequestCardholderNameIfTestingExperimentOn) {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillUpstreamAlwaysRequestCardholderName);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ features::kAutofillUpstreamAlwaysRequestCardholderName);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -2308,9 +2249,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_LogPreviousUseDate) {
TestAutofillClock test_clock;
test_clock.SetNow(kArbitraryTime);
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -2352,9 +2290,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_LogPreviousUseDate) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadDetailsFails) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Anything other than "en-US" will cause GetUploadDetails to return a failure
// response.
credit_card_save_manager_->SetAppLocale("pt-BR");
@@ -2396,10 +2331,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadDetailsFails) {
}
TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_NoUpload) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
- credit_card_save_manager_->SetAppLocale("en-US");
-
// 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;
@@ -2435,10 +2366,28 @@ TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_NoUpload) {
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_NothingIfNothingFound) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+// This class is parametrized to allow running all the inheriting tests with and
+// without a specific feature enabled. See INSTANTIATE_TEST_CASE_P.
+class CreditCardSaveManagerFeatureParameterizedTest
+ : public CreditCardSaveManagerTest,
+ public ::testing::WithParamInterface<
+ /*enable_send_only_country_in_get_upload_details=*/bool> {
+ public:
+ CreditCardSaveManagerFeatureParameterizedTest() {}
+ ~CreditCardSaveManagerFeatureParameterizedTest() override {}
+
+ void SetUp() override {
+ CreditCardSaveManagerTest::SetUp();
+ scoped_feature_list_.InitWithFeatureState(
+ features::kAutofillSendOnlyCountryInGetUploadDetails,
+ /*enable_send_only_country_in_get_upload_details=*/GetParam());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CreditCardSaveManagerFeatureParameterizedTest);
+};
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, NothingIfNothingFound) {
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
@@ -2456,10 +2405,7 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_NothingIfNothingFound) {
EXPECT_EQ(payments_client_->detected_values_in_upload_details(), 0);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectCvc) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCvc) {
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
@@ -2478,10 +2424,7 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectCvc) {
CreditCardSaveManager::DetectedValue::CVC);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectCardholderName) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCardholderName) {
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
@@ -2500,10 +2443,7 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectCardholderName) {
CreditCardSaveManager::DetectedValue::CARDHOLDER_NAME);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectAddressName) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectAddressName) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2528,11 +2468,8 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectAddressName) {
CreditCardSaveManager::DetectedValue::ADDRESS_NAME);
}
-TEST_F(CreditCardSaveManagerTest,
- GetDetectedValues_DetectCardholderAndAddressNameIfMatching) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectCardholderAndAddressNameIfMatching) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2558,11 +2495,8 @@ TEST_F(CreditCardSaveManagerTest,
CreditCardSaveManager::DetectedValue::ADDRESS_NAME);
}
-TEST_F(CreditCardSaveManagerTest,
- GetDetectedValues_DetectNoUniqueNameIfNamesConflict) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectNoUniqueNameIfNamesConflict) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2586,10 +2520,7 @@ TEST_F(CreditCardSaveManagerTest,
EXPECT_EQ(payments_client_->detected_values_in_upload_details(), 0);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectPostalCode) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectPostalCode) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2614,11 +2545,8 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectPostalCode) {
CreditCardSaveManager::DetectedValue::POSTAL_CODE);
}
-TEST_F(CreditCardSaveManagerTest,
- GetDetectedValues_DetectNoUniquePostalCodeIfZipsConflict) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectNoUniquePostalCodeIfZipsConflict) {
// Set up two new address profiles with conflicting postal codes.
AutofillProfile profile1;
profile1.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2646,10 +2574,7 @@ TEST_F(CreditCardSaveManagerTest,
EXPECT_EQ(payments_client_->detected_values_in_upload_details(), 0);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectAddressLine) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectAddressLine) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2674,10 +2599,7 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectAddressLine) {
CreditCardSaveManager::DetectedValue::ADDRESS_LINE);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectLocality) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectLocality) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2702,10 +2624,8 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectLocality) {
CreditCardSaveManager::DetectedValue::LOCALITY);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectAdministrativeArea) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectAdministrativeArea) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2730,10 +2650,7 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectAdministrativeArea) {
CreditCardSaveManager::DetectedValue::ADMINISTRATIVE_AREA);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectCountryCode) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectCountryCode) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2758,11 +2675,8 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectCountryCode) {
CreditCardSaveManager::DetectedValue::COUNTRY_CODE);
}
-TEST_F(CreditCardSaveManagerTest,
- GetDetectedValues_DetectHasGooglePaymentAccount) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectHasGooglePaymentAccount) {
// Set the billing_customer_number Priority Preference to designate existence
// of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -2786,10 +2700,7 @@ TEST_F(CreditCardSaveManagerTest,
CreditCardSaveManager::DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT);
}
-TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectEverythingAtOnce) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest, DetectEverythingAtOnce) {
// Set up a new address profile.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2826,11 +2737,8 @@ TEST_F(CreditCardSaveManagerTest, GetDetectedValues_DetectEverythingAtOnce) {
CreditCardSaveManager::DetectedValue::COUNTRY_CODE);
}
-TEST_F(CreditCardSaveManagerTest,
- GetDetectedValues_DetectSubsetOfPossibleFields) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectSubsetOfPossibleFields) {
// Set up a new address profile, taking out address line and state.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2864,11 +2772,8 @@ TEST_F(CreditCardSaveManagerTest,
// This test checks that ADDRESS_LINE, LOCALITY, ADMINISTRATIVE_AREA, and
// COUNTRY_CODE don't care about possible conflicts or consistency and are
// populated if even one address profile contains it.
-TEST_F(CreditCardSaveManagerTest,
- GetDetectedValues_DetectAddressComponentsAcrossProfiles) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ DetectAddressComponentsAcrossProfiles) {
// Set up four new address profiles, each with a different address component.
AutofillProfile profile1;
profile1.set_guid("00000000-0000-0000-0000-000000000200");
@@ -2909,11 +2814,8 @@ TEST_F(CreditCardSaveManagerTest,
CreditCardSaveManager::DetectedValue::COUNTRY_CODE);
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_LogAdditionalErrorsWithUploadDetailsFailure) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Anything other than "en-US" will cause GetUploadDetails to return a failure
// response.
credit_card_save_manager_->SetAppLocale("pt-BR");
@@ -2962,12 +2864,9 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(
- CreditCardSaveManagerTest,
+TEST_P(
+ CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_ShouldOfferLocalSaveIfEverythingDetectedAndPaymentsDeclines) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Anything other than "en-US" will cause GetUploadDetails to return a failure
// response.
credit_card_save_manager_->SetAppLocale("pt-BR");
@@ -3005,12 +2904,9 @@ TEST_F(
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
}
-TEST_F(
- CreditCardSaveManagerTest,
+TEST_P(
+ CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_ShouldOfferLocalSaveIfEverythingDetectedAndPaymentsDeclines_WithFirstAndLastName) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Anything other than "en-US" will cause GetUploadDetails to return a failure
// response.
credit_card_save_manager_->SetAppLocale("pt-BR");
@@ -3058,12 +2954,9 @@ TEST_F(
"Autofill.SaveCardWithFirstAndLastNameComplete.Server", 0);
}
-TEST_F(
- CreditCardSaveManagerTest,
+TEST_P(
+ CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_ShouldNotOfferLocalSaveIfSomethingNotDetectedAndPaymentsDeclines) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Anything other than "en-US" will cause GetUploadDetails to return a failure
// response.
credit_card_save_manager_->SetAppLocale("pt-BR");
@@ -3098,11 +2991,8 @@ TEST_F(
EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded());
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_PaymentsDecidesOfferToSaveIfNoCvc) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -3143,11 +3033,8 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_PaymentsDecidesOfferToSaveIfNoName) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -3189,11 +3076,8 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_PaymentsDecidesOfferToSaveIfConflictingNames) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
@@ -3234,11 +3118,8 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_PaymentsDecidesOfferToSaveIfNoZip) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Set up a new address profile without a postal code.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -3281,11 +3162,8 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_PaymentsDecidesOfferToSaveIfConflictingZips) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Set up two new address profiles with conflicting postal codes.
AutofillProfile profile1;
profile1.set_guid("00000000-0000-0000-0000-000000000200");
@@ -3340,11 +3218,8 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(CreditCardSaveManagerTest,
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
UploadCreditCard_PaymentsDecidesOfferToSaveIfNothingFound) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
// Set up a new address profile without a name or postal code.
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000200");
@@ -3392,18 +3267,23 @@ TEST_F(CreditCardSaveManagerTest,
1 /* expected_num_matching_entries */);
}
-TEST_F(
- CreditCardSaveManagerTest,
- UploadCreditCard_AddUpdatePromptExplanationFlagStateToRequestIfExperimentOn) {
- EnableAutofillUpstreamUpdatePromptExplanationExperiment();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ UploadCreditCard_UploadOfLocalCard) {
+ // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
+ // enter below.
+ CreditCard local_card;
+ test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111",
+ NextMonth().c_str(), NextYear().c_str(), "1");
+ local_card.set_record_type(CreditCard::LOCAL_CARD);
+ personal_data_.AddCreditCard(local_card);
// 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);
@@ -3411,35 +3291,40 @@ TEST_F(
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("4444333322221111");
+ 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 upload happened and that the enabled UpdatePromptExplanation
- // experiment flag state was sent in the request.
+ base::HistogramTester histogram_tester;
+
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
- EXPECT_THAT(
- payments_client_->active_experiments_in_request(),
- UnorderedElementsAre(kAutofillUpstreamUpdatePromptExplanation.name));
-}
-TEST_F(CreditCardSaveManagerTest,
- UploadCreditCard_DoNotAddAnyFlagStatesToRequestIfExperimentsOff) {
- DisableAutofillUpstreamUpdatePromptExplanationExperiment();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+ // Verify that metrics noted it was an existing local card for which credit
+ // card upload was offered and accepted.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UploadOfferedCardOrigin",
+ AutofillMetrics::OFFERING_UPLOAD_OF_LOCAL_CARD, 1);
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UploadAcceptedCardOrigin",
+ AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_LOCAL_CARD, 1);
+}
+TEST_P(CreditCardSaveManagerFeatureParameterizedTest,
+ UploadCreditCard_UploadOfNewCard) {
// 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);
@@ -3447,6 +3332,7 @@ TEST_F(CreditCardSaveManagerTest,
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");
@@ -3455,18 +3341,24 @@ TEST_F(CreditCardSaveManagerTest,
credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- // Confirm that upload happened and that no experiment flag state was sent in
- // the request.
+ base::HistogramTester histogram_tester;
+
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
- EXPECT_TRUE(payments_client_->active_experiments_in_request().empty());
+
+ // Verify that metrics noted it was a brand new card for which credit card
+ // upload was offered and accepted.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UploadOfferedCardOrigin",
+ AutofillMetrics::OFFERING_UPLOAD_OF_NEW_CARD, 1);
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UploadAcceptedCardOrigin",
+ AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_NEW_CARD, 1);
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_AddPanFirstSixToRequest) {
EnableAutofillUpstreamSendPanFirstSixExperiment();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
@@ -3496,32 +3388,30 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_AddPanFirstSixToRequest) {
EXPECT_EQ(payments_client_->pan_first_six_in_upload_details(), "444433");
// Confirm that the "send pan first six" experiment flag and enabled
// UpdatePromptExplanation experiment flag state was sent in the request.
- EXPECT_THAT(
- payments_client_->active_experiments_in_request(),
- UnorderedElementsAre(kAutofillUpstreamSendPanFirstSix.name,
- kAutofillUpstreamUpdatePromptExplanation.name));
+ EXPECT_THAT(payments_client_->active_experiments_in_request(),
+ UnorderedElementsAre(
+ features::kAutofillUpstreamSendPanFirstSix.name,
+ features::kAutofillUpstreamUpdatePromptExplanation.name));
}
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfLocalCard) {
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
-
- // Add a local credit card whose |TypeAndLastFourDigits| matches what we will
- // enter below.
- CreditCard local_card;
- test::SetCreditCardInfo(&local_card, "Flo Master", "4111111111111111",
- NextMonth().c_str(), NextYear().c_str(), "1");
- local_card.set_record_type(CreditCard::LOCAL_CARD);
- personal_data_.AddCreditCard(local_card);
+// Every test will appear with suffix /0 (param false) and /1 (param true), e.g.
+// CreditCardSaveManagerFeatureParameterizedTest.NothingIfNothingFound/0:
+// Feature disabled
+// CreditCardSaveManagerFeatureParameterizedTest.NothingIfNothingFound/1:
+// Feature enabled.
+INSTANTIATE_TEST_CASE_P(, // Empty instatiation name.
+ CreditCardSaveManagerFeatureParameterizedTest,
+ ::testing::Values(false, true));
+TEST_F(
+ CreditCardSaveManagerTest,
+ UploadCreditCard_AddUpdatePromptExplanationFlagStateToRequestIfExperimentOn) {
+ EnableAutofillUpstreamUpdatePromptExplanationExperiment();
// 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);
@@ -3529,44 +3419,33 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfLocalCard) {
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[1].value = ASCIIToUTF16("4444333322221111");
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;
-
+ // Confirm upload happened and that the enabled UpdatePromptExplanation
+ // experiment flag state was sent in the request.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that metrics noted it was an existing local card for which credit
- // card upload was offered and accepted.
- histogram_tester.ExpectUniqueSample(
- "Autofill.UploadOfferedCardOrigin",
- AutofillMetrics::OFFERING_UPLOAD_OF_LOCAL_CARD, 1);
- histogram_tester.ExpectUniqueSample(
- "Autofill.UploadAcceptedCardOrigin",
- AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_LOCAL_CARD, 1);
+ EXPECT_THAT(payments_client_->active_experiments_in_request(),
+ UnorderedElementsAre(
+ features::kAutofillUpstreamUpdatePromptExplanation.name));
}
-TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfNewCard) {
- // No cards already on the device.
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+TEST_F(CreditCardSaveManagerTest,
+ UploadCreditCard_DoNotAddAnyFlagStatesToRequestIfExperimentsOff) {
+ DisableAutofillUpstreamUpdatePromptExplanationExperiment();
// 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);
@@ -3574,7 +3453,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfNewCard) {
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");
@@ -3583,25 +3461,15 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_UploadOfNewCard) {
credit_card_form.fields[3].value = ASCIIToUTF16(NextYear());
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
+ // Confirm that upload happened and that no experiment flag state was sent in
+ // the request.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded());
-
- // Verify that metrics noted it was a brand new card for which credit card
- // upload was offered and accepted.
- histogram_tester.ExpectUniqueSample(
- "Autofill.UploadOfferedCardOrigin",
- AutofillMetrics::OFFERING_UPLOAD_OF_NEW_CARD, 1);
- histogram_tester.ExpectUniqueSample(
- "Autofill.UploadAcceptedCardOrigin",
- AutofillMetrics::USER_ACCEPTED_UPLOAD_OF_NEW_CARD, 1);
+ EXPECT_TRUE(payments_client_->active_experiments_in_request().empty());
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloDisallowed) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillUpstreamDisallowElo);
@@ -3632,8 +3500,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloDisallowed) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloAllowed) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
scoped_feature_list_.InitAndDisableFeature(
features::kAutofillUpstreamDisallowElo);
@@ -3663,8 +3529,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_EloAllowed) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_JcbDisallowed) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillUpstreamDisallowJcb);
@@ -3695,8 +3559,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_JcbDisallowed) {
}
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_JcbAllowed) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
scoped_feature_list_.InitAndDisableFeature(
features::kAutofillUpstreamDisallowJcb);
@@ -3730,8 +3592,6 @@ TEST_F(CreditCardSaveManagerTest, UploadCreditCard_JcbAllowed) {
// This test ensures that we do not offer local save (again) for the card that
// FormDataImporter imported.
TEST_F(CreditCardSaveManagerTest, UploadCreditCard_DisallowedLocalCard) {
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillUpstreamDisallowElo);
diff --git a/chromium/components/autofill/core/browser/field_filler.cc b/chromium/components/autofill/core/browser/field_filler.cc
index cb536280e1e..e1e56eb081d 100644
--- a/chromium/components/autofill/core/browser/field_filler.cc
+++ b/chromium/components/autofill/core/browser/field_filler.cc
@@ -17,7 +17,6 @@
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_data_model.h"
#include "components/autofill/core/browser/autofill_data_util.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_type.h"
@@ -26,6 +25,7 @@
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/state_names.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_l10n_util.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/strings/grit/components_strings.h"
@@ -626,7 +626,7 @@ bool FieldFiller::FillFormField(const AutofillField& field,
const AutofillType type = field.Type();
// Don't fill if autocomplete=off is set on |field| on desktop for non credit
// card related fields.
- if (!base::FeatureList::IsEnabled(kAutofillAlwaysFillAddresses) &&
+ if (!base::FeatureList::IsEnabled(features::kAutofillAlwaysFillAddresses) &&
!field.should_autocomplete && IsDesktopPlatform() &&
(type.group() != CREDIT_CARD)) {
return false;
diff --git a/chromium/components/autofill/core/browser/field_filler_unittest.cc b/chromium/components/autofill/core/browser/field_filler_unittest.cc
index 928e2b9f97e..b092bfbff40 100644
--- a/chromium/components/autofill/core/browser/field_filler_unittest.cc
+++ b/chromium/components/autofill/core/browser/field_filler_unittest.cc
@@ -19,7 +19,6 @@
#include "base/test/scoped_task_environment.h"
#include "components/autofill/core/browser/address_normalizer.h"
#include "components/autofill/core/browser/address_normalizer_impl.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -27,6 +26,7 @@
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
@@ -335,7 +335,7 @@ TEST_F(AutofillFieldFillerTest, IsFieldFillable) {
TEST_F(AutofillFieldFillerTest,
FillFormField_AutocompleteOffRespected_AddressField) {
base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+ feature_list.InitAndDisableFeature(features::kAutofillAlwaysFillAddresses);
AutofillField field;
field.should_autocomplete = false;
diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc
index 543e5c7cabd..95c19c44471 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer.cc
@@ -20,7 +20,6 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_country.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_type.h"
@@ -138,7 +137,8 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
if (local_card_migration_manager_ &&
local_card_migration_manager_->ShouldOfferLocalCardMigration(
imported_credit_card_record_type_)) {
- local_card_migration_manager_->AttemptToOfferLocalCardMigration();
+ local_card_migration_manager_->AttemptToOfferLocalCardMigration(
+ /*is_from_settings_page=*/false);
return;
}
diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h
index 596fd065c8d..e7bc5b6f71c 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.h
+++ b/chromium/components/autofill/core/browser/form_data_importer.h
@@ -61,6 +61,10 @@ class FormDataImporter {
static bool IsValidLearnableProfile(const AutofillProfile& profile,
const std::string& app_locale);
+ LocalCardMigrationManager* local_card_migration_manager() {
+ return local_card_migration_manager_.get();
+ }
+
protected:
// Exposed for testing.
void set_credit_card_save_manager(
@@ -142,6 +146,7 @@ class FormDataImporter {
friend class FormDataImporterTest;
friend class FormDataImporterTestBase;
friend class SaveCardBubbleViewsBrowserTestBase;
+ friend class SaveCardInfobarEGTestHelper;
FRIEND_TEST_ALL_PREFIXES(AutofillMergeTest, MergeProfiles);
FRIEND_TEST_ALL_PREFIXES(FormDataImporterTest,
AllowDuplicateMaskedServerCardIfFlagEnabled);
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 3c0c3300f53..556fdb6ac1a 100644
--- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -38,6 +38,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
@@ -183,8 +184,7 @@ class FormDataImporterTestBase {
const char* exp_cc_month,
const char* exp_cc_year) {
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
@@ -294,8 +294,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles) {
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -332,8 +331,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_BadEmail) {
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
ASSERT_EQ(0U, personal_data_manager_->GetProfiles().size());
@@ -362,8 +360,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoEmails) {
"example@example.com", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -394,8 +391,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoDifferentEmails) {
&field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
ASSERT_EQ(0U, personal_data_manager_->GetProfiles().size());
@@ -415,8 +411,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_NotEnoughFilledFields) {
"4111 1111 1111 1111", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
ASSERT_EQ(0U, personal_data_manager_->GetProfiles().size());
@@ -442,8 +437,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressUSA) {
test::CreateTestFormField("Country:", "country", "USA", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -470,8 +464,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressGB) {
&field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -493,8 +486,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MinimumAddressGI) {
test::CreateTestFormField("Country:", "country", "Gibraltar", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -534,8 +526,7 @@ TEST_F(FormDataImporterTest,
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -574,8 +565,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MultilineAddress) {
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -615,8 +605,7 @@ TEST_F(FormDataImporterTest,
form1.fields.push_back(field);
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
WaitForOnPersonalDataChanged();
@@ -652,8 +641,7 @@ TEST_F(FormDataImporterTest,
form2.fields.push_back(field);
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
WaitForOnPersonalDataChanged();
@@ -710,8 +698,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_TwoValidProfilesSameForm) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -785,8 +772,7 @@ TEST_F(FormDataImporterTest,
// Still able to do the import.
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -868,8 +854,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_ThreeValidProfilesSameForm) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -923,8 +908,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_SameProfileWithConflict) {
form1.fields.push_back(field);
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
WaitForOnPersonalDataChanged();
@@ -970,8 +954,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_SameProfileWithConflict) {
form2.fields.push_back(field);
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
WaitForOnPersonalDataChanged();
@@ -1008,8 +991,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInOld) {
form1.fields.push_back(field);
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
WaitForOnPersonalDataChanged();
@@ -1045,8 +1027,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInOld) {
form2.fields.push_back(field);
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
WaitForOnPersonalDataChanged();
@@ -1090,8 +1071,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInNew) {
form1.fields.push_back(field);
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure1));
WaitForOnPersonalDataChanged();
@@ -1129,8 +1109,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_MissingInfoInNew) {
form2.fields.push_back(field);
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
WaitForOnPersonalDataChanged();
@@ -1166,8 +1145,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_InsufficientAddress) {
form1.fields.push_back(field);
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure1));
// Since no refresh is expected, reload the data from the database to make
@@ -1219,8 +1197,7 @@ TEST_F(FormDataImporterTest,
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
// Wait for the refresh, which in this case is a no-op.
@@ -1240,8 +1217,8 @@ TEST_F(FormDataImporterTest,
form.fields[0] = field;
FormStructure form_structure2(form);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
+
EXPECT_TRUE(ImportAddressProfiles(form_structure2));
// Wait for the refresh, which in this case is a no-op.
@@ -1281,8 +1258,7 @@ TEST_F(FormDataImporterTest, ImportAddressProfiles_UnrecognizedCountry) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
// Since no refresh is expected, reload the data from the database to make
@@ -1321,8 +1297,7 @@ TEST_F(FormDataImporterTest,
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(ImportAddressProfiles(form_structure));
WaitForOnPersonalDataChanged();
@@ -1369,8 +1344,7 @@ TEST_F(FormDataImporterTest,
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_FALSE(ImportAddressProfiles(form_structure));
// Since no refresh is expected, reload the data from the database to make
@@ -1391,8 +1365,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_Valid) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
base::HistogramTester histogram_tester;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
@@ -1420,8 +1393,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_InvalidCardNumber) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
base::HistogramTester histogram_tester;
EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
@@ -1444,8 +1416,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_InvalidExpiryDate) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
base::HistogramTester histogram_tester;
EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
@@ -1481,8 +1452,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MonthSelectInvalidText) {
form.fields[2].option_contents = contents;
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
base::HistogramTester histogram_tester;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
@@ -1511,8 +1481,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_TwoValidCards) {
"2999");
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
@@ -1533,8 +1502,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_TwoValidCards) {
AddFullCreditCardForm(&form2, "", "5500 0000 0000 0004", "02", "2999");
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
+
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
ASSERT_TRUE(imported_credit_card2);
@@ -1652,8 +1621,7 @@ TEST_F(FormDataImporterTest,
// The card should not be offered to be saved locally because the feature flag
// is disabled.
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
@@ -1682,8 +1650,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_DuplicateServerCards_FullCard) {
// The card should not be offered to be saved locally because it only matches
// the full server card.
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
@@ -1696,8 +1663,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_SameCreditCardWithConflict) {
"2998");
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
@@ -1720,8 +1686,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_SameCreditCardWithConflict) {
/* different year */ "2999");
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
@@ -1746,8 +1711,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_ShouldReturnLocalCard) {
"2998");
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
@@ -1770,8 +1734,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_ShouldReturnLocalCard) {
/* different year */ "2999");
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2,
/* should_return_local_card= */ true,
@@ -1799,8 +1762,8 @@ TEST_F(FormDataImporterTest, ImportCreditCard_EmptyCardWithConflict) {
"2998");
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
+
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
@@ -1822,8 +1785,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_EmptyCardWithConflict) {
"2999");
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_FALSE(
ImportCreditCard(form_structure2, false, &imported_credit_card2));
@@ -1850,8 +1812,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInNew) {
"2999");
FormStructure form_structure1(form1);
- form_structure1.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure1.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure1, false, &imported_credit_card));
ASSERT_TRUE(imported_credit_card);
@@ -1874,8 +1835,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInNew) {
"4111-1111-1111-1111", "01", "2999");
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(ImportCreditCard(form_structure2, false, &imported_credit_card2));
EXPECT_FALSE(imported_credit_card2);
@@ -1900,8 +1860,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInNew) {
/* no year */ nullptr);
FormStructure form_structure3(form3);
- form_structure3.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure3.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card3;
EXPECT_FALSE(
ImportCreditCard(form_structure3, false, &imported_credit_card3));
@@ -1943,8 +1902,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_MissingInfoInOld) {
/* different year */ "2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
@@ -1985,8 +1943,7 @@ TEST_F(FormDataImporterTest, ImportCreditCard_SameCardWithSeparators) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
EXPECT_FALSE(imported_credit_card);
@@ -2026,8 +1983,7 @@ TEST_F(FormDataImporterTest,
/* different year */ "2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(ImportCreditCard(form_structure, false, &imported_credit_card));
ASSERT_FALSE(imported_credit_card);
@@ -2065,8 +2021,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2086,8 +2041,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure2(form2);
- form_structure2.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure2.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card2;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure2, /*profile_autofill_enabled=*/true,
@@ -2124,8 +2078,7 @@ TEST_F(FormDataImporterTest,
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form3.fields.push_back(field);
FormStructure form_structure3(form3);
- form_structure3.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure3.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card3;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure3, /*profile_autofill_enabled=*/true,
@@ -2146,8 +2099,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2182,8 +2134,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2218,8 +2169,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2253,8 +2203,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2275,8 +2224,7 @@ TEST_F(FormDataImporterTest,
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2298,8 +2246,7 @@ TEST_F(FormDataImporterTest,
"1999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2338,8 +2285,7 @@ TEST_F(FormDataImporterTest,
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2384,8 +2330,7 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressOneCreditCard) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
@@ -2463,8 +2408,7 @@ TEST_F(FormDataImporterTest, ImportFormData_TwoAddressesOneCreditCard) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ 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(
@@ -2519,8 +2463,7 @@ TEST_F(FormDataImporterTest, ImportFormData_AddressesDisabledOneCreditCard) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/false,
@@ -2574,8 +2517,7 @@ TEST_F(FormDataImporterTest, ImportFormData_OneAddressCreditCardDisabled) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
@@ -2633,8 +2575,7 @@ TEST_F(FormDataImporterTest, ImportFormData_AddressCreditCardDisabled) {
"2999");
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
@@ -2689,8 +2630,7 @@ TEST_F(FormDataImporterTest, DontDuplicateMaskedServerCard) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -2737,8 +2677,7 @@ TEST_F(FormDataImporterTest, DontDuplicateFullServerCard) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
@@ -2781,8 +2720,7 @@ TEST_F(FormDataImporterTest,
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
@@ -2829,8 +2767,7 @@ TEST_F(FormDataImporterTest,
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
@@ -2877,8 +2814,7 @@ TEST_F(FormDataImporterTest,
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
@@ -2926,8 +2862,7 @@ TEST_F(FormDataImporterTest,
base::HistogramTester histogram_tester;
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
std::unique_ptr<CreditCard> imported_credit_card;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
diff --git a/chromium/components/autofill/core/browser/form_field.cc b/chromium/components/autofill/core/browser/form_field.cc
index c8d7bf171e3..3328e18c6f9 100644
--- a/chromium/components/autofill/core/browser/form_field.cc
+++ b/chromium/components/autofill/core/browser/form_field.cc
@@ -70,7 +70,8 @@ FieldCandidatesMap FormField::ParseFormFields(
ParseFormFieldsPass(PhoneField::Parse, processed_fields, &field_candidates);
// Address pass.
- ParseFormFieldsPass(AddressField::Parse, processed_fields, &field_candidates);
+ ParseFormFieldsPass(autofill::AddressField::Parse, processed_fields,
+ &field_candidates);
// Credit card pass.
ParseFormFieldsPass(CreditCardField::Parse, processed_fields,
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index f712a2d4983..9760452889a 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -25,7 +25,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_candidates.h"
@@ -44,7 +44,6 @@
#include "components/autofill/core/common/form_field_data_predictions.h"
#include "components/autofill/core/common/signatures_util.h"
#include "components/security_state/core/security_state.h"
-#include "services/metrics/public/cpp/ukm_recorder.h"
#include "url/origin.h"
namespace autofill {
@@ -287,14 +286,6 @@ std::ostream& operator<<(
return out;
}
-bool IsCreditCardExpirationType(ServerFieldType type) {
- return type == CREDIT_CARD_EXP_MONTH ||
- type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
- type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
- type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
- type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
-}
-
// Returns true iff all form fields autofill types are in |contained_types|.
bool AllTypesCaptured(const FormStructure& form,
const ServerFieldTypeSet& contained_types) {
@@ -338,6 +329,7 @@ void EncodePasswordAttributesVote(
FormStructure::FormStructure(const FormData& form)
: form_name_(form.name),
+ submission_event_(PasswordForm::SubmissionIndicatorEvent::NONE),
source_url_(form.origin),
target_url_(form.action),
main_frame_origin_(form.main_frame_origin),
@@ -353,7 +345,9 @@ FormStructure::FormStructure(const FormData& form)
is_formless_checkout_(form.is_formless_checkout),
all_fields_are_passwords_(!form.fields.empty()),
is_signin_upload_(false),
- passwords_were_revealed_(false) {
+ form_parsed_timestamp_(base::TimeTicks::Now()),
+ passwords_were_revealed_(false),
+ developer_engagement_metrics_(0) {
// Copy the form fields.
std::map<base::string16, size_t> unique_names;
for (const FormFieldData& field : form.fields) {
@@ -381,8 +375,7 @@ FormStructure::FormStructure(const FormData& form)
FormStructure::~FormStructure() {}
-void FormStructure::DetermineHeuristicTypes(ukm::UkmRecorder* ukm_recorder,
- ukm::SourceId source_id) {
+void FormStructure::DetermineHeuristicTypes() {
const auto determine_heuristic_types_start_time = base::TimeTicks::Now();
// First, try to detect field types based on each field's |autocomplete|
@@ -407,31 +400,25 @@ void FormStructure::DetermineHeuristicTypes(ukm::UkmRecorder* ukm_recorder,
UpdateAutofillCount();
IdentifySections(has_author_specified_sections_);
- int developer_engagement_metrics = 0;
+ developer_engagement_metrics_ = 0;
if (IsAutofillable()) {
AutofillMetrics::DeveloperEngagementMetric metric =
has_author_specified_types_
? AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS
: AutofillMetrics::FILLABLE_FORM_PARSED_WITHOUT_TYPE_HINTS;
- developer_engagement_metrics |= 1 << metric;
+ developer_engagement_metrics_ |= 1 << metric;
AutofillMetrics::LogDeveloperEngagementMetric(metric);
}
if (has_author_specified_upi_vpa_hint_) {
AutofillMetrics::LogDeveloperEngagementMetric(
AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT);
- developer_engagement_metrics |=
+ developer_engagement_metrics_ |=
1 << AutofillMetrics::FORM_CONTAINS_UPI_VPA_HINT;
}
- if (developer_engagement_metrics) {
- AutofillMetrics::LogDeveloperEngagementUkm(
- ukm_recorder, source_id, main_frame_origin().GetURL(),
- IsCompleteCreditCardForm(), GetFormTypes(),
- developer_engagement_metrics, form_signature());
- }
-
- if (base::FeatureList::IsEnabled(kAutofillRationalizeFieldTypePredictions))
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillRationalizeFieldTypePredictions))
RationalizeFieldTypePredictions();
AutofillMetrics::LogDetermineHeuristicTypesTiming(
@@ -444,7 +431,6 @@ bool FormStructure::EncodeUploadRequest(
const std::string& login_form_signature,
bool observed_submission,
AutofillUploadContents* upload) const {
- DCHECK(ShouldBeUploaded());
DCHECK(AllTypesCaptured(*this, available_field_types));
upload->set_submission(observed_submission);
@@ -453,6 +439,13 @@ 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_);
+ if (submission_event_ != PasswordForm::SubmissionIndicatorEvent::NONE) {
+ DCHECK(submission_event_ != PasswordForm::SubmissionIndicatorEvent::
+ SUBMISSION_INDICATOR_EVENT_COUNT);
+ upload->set_submission_event(
+ static_cast<AutofillUploadContents_SubmissionIndicatorEvent>(
+ submission_event_));
+ }
if (password_attributes_vote_) {
EncodePasswordAttributesVote(*password_attributes_vote_,
password_length_vote_, upload);
@@ -523,6 +516,14 @@ void FormStructure::ParseQueryResponse(
VLOG(1) << "Autofill query response was successfully parsed:\n" << response;
+ ProcessQueryResponse(response, forms, form_interactions_ukm_logger);
+}
+
+// static
+void FormStructure::ProcessQueryResponse(
+ const AutofillQueryResponseContents& response,
+ const std::vector<FormStructure*>& forms,
+ AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) {
AutofillMetrics::LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_PARSED);
bool heuristics_detected_fillable_field = false;
@@ -582,7 +583,8 @@ void FormStructure::ParseQueryResponse(
features::kAutofillRationalizeRepeatedServerPredictions))
form->RationalizeRepeatedFields(form_interactions_ukm_logger);
- if (base::FeatureList::IsEnabled(kAutofillRationalizeFieldTypePredictions))
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillRationalizeFieldTypePredictions))
form->RationalizeFieldTypePredictions();
form->IdentifySections(false);
@@ -663,7 +665,7 @@ bool FormStructure::IsCompleteCreditCardForm() const {
bool found_cc_expiration = false;
for (const auto& field : fields_) {
ServerFieldType type = field->Type().GetStorableType();
- if (!found_cc_expiration && IsCreditCardExpirationType(type)) {
+ if (!found_cc_expiration && data_util::IsCreditCardExpirationType(type)) {
found_cc_expiration = true;
} else if (!found_cc_number && type == CREDIT_CARD_NUMBER) {
found_cc_number = true;
@@ -723,8 +725,7 @@ bool FormStructure::ShouldBeQueried() const {
}
bool FormStructure::ShouldBeUploaded() const {
- return (has_password_field_ ||
- active_field_count() >= MinRequiredFieldsForUpload()) &&
+ return active_field_count() >= MinRequiredFieldsForUpload() &&
ShouldBeParsed();
}
@@ -769,7 +770,7 @@ void FormStructure::RetrieveFromCache(
UpdateAutofillCount();
// Update form parsed timestamp
- set_form_parsed_timestamp(cached_form.form_parsed_timestamp());
+ form_parsed_timestamp_ = cached_form.form_parsed_timestamp_;
// The form signature should match between query and upload requests to the
// server. On many websites, form elements are dynamically added, removed, or
@@ -1580,49 +1581,45 @@ void FormStructure::EncodeFormForUpload(AutofillUploadContents* upload) const {
if (IsCheckable(field->check_status))
continue;
- const ServerFieldTypeSet& types = field->possible_types();
- for (const auto& field_type : types) {
- // Add the same field elements as the query and a few more below.
- if (ShouldSkipField(*field))
- continue;
+ // Add the same field elements as the query and a few more below.
+ if (ShouldSkipField(*field))
+ continue;
- AutofillUploadContents::Field* added_field = upload->add_field();
- added_field->set_autofill_type(field_type);
- if (field->generation_type()) {
- added_field->set_generation_type(field->generation_type());
- added_field->set_generated_password_changed(
- field->generated_password_changed());
- }
+ auto* added_field = upload->add_field();
- if (field->form_classifier_outcome()) {
- added_field->set_form_classifier_outcome(
- field->form_classifier_outcome());
- }
+ for (const auto& field_type : field->possible_types()) {
+ added_field->add_autofill_type(field_type);
+ }
- if (field->vote_type()) {
- added_field->set_vote_type(field->vote_type());
- }
+ if (field->generation_type()) {
+ added_field->set_generation_type(field->generation_type());
+ added_field->set_generated_password_changed(
+ field->generated_password_changed());
+ }
+
+ if (field->vote_type()) {
+ added_field->set_vote_type(field->vote_type());
+ }
- added_field->set_signature(field->GetFieldSignature());
+ added_field->set_signature(field->GetFieldSignature());
- if (field->properties_mask)
- added_field->set_properties_mask(field->properties_mask);
+ if (field->properties_mask)
+ added_field->set_properties_mask(field->properties_mask);
- if (IsAutofillFieldMetadataEnabled()) {
- added_field->set_type(field->form_control_type);
+ if (IsAutofillFieldMetadataEnabled()) {
+ added_field->set_type(field->form_control_type);
- if (!field->name.empty())
- added_field->set_name(base::UTF16ToUTF8(field->name));
+ if (!field->name.empty())
+ added_field->set_name(base::UTF16ToUTF8(field->name));
- if (!field->id.empty())
- added_field->set_id(base::UTF16ToUTF8(field->id));
+ if (!field->id.empty())
+ added_field->set_id(base::UTF16ToUTF8(field->id));
- if (!field->autocomplete_attribute.empty())
- added_field->set_autocomplete(field->autocomplete_attribute);
+ if (!field->autocomplete_attribute.empty())
+ added_field->set_autocomplete(field->autocomplete_attribute);
- if (!field->css_classes.empty())
- added_field->set_css_classes(base::UTF16ToUTF8(field->css_classes));
- }
+ if (!field->css_classes.empty())
+ added_field->set_css_classes(base::UTF16ToUTF8(field->css_classes));
}
}
}
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index d41617d668a..2cf3f6e028e 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -23,6 +23,7 @@
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
+#include "components/autofill/core/common/password_form.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -32,10 +33,6 @@ namespace base {
class TimeTicks;
}
-namespace ukm {
-class UkmRecorder;
-}
-
namespace autofill {
// Password attributes (whether a password has special symbols, numeric, etc.)
@@ -58,10 +55,8 @@ class FormStructure {
virtual ~FormStructure();
// Runs several heuristics against the form fields to determine their possible
- // types. If |ukm_recorder| and |source_id| is specified, logs UKM for
- // the form structure corresponding to the source mapped from the |source_id|.
- void DetermineHeuristicTypes(ukm::UkmRecorder* ukm_recorder,
- ukm::SourceId source_id);
+ // types.
+ void DetermineHeuristicTypes();
// Encodes the proto |upload| request from this FormStructure.
// In some cases, a |login_form_signature| is included as part of the upload.
@@ -80,12 +75,21 @@ class FormStructure {
std::vector<std::string>* encoded_signatures,
autofill::AutofillQueryContents* query);
- // Parses the field types from the server query response. |forms| must be the
- // same as the one passed to EncodeQueryRequest when constructing the query.
+ // Parses response as AutofillQueryResponseContents proto and calls
+ // ProcessQueryResponse.
static void ParseQueryResponse(std::string response,
const std::vector<FormStructure*>& forms,
AutofillMetrics::FormInteractionsUkmLogger*);
+ // Parses the field types from the server query response. |forms| must be the
+ // same as the one passed to EncodeQueryRequest when constructing the query.
+ // |form_interactions_ukm_logger| is used to provide logs to UKM and can be
+ // null in tests.
+ static void ProcessQueryResponse(
+ const AutofillQueryResponseContents& response,
+ const std::vector<FormStructure*>& forms,
+ AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger);
+
// Returns predictions using the details from the given |form_structures| and
// their fields' predicted types.
static std::vector<FormDataPredictions> GetFieldTypePredictions(
@@ -128,8 +132,8 @@ class FormStructure {
// directly.
bool ShouldBeQueried() const;
- // Returns true if we should upload votes for this form to the crowd-sourcing
- // server.
+ // Returns true if we should upload Autofill votes for this form to the
+ // crowd-sourcing server. It is not applied for Password Manager votes.
bool ShouldBeUploaded() const;
// Sets the field types to be those set for |cached_form|.
@@ -228,14 +232,16 @@ class FormStructure {
return has_author_specified_upi_vpa_hint_;
}
+ void set_submission_event(
+ PasswordForm::SubmissionIndicatorEvent submission_event) {
+ submission_event_ = submission_event;
+ }
+
void set_upload_required(UploadRequired required) {
upload_required_ = required;
}
UploadRequired upload_required() const { return upload_required_; }
- void set_form_parsed_timestamp(const base::TimeTicks form_parsed_timestamp) {
- form_parsed_timestamp_ = form_parsed_timestamp;
- }
base::TimeTicks form_parsed_timestamp() const {
return form_parsed_timestamp_;
}
@@ -284,6 +290,11 @@ class FormStructure {
"|password_attributes_vote_| has no value.";
return password_length_vote_;
}
+
+ PasswordForm::SubmissionIndicatorEvent get_submission_event_for_testing()
+ const {
+ return submission_event_;
+ }
#endif
bool operator==(const FormData& form) const;
@@ -295,6 +306,8 @@ class FormStructure {
// - Name for Autofill of first field
base::string16 GetIdentifierForRefill() const;
+ int developer_engagement_metrics() { return developer_engagement_metrics_; };
+
private:
friend class AutofillMergeTest;
friend class FormStructureTest;
@@ -442,6 +455,10 @@ class FormStructure {
// The name of the form.
base::string16 form_name_;
+ // The type of the event that was taken as an indication that the form has
+ // been successfully submitted.
+ PasswordForm::SubmissionIndicatorEvent submission_event_;
+
// The source URL.
GURL source_url_;
@@ -505,7 +522,7 @@ class FormStructure {
// the form name, and the form field names in a 64-bit hash.
FormSignature form_signature_;
- // When a form is parsed on this page.
+ // The timestamp (not wallclock time) when this form was initially parsed.
base::TimeTicks form_parsed_timestamp_;
// If phone number rationalization has been performed for a given section.
@@ -523,6 +540,11 @@ class FormStructure {
// has no value, |password_length_vote_| should be ignored.
size_t password_length_vote_;
+ // Used to record whether developer has used autocomplete markup or
+ // UPI-VPA hints, This is a bitmask of DeveloperEngagementMetric and set in
+ // DetermineHeuristicTypes().
+ int developer_engagement_metrics_;
+
DISALLOW_COPY_AND_ASSIGN(FormStructure);
};
diff --git a/chromium/components/autofill/core/browser/form_structure_process_query_response_fuzzer.cc b/chromium/components/autofill/core/browser/form_structure_process_query_response_fuzzer.cc
new file mode 100644
index 00000000000..b684f2f6ed2
--- /dev/null
+++ b/chromium/components/autofill/core/browser/form_structure_process_query_response_fuzzer.cc
@@ -0,0 +1,50 @@
+// 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 <stdlib.h>
+
+#include <iostream>
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "testing/libfuzzer/proto/lpm_interface.h"
+
+namespace autofill {
+namespace {
+
+using ::base::ASCIIToUTF16;
+
+void AddField(const std::string& label,
+ const std::string& name,
+ const std::string& control_type,
+ FormData* form_data) {
+ FormFieldData field;
+ field.label = ASCIIToUTF16(label);
+ field.name = ASCIIToUTF16(name);
+ field.form_control_type = control_type;
+
+ form_data->fields.push_back(field);
+}
+
+// We run ProcessQueryResponse twice with hardcoded forms vectors. Ideally we
+// should also generate forms vectors by using fuzzing, but at the moment we use
+// simplified approach. There is no specific reason to use those two hardcoded
+// forms vectors, so it can be changed if needed.
+DEFINE_BINARY_PROTO_FUZZER(const AutofillQueryResponseContents& response) {
+ std::vector<FormStructure*> forms;
+ FormStructure::ProcessQueryResponse(response, forms, nullptr);
+
+ FormData form_data;
+ AddField("username", "username", "text", &form_data);
+ AddField("password", "password", "password", &form_data);
+
+ FormStructure form(form_data);
+ forms.push_back(&form);
+ FormStructure::ProcessQueryResponse(response, forms, nullptr);
+}
+
+} // namespace
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index ee8a503e718..61c14608319 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -20,6 +20,7 @@
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/form_data.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 "components/variations/entropy_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -96,8 +97,7 @@ class FormStructureTest : public testing::Test {
InitFeature(&feature_list, kAutofillEnforceMinRequiredFieldsForHeuristics,
enforce_min_fields);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
return form_structure.IsAutofillable();
}
@@ -210,8 +210,7 @@ TEST_F(FormStructureTest, AutofillCount) {
// Only text and select fields that are heuristically matched are counted.
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_EQ(3U, form_structure->autofill_count());
// Add a field with should_autocomplete=false. This should not be considered a
@@ -223,8 +222,7 @@ TEST_F(FormStructureTest, AutofillCount) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_EQ(4U, form_structure->autofill_count());
}
@@ -470,8 +468,7 @@ TEST_F(FormStructureTest, DetermineHeuristicTypes_AutocompleteFalse) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->ShouldBeParsed());
EXPECT_EQ(3U, form_structure->autofill_count());
EXPECT_EQ(NAME_FULL, form_structure->field(0)->Type().GetStorableType());
@@ -525,8 +522,7 @@ TEST_F(FormStructureTest, HeuristicsContactInfo) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -583,8 +579,7 @@ TEST_F(FormStructureTest, HeuristicsAutocompleteAttribute) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
EXPECT_TRUE(form_structure->has_author_specified_types());
EXPECT_TRUE(form_structure->has_author_specified_upi_vpa_hint());
@@ -630,8 +625,7 @@ TEST_F(FormStructureTest, Heuristics_FormlessNonCheckoutForm) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -647,8 +641,7 @@ TEST_F(FormStructureTest, Heuristics_FormlessNonCheckoutForm) {
form.is_form_tag = false;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -689,8 +682,7 @@ TEST_F(FormStructureTest, StripCommonNamePrefix) {
form.fields.push_back(field);
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -730,8 +722,7 @@ TEST_F(FormStructureTest, StripCommonNamePrefix_SmallPrefix) {
form.fields.push_back(field);
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -767,8 +758,7 @@ TEST_F(FormStructureTest, IsCompleteCreditCardForm_Minimal) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsCompleteCreditCardForm());
}
@@ -806,8 +796,7 @@ TEST_F(FormStructureTest, IsCompleteCreditCardForm_Full) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsCompleteCreditCardForm());
}
@@ -825,8 +814,7 @@ TEST_F(FormStructureTest, IsCompleteCreditCardForm_OnlyCCNumber) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_FALSE(form_structure->IsCompleteCreditCardForm());
}
@@ -867,8 +855,7 @@ TEST_F(FormStructureTest, IsCompleteCreditCardForm_AddressForm) {
field.name = base::string16();
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_FALSE(form_structure->IsCompleteCreditCardForm());
}
@@ -898,8 +885,7 @@ TEST_F(FormStructureTest, HeuristicsAutocompleteAttributePhoneTypes) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -939,8 +925,7 @@ TEST_F(FormStructureTest,
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
EXPECT_TRUE(form_structure->ShouldBeQueried());
EXPECT_TRUE(form_structure->ShouldBeUploaded());
@@ -979,8 +964,7 @@ TEST_F(FormStructureTest,
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
EXPECT_TRUE(form_structure->ShouldBeQueried());
EXPECT_TRUE(form_structure->ShouldBeUploaded());
@@ -1024,8 +1008,7 @@ TEST_F(FormStructureTest,
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
EXPECT_TRUE(form_structure->ShouldBeQueried());
@@ -1069,8 +1052,7 @@ TEST_F(FormStructureTest,
// Disabled.
{});
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
ASSERT_EQ(2U, form_structure.field_count());
ASSERT_EQ(0U, form_structure.autofill_count());
EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type());
@@ -1083,8 +1065,7 @@ TEST_F(FormStructureTest,
// Default configuration.
{
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
ASSERT_EQ(2U, form_structure.field_count());
ASSERT_EQ(0U, form_structure.autofill_count());
EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type());
@@ -1100,8 +1081,7 @@ TEST_F(FormStructureTest,
feature_list.InitAndDisableFeature(
kAutofillEnforceMinRequiredFieldsForHeuristics);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
ASSERT_EQ(2U, form_structure.field_count());
ASSERT_EQ(2U, form_structure.autofill_count());
EXPECT_EQ(NAME_FIRST, form_structure.field(0)->heuristic_type());
@@ -1150,8 +1130,7 @@ TEST_F(FormStructureTest,
// Disabled.
{});
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
ASSERT_EQ(2U, form_structure.field_count());
ASSERT_EQ(1U, form_structure.autofill_count());
EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type());
@@ -1167,8 +1146,7 @@ TEST_F(FormStructureTest,
feature_list.InitAndDisableFeature(
kAutofillEnforceMinRequiredFieldsForHeuristics);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
ASSERT_EQ(2U, form_structure.field_count());
ASSERT_EQ(2U, form_structure.autofill_count());
EXPECT_EQ(NAME_FIRST, form_structure.field(0)->heuristic_type());
@@ -1190,8 +1168,7 @@ TEST_F(FormStructureTest,
FormData form_copy = form;
form_copy.fields.pop_back();
FormStructure form_structure(form_copy);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
ASSERT_EQ(1U, form_structure.field_count());
ASSERT_EQ(1U, form_structure.autofill_count());
EXPECT_EQ(UNKNOWN_TYPE, form_structure.field(0)->heuristic_type());
@@ -1231,8 +1208,7 @@ TEST_F(FormStructureTest, PasswordFormShouldBeQueried) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(form_structure.ShouldBeQueried());
EXPECT_TRUE(form_structure.ShouldBeUploaded());
}
@@ -1284,8 +1260,7 @@ TEST_F(FormStructureTest, HeuristicsAutocompleteAttributeWithSections) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
EXPECT_TRUE(form_structure.IsAutofillable());
// Expect the correct number of fields.
@@ -1330,8 +1305,7 @@ TEST_F(FormStructureTest,
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
// Expect the correct number of fields.
ASSERT_EQ(6U, form_structure.field_count());
@@ -1360,8 +1334,7 @@ TEST_F(FormStructureTest, HeuristicsAutocompleteAttributeWithSectionsRepeated) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
// Expect the correct number of fields.
ASSERT_EQ(2U, form_structure.field_count());
@@ -1398,8 +1371,7 @@ TEST_F(FormStructureTest, HeuristicsDontOverrideAutocompleteAttributeSections) {
form.fields.push_back(field);
FormStructure form_structure(form);
- form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ form_structure.DetermineHeuristicTypes();
// Expect the correct number of fields.
ASSERT_EQ(4U, form_structure.field_count());
@@ -1462,8 +1434,7 @@ TEST_F(FormStructureTest, HeuristicsSample8) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(10U, form_structure->field_count());
ASSERT_EQ(9U, form_structure->autofill_count());
@@ -1529,8 +1500,7 @@ TEST_F(FormStructureTest, HeuristicsSample6) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(7U, form_structure->field_count());
ASSERT_EQ(6U, form_structure->autofill_count());
@@ -1595,8 +1565,7 @@ TEST_F(FormStructureTest, HeuristicsLabelsOnly) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(8U, form_structure->field_count());
ASSERT_EQ(7U, form_structure->autofill_count());
@@ -1653,8 +1622,7 @@ TEST_F(FormStructureTest, HeuristicsCreditCardInfo) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(6U, form_structure->field_count());
ASSERT_EQ(5U, form_structure->autofill_count());
@@ -1714,8 +1682,7 @@ TEST_F(FormStructureTest, HeuristicsCreditCardInfoWithUnknownCardField) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(7U, form_structure->field_count());
ASSERT_EQ(5U, form_structure->autofill_count());
@@ -1762,8 +1729,7 @@ TEST_F(FormStructureTest, ThreeAddressLines) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(4U, form_structure->field_count());
ASSERT_EQ(4U, form_structure->autofill_count());
@@ -1803,8 +1769,7 @@ TEST_F(FormStructureTest, SurplusAddressLinesIgnored) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
ASSERT_EQ(4U, form_structure->field_count());
ASSERT_EQ(3U, form_structure->autofill_count());
@@ -1847,8 +1812,7 @@ TEST_F(FormStructureTest, ThreeAddressLinesExpedia) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(4U, form_structure->field_count());
EXPECT_EQ(4U, form_structure->autofill_count());
@@ -1886,8 +1850,7 @@ TEST_F(FormStructureTest, TwoAddressLinesEbay) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(3U, form_structure->field_count());
ASSERT_EQ(3U, form_structure->autofill_count());
@@ -1920,8 +1883,7 @@ TEST_F(FormStructureTest, HeuristicsStateWithProvince) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(3U, form_structure->field_count());
ASSERT_EQ(3U, form_structure->autofill_count());
@@ -1987,8 +1949,7 @@ TEST_F(FormStructureTest, HeuristicsWithBilling) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(11U, form_structure->field_count());
ASSERT_EQ(11U, form_structure->autofill_count());
@@ -2037,8 +1998,7 @@ TEST_F(FormStructureTest, ThreePartPhoneNumber) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
ASSERT_EQ(4U, form_structure->field_count());
ASSERT_EQ(4U, form_structure->autofill_count());
@@ -2081,8 +2041,7 @@ TEST_F(FormStructureTest, HeuristicsInfernoCC) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -2136,8 +2095,7 @@ TEST_F(FormStructureTest, HeuristicsInferCCNames_NamesNotFirst) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -2195,8 +2153,7 @@ TEST_F(FormStructureTest, HeuristicsInferCCNames_NamesFirst) {
form.fields.push_back(field);
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
EXPECT_TRUE(form_structure->IsAutofillable());
// Expect the correct number of fields.
@@ -2379,8 +2336,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -2431,6 +2387,8 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
form_structure->set_password_attributes_vote(
std::make_pair(PasswordAttribute::kHasNumeric, true));
form_structure->set_password_length_vote(10u);
+ form_structure->set_submission_event(
+ PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION);
ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
for (size_t i = 0; i < form_structure->field_count(); ++i)
@@ -2450,6 +2408,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
// Prepare the expected proto string.
AutofillUploadContents upload;
upload.set_submission(true);
+ upload.set_submission_event(AutofillUploadContents::HTML_FORM_SUBMISSION);
upload.set_client_version("6.1.1715.1442/en (GGLL)");
upload.set_form_signature(8736493185895608956U);
upload.set_autofill_used(false);
@@ -2509,6 +2468,8 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
form_structure->set_password_attributes_vote(
std::make_pair(PasswordAttribute::kHasNumeric, true));
form_structure->set_password_length_vote(10u);
+ form_structure->set_submission_event(
+ PasswordForm::SubmissionIndicatorEvent::HTML_FORM_SUBMISSION);
ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
for (size_t i = 0; i < form_structure->field_count(); ++i)
form_structure->field(i)->set_possible_types(possible_field_types[i]);
@@ -2516,18 +2477,18 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
// Adjust the expected proto string.
upload.set_form_signature(7816485729218079147U);
upload.set_autofill_used(false);
- // Create an additonal 8 fields (total of 13).
- for (int i = 0; i < 8; ++i) {
+ // Create an additional 2 fields (total of 7).
+ for (int i = 0; i < 2; ++i) {
test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
nullptr, 30U);
}
// Put the appropriate autofill type on the different address fields.
- upload.mutable_field(6)->set_autofill_type(31U);
- upload.mutable_field(7)->set_autofill_type(37U);
- upload.mutable_field(8)->set_autofill_type(38U);
- upload.mutable_field(10)->set_autofill_type(31U);
- upload.mutable_field(11)->set_autofill_type(37U);
- upload.mutable_field(12)->set_autofill_type(38U);
+ upload.mutable_field(5)->add_autofill_type(31U);
+ upload.mutable_field(5)->add_autofill_type(37U);
+ upload.mutable_field(5)->add_autofill_type(38U);
+ upload.mutable_field(6)->add_autofill_type(31U);
+ upload.mutable_field(6)->add_autofill_type(37U);
+ upload.mutable_field(6)->add_autofill_type(38U);
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
AutofillUploadContents encoded_upload3;
@@ -2566,8 +2527,7 @@ TEST_F(FormStructureTest,
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.label = ASCIIToUTF16("First Name");
@@ -2616,11 +2576,6 @@ TEST_F(FormStructureTest,
AutofillUploadContents::Field::
MANUALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM);
form_structure->field(i)->set_generated_password_changed(true);
- form_structure->field(i)->set_form_classifier_outcome(
- AutofillUploadContents::Field::GENERATION_ELEMENT);
- } else {
- form_structure->field(i)->set_form_classifier_outcome(
- AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
}
if (form_structure->field(i)->name == ASCIIToUTF16("username")) {
form_structure->field(i)->set_vote_type(
@@ -2649,34 +2604,24 @@ TEST_F(FormStructureTest,
AutofillUploadContents::Field* upload_firstname_field = upload.add_field();
test::FillUploadField(upload_firstname_field, 4224610201U, "firstname", "",
"given-name", 3U);
- upload_firstname_field->set_form_classifier_outcome(
- AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
AutofillUploadContents::Field* upload_lastname_field = upload.add_field();
test::FillUploadField(upload_lastname_field, 2786066110U, "lastname", "",
"family-name", 5U);
- upload_lastname_field->set_form_classifier_outcome(
- AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
AutofillUploadContents::Field* upload_email_field = upload.add_field();
test::FillUploadField(upload_email_field, 1029417091U, "email", "email",
"email", 9U);
- upload_email_field->set_form_classifier_outcome(
- AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
AutofillUploadContents::Field* upload_username_field = upload.add_field();
test::FillUploadField(upload_username_field, 239111655U, "username", "text",
"email", 86U);
- upload_username_field->set_form_classifier_outcome(
- AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
upload_username_field->set_vote_type(
AutofillUploadContents::Field::CREDENTIALS_REUSED);
AutofillUploadContents::Field* upload_password_field = upload.add_field();
test::FillUploadField(upload_password_field, 2051817934U, "password",
"password", "email", 76U);
- upload_password_field->set_form_classifier_outcome(
- AutofillUploadContents::Field::GENERATION_ELEMENT);
upload_password_field->set_generation_type(
AutofillUploadContents::Field::
MANUALLY_TRIGGERED_GENERATION_ON_SIGN_UP_FORM);
@@ -2699,8 +2644,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithAutocomplete) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -2774,8 +2718,7 @@ TEST_F(FormStructureTest, EncodeUploadRequestWithPropertiesMask) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -2862,8 +2805,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_ObservedSubmissionFalse) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -2933,8 +2875,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithLabels) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -3073,8 +3014,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithFormName) {
// Setting the form name which we expect to see in the upload.
form.name = ASCIIToUTF16("myform");
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -3137,8 +3077,7 @@ TEST_F(FormStructureTest, EncodeUploadRequestPartialMetadata) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -3212,8 +3151,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
form_structure.reset(new FormStructure(form));
- form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure->DetermineHeuristicTypes();
FormFieldData field;
field.form_control_type = "text";
@@ -3621,14 +3559,9 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
form_structure->field(2)->set_possible_types(possible_field_types[2]);
// Modify the expected upload.
- // Put the NAME_FIRST prediction on the third field.
- upload.mutable_field(2)->set_autofill_type(3);
- // Replace the fourth field by the old third field.
- test::FillUploadField(upload.mutable_field(3), 2404144663U, "last", "text",
- nullptr, 5U);
- // Re-add the old fourth field.
- test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
- nullptr, 30U);
+ // Add the NAME_FIRST prediction to the third field.
+ upload.mutable_field(2)->add_autofill_type(3);
+ upload.mutable_field(2)->mutable_autofill_type()->SwapElements(0, 1);
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -3646,8 +3579,7 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
possible_field_types[form_structure->field_count() - 1]);
// Adjust the expected upload proto.
- test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
- nullptr, 31U);
+ upload.mutable_field(3)->add_autofill_type(31U);
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
AutofillUploadContents encoded_upload3;
@@ -3666,7 +3598,7 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
possible_field_types[form_structure->field_count() - 1]);
// Adjust the expected upload proto.
- upload.mutable_field(5)->set_autofill_type(60);
+ upload.mutable_field(3)->set_autofill_type(1, 60);
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
AutofillUploadContents encoded_upload4;
@@ -4113,7 +4045,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_UnknownType) {
form_data.fields.push_back(field);
FormStructure form(form_data);
- form.DetermineHeuristicTypes(nullptr /* ukm_service */, 0 /* source_id */);
+ form.DetermineHeuristicTypes();
// Setup the query response.
AutofillQueryResponseContents response;
@@ -4240,8 +4172,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_AuthorDefinedTypes) {
FormStructure form_structure(form);
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
- forms.front()->DetermineHeuristicTypes(nullptr /* ukm_service */,
- 0 /* source_id */);
+ forms.front()->DetermineHeuristicTypes();
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(EMAIL_ADDRESS);
@@ -4301,7 +4232,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeLoneField) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
@@ -4316,7 +4247,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeLoneField) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
@@ -4363,7 +4294,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
@@ -4377,7 +4308,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
@@ -4436,7 +4367,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
@@ -4455,7 +4386,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
@@ -4513,7 +4444,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
@@ -4529,7 +4460,7 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(
- autofill::kAutofillRationalizeFieldTypePredictions);
+ autofill::features::kAutofillRationalizeFieldTypePredictions);
FormStructure::ParseQueryResponse(response_string, forms, nullptr);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
@@ -5158,8 +5089,7 @@ TEST_F(FormStructureTest,
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
// Will identify the sections based on the heuristics types.
- form_structure.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure.DetermineHeuristicTypes();
AutofillQueryResponseContents response;
// Billing
@@ -5250,8 +5180,7 @@ TEST_F(
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
// Will identify the sections based on the heuristics types.
- form_structure.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure.DetermineHeuristicTypes();
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
@@ -5350,8 +5279,7 @@ TEST_F(FormStructureTest,
forms.push_back(&form_structure);
// Will identify the sections based on the heuristics types.
- form_structure.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
+ form_structure.DetermineHeuristicTypes();
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
@@ -5614,9 +5542,7 @@ TEST_F(FormStructureTest,
forms.push_back(&form_structure);
// Will identify the sections based on the heuristics types.
- form_structure.DetermineHeuristicTypes(/*ukm_service=*/nullptr,
- /*source_id=*/0);
-
+ form_structure.DetermineHeuristicTypes();
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
response.add_field()->set_overall_type_prediction(ADDRESS_HOME_COUNTRY);
@@ -5824,4 +5750,20 @@ TEST_F(FormStructureTest, AllowBigForms) {
EXPECT_EQ(1u, encoded_signatures.size());
}
+// Tests that an Autofill upload for password form with 1 field should not be
+// uploaded.
+TEST_F(FormStructureTest, OneFieldPasswordFormShouldNotBeUpload) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ /* enabled features */ {kAutofillEnforceMinRequiredFieldsForUpload},
+ /* disabled features */ {kAutofillEnforceMinRequiredFieldsForQuery});
+ FormData form;
+ FormFieldData field;
+ field.name = ASCIIToUTF16("Password");
+ field.form_control_type = "password";
+ form.fields.push_back(field);
+
+ EXPECT_FALSE(FormStructure(form).ShouldBeUploaded());
+}
+
} // namespace autofill
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 0040b5748c9..643e2d84724 100644
--- a/chromium/components/autofill/core/browser/local_card_migration_manager.cc
+++ b/chromium/components/autofill/core/browser/local_card_migration_manager.cc
@@ -16,11 +16,19 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_data_importer.h"
#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/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "services/identity/public/cpp/identity_manager.h"
namespace autofill {
+MigratableCreditCard::MigratableCreditCard(const CreditCard& credit_card)
+ : credit_card_(credit_card) {}
+
+MigratableCreditCard::~MigratableCreditCard() {}
+
LocalCardMigrationManager::LocalCardMigrationManager(
AutofillClient* client,
payments::PaymentsClient* payments_client,
@@ -29,40 +37,32 @@ LocalCardMigrationManager::LocalCardMigrationManager(
: client_(client),
payments_client_(payments_client),
app_locale_(app_locale),
- personal_data_manager_(personal_data_manager) {
- if (payments_client_)
- payments_client_->SetSaveDelegate(this);
-}
+ personal_data_manager_(personal_data_manager),
+ weak_ptr_factory_(this) {}
LocalCardMigrationManager::~LocalCardMigrationManager() {}
bool LocalCardMigrationManager::ShouldOfferLocalCardMigration(
int imported_credit_card_record_type) {
// Must be an existing card. New cards always get Upstream or local save.
- if (imported_credit_card_record_type !=
- FormDataImporter::ImportedCreditCardRecordType::LOCAL_CARD &&
- imported_credit_card_record_type !=
- FormDataImporter::ImportedCreditCardRecordType::SERVER_CARD) {
- return false;
+ switch (imported_credit_card_record_type) {
+ case FormDataImporter::ImportedCreditCardRecordType::LOCAL_CARD:
+ local_card_migration_origin_ =
+ AutofillMetrics::LocalCardMigrationOrigin::UseOfLocalCard;
+ break;
+ case FormDataImporter::ImportedCreditCardRecordType::SERVER_CARD:
+ local_card_migration_origin_ =
+ AutofillMetrics::LocalCardMigrationOrigin::UseOfServerCard;
+ break;
+ default:
+ return false;
}
if (!IsCreditCardMigrationEnabled())
return false;
- std::vector<CreditCard*> local_credit_cards =
- personal_data_manager_->GetLocalCreditCards();
-
- // Empty previous state.
- migratable_credit_cards_.clear();
-
- // Initialize the local credit card list and queue for showing and uploading.
- for (CreditCard* card : local_credit_cards) {
- // If the card is valid (has a valid card number, expiration date, and is
- // not expired) and is not a server card, add it to the list of migratable
- // cards.
- if (card->IsValid() && !IsServerCard(card))
- migratable_credit_cards_.push_back(*card);
- }
+ // Fetch all migratable credit cards and store in |migratable_credit_cards_|.
+ GetMigratableCreditCards();
// If the form was submitted with a local card, only offer migration instead
// of Upstream if there are other local cards to migrate as well. If the form
@@ -76,62 +76,167 @@ bool LocalCardMigrationManager::ShouldOfferLocalCardMigration(
!migratable_credit_cards_.empty());
}
-void LocalCardMigrationManager::AttemptToOfferLocalCardMigration() {
+void LocalCardMigrationManager::AttemptToOfferLocalCardMigration(
+ bool is_from_settings_page) {
// Abort the migration if |payments_client_| is nullptr.
if (!payments_client_)
return;
- payments_client_->SetSaveDelegate(this);
- upload_request_ = payments::PaymentsClient::UploadRequestDetails();
-
- // Payments server determines which version of the legal message to show based
- // on the existence of this experiment flag.
- if (IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled()) {
- upload_request_.active_experiments.push_back(
- kAutofillUpstreamUpdatePromptExplanation.name);
- }
+ migration_request_ = payments::PaymentsClient::MigrationRequestDetails();
// Don't send pan_first_six, as potentially migrating multiple local cards at
// once will negate its usefulness.
payments_client_->GetUploadDetails(
- upload_request_.profiles, GetDetectedValues(),
- /*pan_first_six=*/std::string(), upload_request_.active_experiments,
- app_locale_);
+ std::vector<AutofillProfile>(), GetDetectedValues(),
+ /*pan_first_six=*/std::string(),
+ /*active_experiments=*/std::vector<const char*>(), app_locale_,
+ base::BindOnce(&LocalCardMigrationManager::OnDidGetUploadDetails,
+ weak_ptr_factory_.GetWeakPtr(), is_from_settings_page),
+ payments::kMigrateCardsBillableServiceNumber);
+}
+
+// Callback function when user agrees to migration on the intermediate dialog.
+// Call ShowMainMigrationDialog() to pop up a larger, modal dialog showing the
+// local cards to be uploaded.
+void LocalCardMigrationManager::OnUserAcceptedIntermediateMigrationDialog() {
+ AutofillMetrics::LogLocalCardMigrationPromptMetric(
+ local_card_migration_origin_,
+ AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED);
+ ShowMainMigrationDialog();
+}
+
+// Send the migration request once risk data is available.
+void LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog() {
+ user_accepted_main_migration_dialog_ = true;
+ AutofillMetrics::LogLocalCardMigrationPromptMetric(
+ local_card_migration_origin_, AutofillMetrics::MAIN_DIALOG_ACCEPTED);
+ // Populating risk data and offering migration two-round pop-ups occur
+ // asynchronously. If |migration_risk_data_| has already been loaded, send the
+ // migrate local cards request. Otherwise, continue to wait and let
+ // OnDidGetUploadRiskData handle it.
+ if (!migration_request_.risk_data.empty())
+ SendMigrateLocalCardsRequest();
}
bool LocalCardMigrationManager::IsCreditCardMigrationEnabled() {
// Confirm that the user is signed in, syncing, and the proper experiment
// flags are enabled.
bool migration_experiment_enabled =
- IsAutofillCreditCardLocalCardMigrationExperimentEnabled();
+ features::GetLocalCardMigrationExperimentalFlag() !=
+ features::LocalCardMigrationExperimentalFlag::kMigrationDisabled;
bool credit_card_upload_enabled = ::autofill::IsCreditCardUploadEnabled(
client_->GetPrefs(), client_->GetSyncService(),
client_->GetIdentityManager()->GetPrimaryAccountInfo().email);
bool has_google_payments_account =
- (static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
- prefs::kAutofillBillingCustomerNumber)) != 0);
+ (payments::GetBillingCustomerId(personal_data_manager_,
+ payments_client_->GetPrefService()) != 0);
return migration_experiment_enabled && credit_card_upload_enabled &&
has_google_payments_account;
}
void LocalCardMigrationManager::OnDidGetUploadDetails(
+ bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
std::unique_ptr<base::DictionaryValue> legal_message) {
if (result == AutofillClient::SUCCESS) {
- upload_request_.context_token = context_token;
+ migration_request_.context_token = context_token;
legal_message_ = std::move(legal_message);
+ migration_request_.risk_data.clear();
// If we successfully received the legal docs, trigger the offer-to-migrate
- // dialog.
- // TODO(crbug.com/852904): Show intermediate migration prompt here! Relies
- // on CL/1117929 first.
+ // dialog. If triggered from settings page, we pop-up the main prompt
+ // directly. If not, we pop up the intermediate bubble.
+ if (is_from_settings_page) {
+ // Set the origin to SettingsPage.
+ local_card_migration_origin_ =
+ AutofillMetrics::LocalCardMigrationOrigin::SettingsPage;
+ // Pops up a larger, modal dialog showing the local cards to be uploaded.
+ ShowMainMigrationDialog();
+ } else {
+ client_->ShowLocalCardMigrationDialog(base::BindOnce(
+ &LocalCardMigrationManager::OnUserAcceptedIntermediateMigrationDialog,
+ weak_ptr_factory_.GetWeakPtr()));
+ AutofillMetrics::LogLocalCardMigrationPromptMetric(
+ local_card_migration_origin_,
+ AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN);
+ }
+ // TODO(crbug.com/876895): Clean up the LoadRiskData Bind/BindRepeating
+ // usages
+ client_->LoadRiskData(base::BindRepeating(
+ &LocalCardMigrationManager::OnDidGetMigrationRiskData,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
-// TODO(crbug.com/852904): Starts the upload of the next local card if one
-// exists.
-void LocalCardMigrationManager::OnDidUploadCard(
+void LocalCardMigrationManager::OnDidMigrateLocalCards(
AutofillClient::PaymentsRpcResult result,
- const std::string& server_id) {}
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result,
+ const std::string& display_text) {
+ if (!save_result)
+ return;
+
+ // Traverse the migratable credit cards to update each migrated card status.
+ for (MigratableCreditCard& card : migratable_credit_cards_) {
+ // Not every card exists in the |save_result| since some cards are unchecked
+ // by the user and not migrated.
+ auto it = save_result->find(card.credit_card().guid());
+ // If current card exists in the |save_result|, update its migration status.
+ if (it != save_result->end()) {
+ // Server-side response can return SUCCESS, TEMPORARY_FAILURE, or
+ // PERMANENT_FAILURE (see SaveResult enum). Branch here depending on which
+ // is received.
+ if (it->second == kMigrationResultPermanentFailure ||
+ it->second == kMigrationResultTemporaryFailure) {
+ card.set_migration_status(
+ autofill::MigratableCreditCard::FAILURE_ON_UPLOAD);
+ } else if (it->second == kMigrationResultSuccess) {
+ card.set_migration_status(
+ autofill::MigratableCreditCard::SUCCESS_ON_UPLOAD);
+ } else {
+ NOTREACHED();
+ }
+ }
+ }
+ // TODO(crbug.com/852904): Trigger the show result window.
+}
+
+void LocalCardMigrationManager::OnDidGetMigrationRiskData(
+ const std::string& risk_data) {
+ migration_request_.risk_data = risk_data;
+ // Populating risk data and offering migration two-round pop-ups occur
+ // asynchronously. If the main migration dialog has already been accepted,
+ // send the migrate local cards request. Otherwise, continue to wait for the
+ // user to accept the two round dialog.
+ if (user_accepted_main_migration_dialog_)
+ SendMigrateLocalCardsRequest();
+}
+
+// Send the migration request. Will call payments_client to create a new
+// PaymentsRequest. Also create a new callback function OnDidMigrateLocalCards.
+void LocalCardMigrationManager::SendMigrateLocalCardsRequest() {
+ migration_request_.app_locale = app_locale_;
+ migration_request_.billing_customer_number = payments::GetBillingCustomerId(
+ personal_data_manager_, payments_client_->GetPrefService());
+ payments_client_->MigrateCards(
+ migration_request_, migratable_credit_cards_,
+ base::BindOnce(&LocalCardMigrationManager::OnDidMigrateLocalCards,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+// Pops up a larger, modal dialog showing the local cards to be uploaded. Pass
+// the reference of vector<MigratableCreditCard> and the callback function is
+// OnUserAcceptedMainMigrationDialog(). Can be called when user agrees to
+// migration on the intermediate dialog or directly from settings page.
+void LocalCardMigrationManager::ShowMainMigrationDialog() {
+ user_accepted_main_migration_dialog_ = false;
+ AutofillMetrics::LogLocalCardMigrationPromptMetric(
+ 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_,
+ base::BindOnce(
+ &LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog,
+ weak_ptr_factory_.GetWeakPtr()));
+}
int LocalCardMigrationManager::GetDetectedValues() const {
int detected_values = 0;
@@ -139,32 +244,42 @@ int LocalCardMigrationManager::GetDetectedValues() const {
// If all cards to be migrated have a cardholder name, include it in the
// detected values.
bool all_cards_have_cardholder_name = true;
- for (CreditCard card : migratable_credit_cards_) {
+ for (MigratableCreditCard migratable_credit_card : migratable_credit_cards_) {
all_cards_have_cardholder_name &=
- !card.GetInfo(AutofillType(CREDIT_CARD_NAME_FULL), app_locale_).empty();
+ !migratable_credit_card.credit_card()
+ .GetInfo(AutofillType(CREDIT_CARD_NAME_FULL), app_locale_)
+ .empty();
}
if (all_cards_have_cardholder_name)
detected_values |= CreditCardSaveManager::DetectedValue::CARDHOLDER_NAME;
// Local card migration should ONLY be offered when the user already has a
// Google Payments account.
- DCHECK(static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
- prefs::kAutofillBillingCustomerNumber)) != 0);
+ DCHECK_NE(0, payments::GetBillingCustomerId(
+ personal_data_manager_, payments_client_->GetPrefService()));
detected_values |=
CreditCardSaveManager::DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT;
return detected_values;
}
-bool LocalCardMigrationManager::IsServerCard(CreditCard* local_card) const {
- std::vector<CreditCard*> server_credit_cards =
- personal_data_manager_->GetServerCreditCards();
- // Check whether the current card is already uploaded.
- for (const CreditCard* server_card : server_credit_cards) {
- if (local_card->HasSameNumberAs(*server_card))
- return true;
+void LocalCardMigrationManager::GetMigratableCreditCards() {
+ std::vector<CreditCard*> local_credit_cards =
+ personal_data_manager_->GetLocalCreditCards();
+
+ // Empty previous state.
+ migratable_credit_cards_.clear();
+
+ // Initialize the local credit card list and queue for showing and uploading.
+ for (CreditCard* credit_card : local_credit_cards) {
+ // If the card is valid (has a valid card number, expiration date, and is
+ // not expired) and is not a server card, add it to the list of migratable
+ // cards.
+ if (credit_card->IsValid() &&
+ !personal_data_manager_->IsServerCard(credit_card)) {
+ migratable_credit_cards_.push_back(MigratableCreditCard(*credit_card));
+ }
}
- return false;
}
} // namespace autofill
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 62802c86c47..7304f83af9d 100644
--- a/chromium/components/autofill/core/browser/local_card_migration_manager.h
+++ b/chromium/components/autofill/core/browser/local_card_migration_manager.h
@@ -11,6 +11,7 @@
#include "base/strings/string16.h"
#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/payments/payments_client.h"
namespace autofill {
@@ -18,10 +19,61 @@ namespace autofill {
class CreditCard;
class PersonalDataManager;
+// Server-side response can return SUCCESS, TEMPORARY_FAILURE, or
+// PERMANENT_FAILURE (see SaveResult enum). Use these to extract migration
+// result.
+const char kMigrationResultPermanentFailure[] = "PERMANENT_FAILURE";
+const char kMigrationResultTemporaryFailure[] = "TEMPORARY_FAILURE";
+const char kMigrationResultSuccess[] = "SUCCESS";
+
+// MigratableCreditCard class is used as a data structure to work as an
+// intermediary between the UI side and the migration manager. Besides the basic
+// credit card information, it also includes a boolean that represents whether
+// the card was chosen for upload. We use each card's guid to distinguish each
+// credit card for upload request/response.
+// TODO(crbug.com/852904): Create one Enum to represent migration status such as
+// whether the card is successfully uploaded or failure on uploading.
+class MigratableCreditCard {
+ public:
+ // Possible states for the migratable local card.
+ enum MigrationStatus {
+ // Set if the migratable card have not been uploaded.
+ UNKNOWN,
+ // Set if the migratable card was successfully uploaded to the server.
+ SUCCESS_ON_UPLOAD,
+ // Set if the migratable card encountered a failure during upload.
+ FAILURE_ON_UPLOAD,
+ };
+
+ MigratableCreditCard(const CreditCard& credit_card);
+ ~MigratableCreditCard();
+
+ CreditCard credit_card() const { return credit_card_; }
+
+ bool is_chosen() const { return is_chosen_; }
+ void ToggleChosen() { is_chosen_ = !is_chosen(); }
+
+ MigrationStatus migration_status() const { return migration_status_; }
+ void set_migration_status(MigrationStatus migration_status) {
+ migration_status_ = migration_status;
+ }
+
+ private:
+ // The main card information of the current migratable card.
+ CreditCard credit_card_;
+
+ // Whether the user has decided to migrate the this card; shown as a checkbox
+ // in the UI.
+ bool is_chosen_ = true;
+
+ // Migration status for this card.
+ MigrationStatus migration_status_ = MigrationStatus::UNKNOWN;
+};
+
// Manages logic for determining whether migration of locally saved credit cards
// to Google Payments is available as well as multiple local card uploading.
// Owned by FormDataImporter.
-class LocalCardMigrationManager : public payments::PaymentsClientSaveDelegate {
+class LocalCardMigrationManager {
public:
// The parameters should outlive the LocalCardMigrationManager.
LocalCardMigrationManager(AutofillClient* client,
@@ -34,9 +86,22 @@ class LocalCardMigrationManager : public payments::PaymentsClientSaveDelegate {
// migration are satisfied. Initializes the local card list for upload.
bool ShouldOfferLocalCardMigration(int imported_credit_card_record_type);
- // Called from FormDataImporter when all migration requirements are met.
- // Fetches legal documents and triggers the OnDidGetUploadDetails callback.
- void AttemptToOfferLocalCardMigration();
+ // Called from FormDataImporter or settings page when all migration
+ // requirements are met. Fetches legal documents and triggers the
+ // OnDidGetUploadDetails callback. |is_from_settings_page| to denote the user
+ // triggers the migration from settings page. It will trigger the main prompt
+ // directly if the get upload details call returns success.
+ void AttemptToOfferLocalCardMigration(bool is_from_settings_page);
+
+ // Callback function when user agrees to migration on the intermediate dialog.
+ // Pops up a larger, modal dialog showing the local cards to be uploaded.
+ // Exposed for testing.
+ virtual void OnUserAcceptedIntermediateMigrationDialog();
+
+ // Callback function when user confirms migration on the main migration
+ // dialog. Sets |user_accepted_main_migration_dialog_| and sends the migration
+ // request once risk data is available. Exposed for testing.
+ virtual void OnUserAcceptedMainMigrationDialog();
// Check that the user is signed in, syncing, and the proper experiment
// flags are enabled. Override in the test class.
@@ -46,24 +111,28 @@ class LocalCardMigrationManager : public payments::PaymentsClientSaveDelegate {
// name if it exists on all cards, and existence of Payments customer).
int GetDetectedValues() const;
+ // Fetch all migratable credit cards and store in |migratable_credit_cards_|.
+ void GetMigratableCreditCards();
+
protected:
- // payments::PaymentsClientSaveDelegate:
// Callback after successfully getting the legal documents. On success,
// displays the offer-to-migrate dialog, which the user can accept or not.
- void OnDidGetUploadDetails(
+ // When |is_from_settings_page| is true, it will trigger the main prompt
+ // directly. If not, trigger the intermediate prompt. Exposed for testing.
+ virtual void OnDidGetUploadDetails(
+ bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) override;
-
- // payments::PaymentsClientSaveDelegate:
- // Callback after a local card was uploaded. Starts the upload of the next
- // local card if one exists.
- // Exposed for testing.
- void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
- const std::string& server_id) override;
+ std::unique_ptr<base::DictionaryValue> legal_message);
- // Check whether a local card is already a server card.
- bool IsServerCard(CreditCard* local_card) const;
+ // Callback after successfully getting the migration save results. Map
+ // migration save result to each card depending on the |save_result|. Will
+ // trigger a window showing the migration result together with display text to
+ // the user.
+ void OnDidMigrateLocalCards(
+ AutofillClient::PaymentsRpcResult result,
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result,
+ const std::string& display_text);
AutofillClient* const client_;
@@ -72,6 +141,24 @@ class LocalCardMigrationManager : public payments::PaymentsClientSaveDelegate {
payments::PaymentsClient* payments_client_;
private:
+ FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest,
+ MigrateCreditCard_MigrationPermanentFailure);
+ FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest,
+ MigrateCreditCard_MigrationTemporaryFailure);
+ FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest,
+ MigrateCreditCard_MigrationSuccess);
+
+ // Pops up a larger, modal dialog showing the local cards to be uploaded.
+ void ShowMainMigrationDialog();
+
+ // Callback function when migration risk data is ready. Saves risk data in
+ // |migration_risk_data_| and calls SendMigrateLocalCardsRequest if the user
+ // has accepted the main migration dialog.
+ void OnDidGetMigrationRiskData(const std::string& risk_data);
+
+ // Finalizes the migration request and calls PaymentsClient.
+ void SendMigrateLocalCardsRequest();
+
std::unique_ptr<base::DictionaryValue> legal_message_;
std::string app_locale_;
@@ -82,11 +169,20 @@ class LocalCardMigrationManager : public payments::PaymentsClientSaveDelegate {
// May be NULL. NULL indicates OTR.
PersonalDataManager* personal_data_manager_;
- // Collected information about a pending upload request.
- payments::PaymentsClient::UploadRequestDetails upload_request_;
+ // Collected information about a pending migration request.
+ payments::PaymentsClient::MigrationRequestDetails migration_request_;
// The local credit cards to be uploaded.
- std::vector<CreditCard> migratable_credit_cards_;
+ std::vector<MigratableCreditCard> migratable_credit_cards_;
+
+ // |true| if the user has accepted migrating their local cards to Google Pay
+ // on the main dialog.
+ bool user_accepted_main_migration_dialog_ = false;
+
+ // Record the triggering source of the local card migration.
+ AutofillMetrics::LocalCardMigrationOrigin local_card_migration_origin_;
+
+ base::WeakPtrFactory<LocalCardMigrationManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationManager);
};
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 cb6124be68f..7ad864d1053 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
@@ -22,7 +22,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -40,6 +39,8 @@
#include "components/autofill/core/browser/validation.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/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
@@ -68,12 +69,11 @@ class LocalCardMigrationManagerTest : public testing::Test {
autofill_driver_->SetURLRequestContext(request_context_.get());
payments_client_ = new payments::TestPaymentsClient(
autofill_driver_->GetURLLoaderFactory(), autofill_client_.GetPrefs(),
- autofill_client_.GetIdentityManager(),
- /*unmask_delegate=*/nullptr,
- /*save_delegate=*/nullptr);
+ autofill_client_.GetIdentityManager(), &personal_data_);
credit_card_save_manager_ =
new TestCreditCardSaveManager(autofill_driver_.get(), &autofill_client_,
payments_client_, &personal_data_);
+ credit_card_save_manager_->SetCreditCardUploadEnabled(true);
local_card_migration_manager_ = new TestLocalCardMigrationManager(
autofill_driver_.get(), &autofill_client_, payments_client_,
&personal_data_);
@@ -100,12 +100,12 @@ class LocalCardMigrationManagerTest : public testing::Test {
void EnableAutofillCreditCardLocalCardMigrationExperiment() {
scoped_feature_list_.InitAndEnableFeature(
- kAutofillCreditCardLocalCardMigration);
+ features::kAutofillCreditCardLocalCardMigration);
}
void DisableAutofillCreditCardLocalCardMigrationExperiment() {
scoped_feature_list_.InitAndDisableFeature(
- kAutofillCreditCardLocalCardMigration);
+ features::kAutofillCreditCardLocalCardMigration);
}
void FormsSeen(const std::vector<FormData>& forms) {
@@ -145,6 +145,15 @@ class LocalCardMigrationManagerTest : public testing::Test {
personal_data.AddCreditCard(local_card);
}
+ // Set the parsed response |result| for the provided |guid|.
+ void SetUpMigrationResponseForGuid(const std::string& guid,
+ const std::string& result) {
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result =
+ std::make_unique<std::unordered_map<std::string, std::string>>();
+ save_result->insert(std::make_pair(guid, result));
+ payments_client_->SetSaveResultForCardsMigration(std::move(save_result));
+ }
+
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
@@ -166,9 +175,7 @@ class LocalCardMigrationManagerTest : public testing::Test {
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_UseLocalCardWithOneLocal) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -183,11 +190,17 @@ TEST_F(LocalCardMigrationManagerTest,
test::CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
+ base::HistogramTester histogram_tester;
// Edit the data, and submit.
EditCreditCardFrom(credit_card_form, "Flo Master", "4111111111111111", "11",
test::NextYear().c_str(), "123");
FormSubmitted(credit_card_form);
EXPECT_FALSE(local_card_migration_manager_->LocalCardMigrationWasTriggered());
+
+ // Verify that metrics are correctly logged to the UseOfLocalCard
+ // sub-histogram.
+ histogram_tester.ExpectTotalCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfLocalCard", 0);
}
// Having any number of local cards on file and using a new card will not
@@ -195,9 +208,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_UseNewCardWithAnyLocal) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -227,9 +238,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_UseLocalCardWithMoreLocal) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -247,11 +256,27 @@ TEST_F(LocalCardMigrationManagerTest,
test::CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
+ base::HistogramTester histogram_tester;
// 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());
+
+ // Verify that metrics are correctly logged to the UseOfLocalCard
+ // sub-histogram.
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfLocalCard",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfLocalCard",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfLocalCard",
+ AutofillMetrics::MAIN_DIALOG_SHOWN, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfLocalCard",
+ AutofillMetrics::MAIN_DIALOG_ACCEPTED, 1);
}
// Using a local card will not trigger migration even if there are other local
@@ -259,9 +284,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_UseLocalCardWithInvalidLocal) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -294,9 +317,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_UseServerCardWithOneValidLocal) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -317,11 +338,27 @@ TEST_F(LocalCardMigrationManagerTest,
test::CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
+ base::HistogramTester histogram_tester;
// 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());
+
+ // Verify that metrics are correctly logged to the UseOfServerCard
+ // sub-histogram.
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfServerCard",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfServerCard",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfServerCard",
+ AutofillMetrics::MAIN_DIALOG_SHOWN, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfServerCard",
+ AutofillMetrics::MAIN_DIALOG_ACCEPTED, 1);
}
// Using a server card will not trigger migration even if there are other local
@@ -329,9 +366,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_UseServerCardWithNoneValidLocal) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -355,11 +390,17 @@ TEST_F(LocalCardMigrationManagerTest,
test::CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
+ base::HistogramTester histogram_tester;
// Edit the data, and submit.
EditCreditCardFrom(credit_card_form, "Flo Master", "4111111111111111", "11",
test::NextYear().c_str(), "123");
FormSubmitted(credit_card_form);
EXPECT_FALSE(local_card_migration_manager_->LocalCardMigrationWasTriggered());
+
+ // Verify that metrics are correctly logged to the UseOfServerCard
+ // sub-histogram.
+ histogram_tester.ExpectTotalCount(
+ "Autofill.LocalCardMigrationOrigin.UseOfServerCard", 0);
}
// Use one local card with more valid local cards available but experiment flag
@@ -367,9 +408,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_FeatureNotEnabled) {
// Turn off the experiment flag.
DisableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -398,9 +437,7 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_FeatureNotEnabled) {
// number is blank, will not trigger migration.
TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_NoPaymentsAccount) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCrediCard(personal_data_, "Flo Master", "4111111111111111", "11",
@@ -426,9 +463,7 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_NoPaymentsAccount) {
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_LocalCardMatchMaskedServerCard) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -465,9 +500,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
MigrateCreditCard_LocalCardMatchFullServerCard) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -499,9 +532,7 @@ TEST_F(LocalCardMigrationManagerTest,
// GetDetectedValues() should includes cardholder name if all cards have it.
TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_AllWithCardHolderName) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -533,9 +564,7 @@ TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_AllWithCardHolderName) {
TEST_F(LocalCardMigrationManagerTest,
GetDetectedValues_OneCardWithoutCardHolderName) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -566,9 +595,7 @@ TEST_F(LocalCardMigrationManagerTest,
TEST_F(LocalCardMigrationManagerTest,
GetDetectedValues_IncludeGooglePaymentsAccount) {
EnableAutofillCreditCardLocalCardMigrationExperiment();
- personal_data_.ClearCreditCards();
- personal_data_.ClearProfiles();
- credit_card_save_manager_->SetCreditCardUploadEnabled(true);
+
// Set the billing_customer_number Priority Preference to designate
// existence of a Payments account.
autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber,
@@ -596,4 +623,182 @@ TEST_F(LocalCardMigrationManagerTest,
CreditCardSaveManager::DetectedValue::HAS_GOOGLE_PAYMENTS_ACCOUNT);
}
+// Verify that when triggering from settings page, intermediate prompt will not
+// be triggered.
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_TriggerFromSettingsPage) {
+ 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.
+ AddLocalCrediCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1");
+
+ 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());
+
+ // Verify that metrics are correctly logged to the SettingsPage sub-histogram.
+ // Triggering from settings page won't show intermediate bubble.
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.SettingsPage",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_SHOWN, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.SettingsPage",
+ AutofillMetrics::INTERMEDIATE_BUBBLE_ACCEPTED, 0);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.SettingsPage",
+ AutofillMetrics::MAIN_DIALOG_SHOWN, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.LocalCardMigrationOrigin.SettingsPage",
+ AutofillMetrics::MAIN_DIALOG_ACCEPTED, 1);
+}
+
+// Verify that when triggering from submitted form, intermediate prompt and main
+// prompt are both triggered.
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_TriggerFromSubmittedForm) {
+ 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.
+ AddLocalCrediCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1");
+ // Add another local credit card, so it will trigger migration.
+ AddLocalCrediCard(personal_data_, "Flo Master", "5555555555554444", "11",
+ test::NextYear().c_str(), "1");
+
+ // 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_->IntermediatePromptWasShown());
+ EXPECT_TRUE(local_card_migration_manager_->MainPromptWasShown());
+}
+
+// Verify that given the parsed response from the payments client, the migration
+// status is correctly set.
+TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationSuccess) {
+ 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 for migration.
+ AddLocalCrediCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1");
+
+ // Get the migratable credit cards.
+ local_card_migration_manager_->GetMigratableCreditCards();
+
+ // Set the parsed response to success.
+ SetUpMigrationResponseForGuid(
+ local_card_migration_manager_->migratable_credit_cards_[0]
+ .credit_card()
+ .guid(),
+ autofill::kMigrationResultSuccess);
+
+ EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
+ .migration_status(),
+ autofill::MigratableCreditCard::UNKNOWN);
+
+ local_card_migration_manager_->AttemptToOfferLocalCardMigration(true);
+
+ EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
+ .migration_status(),
+ autofill::MigratableCreditCard::SUCCESS_ON_UPLOAD);
+}
+
+// Verify that given the parsed response from the payments client, the migration
+// status is correctly set.
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_MigrationTemporaryFailure) {
+ 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.
+ AddLocalCrediCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1");
+
+ // Get the migratable credit cards.
+ local_card_migration_manager_->GetMigratableCreditCards();
+
+ // Set the parsed response to temporary failure.
+ SetUpMigrationResponseForGuid(
+ local_card_migration_manager_->migratable_credit_cards_[0]
+ .credit_card()
+ .guid(),
+ autofill::kMigrationResultTemporaryFailure);
+
+ EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
+ .migration_status(),
+ autofill::MigratableCreditCard::UNKNOWN);
+
+ // Start the migration.
+ local_card_migration_manager_->AttemptToOfferLocalCardMigration(true);
+
+ EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
+ .migration_status(),
+ autofill::MigratableCreditCard::FAILURE_ON_UPLOAD);
+}
+
+// Verify that given the parsed response from the payments client, the migration
+// status is correctly set.
+TEST_F(LocalCardMigrationManagerTest,
+ MigrateCreditCard_MigrationPermanentFailure) {
+ 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.
+ AddLocalCrediCard(personal_data_, "Flo Master", "4111111111111111", "11",
+ test::NextYear().c_str(), "1");
+
+ // Get the migratable credit cards.
+ local_card_migration_manager_->GetMigratableCreditCards();
+
+ // Set the parsed response to permanent failure.
+ SetUpMigrationResponseForGuid(
+ local_card_migration_manager_->migratable_credit_cards_[0]
+ .credit_card()
+ .guid(),
+ autofill::kMigrationResultPermanentFailure);
+
+ EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
+ .migration_status(),
+ autofill::MigratableCreditCard::UNKNOWN);
+
+ // Start the migration.
+ local_card_migration_manager_->AttemptToOfferLocalCardMigration(true);
+
+ EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
+ .migration_status(),
+ autofill::MigratableCreditCard::FAILURE_ON_UPLOAD);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/password_generator_proto_fuzzer.cc b/chromium/components/autofill/core/browser/password_generator_proto_fuzzer.cc
new file mode 100644
index 00000000000..2967bc68616
--- /dev/null
+++ b/chromium/components/autofill/core/browser/password_generator_proto_fuzzer.cc
@@ -0,0 +1,15 @@
+// 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/password_generator.h"
+#include "components/autofill/core/browser/proto/password_requirements.pb.h"
+#include "testing/libfuzzer/proto/lpm_interface.h"
+
+namespace autofill {
+
+DEFINE_PROTO_FUZZER(const PasswordRequirementsSpec& spec) {
+ GeneratePassword(spec);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/password_requirements_spec_printer.cc b/chromium/components/autofill/core/browser/password_requirements_spec_printer.cc
index 7a4d72eeb3b..dd7049d34da 100644
--- a/chromium/components/autofill/core/browser/password_requirements_spec_printer.cc
+++ b/chromium/components/autofill/core/browser/password_requirements_spec_printer.cc
@@ -4,9 +4,11 @@
#include "components/autofill/core/browser/password_requirements_spec_printer.h"
+namespace autofill {
+
std::ostream& operator<<(
std::ostream& out,
- const autofill::PasswordRequirementsSpec::CharacterClass& character_class) {
+ const PasswordRequirementsSpec::CharacterClass& character_class) {
out << "{";
if (character_class.has_character_set())
out << "character_set: \"" << character_class.character_set() << "\", ";
@@ -19,7 +21,7 @@ std::ostream& operator<<(
}
std::ostream& operator<<(std::ostream& out,
- const autofill::PasswordRequirementsSpec& spec) {
+ const PasswordRequirementsSpec& spec) {
out << "{";
if (spec.has_priority())
out << "priority: " << spec.priority() << ", ";
@@ -42,3 +44,5 @@ std::ostream& operator<<(std::ostream& out,
out << "}";
return out;
}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/password_requirements_spec_printer.h b/chromium/components/autofill/core/browser/password_requirements_spec_printer.h
index 55db287068c..81169340bce 100644
--- a/chromium/components/autofill/core/browser/password_requirements_spec_printer.h
+++ b/chromium/components/autofill/core/browser/password_requirements_spec_printer.h
@@ -9,11 +9,15 @@
#include "components/autofill/core/browser/proto/password_requirements.pb.h"
+namespace autofill {
+
std::ostream& operator<<(
std::ostream& out,
- const autofill::PasswordRequirementsSpec::CharacterClass& character_class);
+ const PasswordRequirementsSpec::CharacterClass& character_class);
std::ostream& operator<<(std::ostream& out,
- const autofill::PasswordRequirementsSpec& spec);
+ const PasswordRequirementsSpec& spec);
+
+} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PASSWORD_REQUIREMENTS_SPEC_PRINTER_H_
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.cc b/chromium/components/autofill/core/browser/payments/full_card_request.cc
index 9fab4b42888..a787034db51 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.cc
@@ -8,9 +8,9 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_util.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_clock.h"
@@ -68,9 +68,8 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
card.ShouldUpdateExpiration(AutofillClock::Now()));
if (should_unmask_card_) {
payments_client_->Prepare();
- request_->billing_customer_number =
- static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
- prefs::kAutofillBillingCustomerNumber));
+ request_->billing_customer_number = GetBillingCustomerId(
+ personal_data_manager_, payments_client_->GetPrefService());
}
ui_delegate_->ShowUnmaskPrompt(request_->card, reason,
@@ -131,7 +130,9 @@ void FullCardRequest::OnDidGetUnmaskRiskData(const std::string& risk_data) {
void FullCardRequest::SendUnmaskCardRequest() {
real_pan_request_timestamp_ = AutofillClock::Now();
- payments_client_->UnmaskCard(*request_);
+ payments_client_->UnmaskCard(*request_,
+ base::BindOnce(&FullCardRequest::OnDidGetRealPan,
+ weak_ptr_factory_.GetWeakPtr()));
}
void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
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 03d1b3eda65..a71d0211bac 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
@@ -17,7 +17,8 @@
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/testing_pref_service.h"
@@ -57,17 +58,18 @@ class MockUIDelegate : public FullCardRequest::UIDelegate,
};
// The personal data manager.
-class MockPersonalDataManager : public PersonalDataManager {
+class MockPersonalDataManager : public TestPersonalDataManager {
public:
- MockPersonalDataManager() : PersonalDataManager("en-US") {}
+ MockPersonalDataManager() {}
~MockPersonalDataManager() override {}
+ MOCK_CONST_METHOD0(IsSyncFeatureEnabled, bool());
MOCK_METHOD1(UpdateCreditCard, void(const CreditCard& credit_card));
MOCK_METHOD1(UpdateServerCreditCard, void(const CreditCard& credit_card));
};
+// TODO(crbug.com/881835): Simplify this test setup.
// The test fixture for full card request.
-class FullCardRequestTest : public testing::Test,
- public PaymentsClientUnmaskDelegate {
+class FullCardRequestTest : public testing::Test {
public:
FullCardRequestTest()
: request_context_(new net::TestURLRequestContextGetter(
@@ -82,9 +84,11 @@ class FullCardRequestTest : public testing::Test,
autofill_client_.SetPrefs(std::move(pref_service));
payments_client_ = std::make_unique<PaymentsClient>(
test_shared_loader_factory_, autofill_client_.GetPrefs(),
- autofill_client_.GetIdentityManager(), this, nullptr);
+ autofill_client_.GetIdentityManager(), &personal_data_);
request_ = std::make_unique<FullCardRequest>(
&autofill_client_, payments_client_.get(), &personal_data_);
+ personal_data_.SetAccountInfoForPayments(
+ autofill_client_.GetIdentityManager()->GetPrimaryAccountInfo());
// Silence the warning from PaymentsClient about matching sync and Payments
// server types.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
@@ -105,9 +109,8 @@ class FullCardRequestTest : public testing::Test,
MockUIDelegate* ui_delegate() { return &ui_delegate_; }
- // PaymentsClientUnmaskDelegate:
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) override {
+ const std::string& real_pan) {
request_->OnDidGetRealPan(result, real_pan);
}
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index 6785c51868f..39eb28a9131 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -17,10 +17,12 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/account_info_getter.h"
#include "components/autofill/core/browser/autofill_data_model.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/local_card_migration_manager.h"
#include "components/autofill/core/browser/payments/payments_request.h"
#include "components/autofill/core/browser/payments/payments_service_url.h"
#include "components/autofill/core/common/autofill_features.h"
@@ -60,13 +62,16 @@ const char kUploadCardRequestFormatWithoutCvc[] =
"requestContentType=application/json; charset=utf-8&request=%s"
"&s7e_1_pan=%s";
+const char kMigrateCardsRequestPath[] =
+ "payments/apis-secure/chromepaymentsservice/migratecards"
+ "?s7e_suffix=chromewallet";
+const char kMigrateCardsRequestFormat[] =
+ "requestContentType=application/json; charset=utf-8&request=%s";
+
const char kTokenFetchId[] = "wallet_client";
const char kPaymentsOAuth2Scope[] =
"https://www.googleapis.com/auth/wallet.chrome";
-const int kUnmaskCardBillableServiceNumber = 70154;
-const int kUploadCardBillableServiceNumber = 70073;
-
GURL GetRequestUrl(const std::string& path) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch("sync-url")) {
if (IsPaymentsProductionEnabled()) {
@@ -179,6 +184,34 @@ std::unique_ptr<base::DictionaryValue> BuildAddressDictionary(
return address;
}
+// Returns a dictionary of the credit card with the structure expected by
+// Payments RPCs, containing expiration month, expiration year and cardholder
+// 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());
+
+ const base::string16 exp_month =
+ credit_card.GetInfo(AutofillType(CREDIT_CARD_EXP_MONTH), app_locale);
+ const base::string16 exp_year = credit_card.GetInfo(
+ AutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), app_locale);
+ int value = 0;
+ if (base::StringToInt(exp_month, &value))
+ card->SetInteger("expiration_month", value);
+ if (base::StringToInt(exp_year, &value))
+ card->SetInteger("expiration_year", value);
+ SetStringIfNotEmpty(credit_card, CREDIT_CARD_NAME_FULL, app_locale,
+ "cardholder_name", card.get());
+
+ card->SetString("encrypted_pan", "__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,
@@ -198,8 +231,12 @@ void SetActiveExperiments(const std::vector<const char*>& active_experiments,
class UnmaskCardRequest : public PaymentsRequest {
public:
UnmaskCardRequest(const PaymentsClient::UnmaskRequestDetails& request_details,
- PaymentsClientUnmaskDelegate* delegate)
- : request_details_(request_details), delegate_(delegate) {
+ const bool full_sync_enabled,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback)
+ : request_details_(request_details),
+ full_sync_enabled_(full_sync_enabled),
+ callback_(std::move(callback)) {
DCHECK(
CreditCard::MASKED_SERVER_CARD == request_details.card.record_type() ||
CreditCard::FULL_SERVER_CARD == request_details.card.record_type());
@@ -227,6 +264,13 @@ class UnmaskCardRequest : public PaymentsRequest {
}
request_dict.Set("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));
+ }
+
int value = 0;
if (base::StringToInt(request_details_.user_response.exp_month, &value))
request_dict.SetInteger("expiration_month", value);
@@ -252,29 +296,39 @@ class UnmaskCardRequest : public PaymentsRequest {
bool IsResponseComplete() override { return !real_pan_.empty(); }
void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
- delegate_->OnDidGetRealPan(result, real_pan_);
+ std::move(callback_).Run(result, real_pan_);
}
private:
PaymentsClient::UnmaskRequestDetails request_details_;
- PaymentsClientUnmaskDelegate* delegate_;
+ const bool full_sync_enabled_;
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)>
+ callback_;
std::string real_pan_;
};
class GetUploadDetailsRequest : public PaymentsRequest {
public:
- GetUploadDetailsRequest(const std::vector<AutofillProfile>& addresses,
- const int detected_values,
- const std::string& pan_first_six,
- const std::vector<const char*>& active_experiments,
- const std::string& app_locale,
- PaymentsClientSaveDelegate* delegate)
+ GetUploadDetailsRequest(
+ const std::vector<AutofillProfile>& addresses,
+ const int detected_values,
+ const std::string& pan_first_six,
+ const std::vector<const char*>& active_experiments,
+ const bool full_sync_enabled,
+ const std::string& app_locale,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const base::string16&,
+ std::unique_ptr<base::DictionaryValue>)> callback,
+ const int billable_service_number)
: addresses_(addresses),
detected_values_(detected_values),
pan_first_six_(pan_first_six),
active_experiments_(active_experiments),
+ full_sync_enabled_(full_sync_enabled),
app_locale_(app_locale),
- delegate_(delegate) {}
+ callback_(std::move(callback)),
+ billable_service_number_(billable_service_number) {}
~GetUploadDetailsRequest() override {}
std::string GetRequestUrlPath() override {
@@ -287,8 +341,16 @@ class GetUploadDetailsRequest : public PaymentsRequest {
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));
+ 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));
+ }
+
std::unique_ptr<base::ListValue> addresses(new base::ListValue());
for (const AutofillProfile& profile : addresses_) {
// These addresses are used by Payments to (1) accurately determine the
@@ -307,7 +369,7 @@ class GetUploadDetailsRequest : public PaymentsRequest {
// Payments will decide if the provided data is enough to offer upload save.
request_dict.SetInteger("detected_values", detected_values_);
- if (IsAutofillUpstreamSendPanFirstSixExperimentEnabled() &&
+ if (features::IsAutofillUpstreamSendPanFirstSixExperimentEnabled() &&
!pan_first_six_.empty())
request_dict.SetString("pan_first6", pan_first_six_);
@@ -331,8 +393,7 @@ class GetUploadDetailsRequest : public PaymentsRequest {
}
void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
- delegate_->OnDidGetUploadDetails(result, context_token_,
- std::move(legal_message_));
+ std::move(callback_).Run(result, context_token_, std::move(legal_message_));
}
private:
@@ -340,17 +401,26 @@ class GetUploadDetailsRequest : public PaymentsRequest {
const int detected_values_;
const std::string pan_first_six_;
const std::vector<const char*> active_experiments_;
+ const bool full_sync_enabled_;
std::string app_locale_;
- PaymentsClientSaveDelegate* delegate_;
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const base::string16&,
+ std::unique_ptr<base::DictionaryValue>)>
+ callback_;
base::string16 context_token_;
std::unique_ptr<base::DictionaryValue> legal_message_;
+ const int billable_service_number_;
};
class UploadCardRequest : public PaymentsRequest {
public:
UploadCardRequest(const PaymentsClient::UploadRequestDetails& request_details,
- PaymentsClientSaveDelegate* delegate)
- : request_details_(request_details), delegate_(delegate) {}
+ const bool full_sync_enabled,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback)
+ : request_details_(request_details),
+ full_sync_enabled_(full_sync_enabled),
+ callback_(std::move(callback)) {}
~UploadCardRequest() override {}
std::string GetRequestUrlPath() override { return kUploadCardRequestPath; }
@@ -378,6 +448,13 @@ class UploadCardRequest : public PaymentsRequest {
}
request_dict.Set("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));
+ }
+
SetStringIfNotEmpty(request_details_.card, CREDIT_CARD_NAME_FULL,
app_locale, "cardholder_name", &request_dict);
@@ -431,15 +508,143 @@ class UploadCardRequest : public PaymentsRequest {
bool IsResponseComplete() override { return true; }
void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
- delegate_->OnDidUploadCard(result, server_id_);
+ std::move(callback_).Run(result, server_id_);
}
private:
const PaymentsClient::UploadRequestDetails request_details_;
- PaymentsClientSaveDelegate* delegate_;
+ const bool full_sync_enabled_;
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)>
+ callback_;
std::string server_id_;
};
+class MigrateCardsRequest : public PaymentsRequest {
+ public:
+ MigrateCardsRequest(
+ const PaymentsClient::MigrationRequestDetails& request_details,
+ const std::vector<MigratableCreditCard>& migratable_credit_cards,
+ const bool full_sync_enabled,
+ MigrateCardsCallback callback)
+ : request_details_(request_details),
+ migratable_credit_cards_(migratable_credit_cards),
+ full_sync_enabled_(full_sync_enabled),
+ callback_(std::move(callback)) {}
+ ~MigrateCardsRequest() override {}
+
+ std::string GetRequestUrlPath() override { return kMigrateCardsRequestPath; }
+
+ std::string GetRequestContentType() override {
+ return "application/x-www-form-urlencoded";
+ }
+
+ // TODO(crbug.com/877281):Refactor DictionaryValue to base::Value
+ std::string GetRequestContent() override {
+ base::DictionaryValue request_dict;
+
+ 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);
+ if (request_details_.billing_customer_number != 0) {
+ context->SetKey("customer_context",
+ BuildCustomerContextDictionary(
+ request_details_.billing_customer_number));
+ }
+ request_dict.Set("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));
+ }
+
+ request_dict.SetString("context_token", request_details_.context_token);
+
+ std::string all_pans_data = std::string();
+ std::unique_ptr<base::ListValue> migrate_cards(new base::ListValue());
+ for (size_t index = 0; index < migratable_credit_cards_.size(); ++index) {
+ if (migratable_credit_cards_[index].is_chosen()) {
+ std::string pan_field_name = GetPanFieldName(index);
+ // Generate credit card dictionary.
+ migrate_cards->Append(BuildCreditCardDictionary(
+ migratable_credit_cards_[index].credit_card(), app_locale,
+ pan_field_name));
+ // Append pan data to the |all_pans_data|.
+ all_pans_data +=
+ GetAppendPan(migratable_credit_cards_[index].credit_card(),
+ app_locale, pan_field_name);
+ }
+ }
+ request_dict.Set("local_card", std::move(migrate_cards));
+
+ std::string json_request;
+ base::JSONWriter::Write(request_dict, &json_request);
+ std::string request_content = base::StringPrintf(
+ kMigrateCardsRequestFormat,
+ net::EscapeUrlEncodedData(json_request, true).c_str());
+ request_content += all_pans_data;
+ 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))
+ 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)) {
+ std::string unique_id;
+ single_card_save_result->GetString("unique_id", &unique_id);
+ std::string save_result;
+ single_card_save_result->GetString("status", &save_result);
+ save_result_->insert(std::make_pair(unique_id, save_result));
+ }
+ }
+ response->GetString("value_prop_display_text", &display_text_);
+ }
+
+ bool IsResponseComplete() override {
+ return !display_text_.empty() && save_result_;
+ }
+
+ void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override {
+ std::move(callback_).Run(result, std::move(save_result_), display_text_);
+ }
+
+ private:
+ // Return the pan field name for the encrypted pan based on the |index|.
+ std::string GetPanFieldName(const size_t& index) {
+ return "s7e_1_pan" + std::to_string(index);
+ }
+
+ // Return the formatted pan to append to the end of the request.
+ std::string GetAppendPan(const CreditCard& credit_card,
+ const std::string& app_locale,
+ const std::string& pan_field_name) {
+ const base::string16 pan =
+ credit_card.GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale);
+ std::string pan_str =
+ net::EscapeUrlEncodedData(base::UTF16ToASCII(pan), true).c_str();
+ std::string append_pan = "&" + pan_field_name + "=" + pan_str;
+ return append_pan;
+ }
+
+ const PaymentsClient::MigrationRequestDetails request_details_;
+ const std::vector<MigratableCreditCard>& migratable_credit_cards_;
+ const bool full_sync_enabled_;
+ MigrateCardsCallback callback_;
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
+ std::string display_text_;
+};
+
} // namespace
const char PaymentsClient::kRecipientName[] = "recipient_name";
@@ -455,18 +660,21 @@ PaymentsClient::UploadRequestDetails::UploadRequestDetails(
const UploadRequestDetails& other) = default;
PaymentsClient::UploadRequestDetails::~UploadRequestDetails() {}
+PaymentsClient::MigrationRequestDetails::MigrationRequestDetails() {}
+PaymentsClient::MigrationRequestDetails::MigrationRequestDetails(
+ const MigrationRequestDetails& other) = default;
+PaymentsClient::MigrationRequestDetails::~MigrationRequestDetails() {}
+
PaymentsClient::PaymentsClient(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
PrefService* pref_service,
identity::IdentityManager* identity_manager,
- PaymentsClientUnmaskDelegate* unmask_delegate,
- PaymentsClientSaveDelegate* save_delegate,
+ AccountInfoGetter* account_info_getter,
bool is_off_the_record)
: url_loader_factory_(url_loader_factory),
pref_service_(pref_service),
identity_manager_(identity_manager),
- unmask_delegate_(unmask_delegate),
- save_delegate_(save_delegate),
+ account_info_getter_(account_info_getter),
is_off_the_record_(is_off_the_record),
has_retried_authorization_(false),
weak_ptr_factory_(this) {}
@@ -478,20 +686,18 @@ void PaymentsClient::Prepare() {
StartTokenFetch(false);
}
-void PaymentsClient::SetSaveDelegate(
- PaymentsClientSaveDelegate* save_delegate) {
- save_delegate_ = save_delegate;
-}
-
PrefService* PaymentsClient::GetPrefService() const {
return pref_service_;
}
void PaymentsClient::UnmaskCard(
- const PaymentsClient::UnmaskRequestDetails& request_details) {
- DCHECK(unmask_delegate_);
+ const PaymentsClient::UnmaskRequestDetails& request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback) {
IssueRequest(
- std::make_unique<UnmaskCardRequest>(request_details, unmask_delegate_),
+ std::make_unique<UnmaskCardRequest>(
+ request_details, account_info_getter_->IsSyncFeatureEnabled(),
+ std::move(callback)),
true);
}
@@ -500,22 +706,41 @@ void PaymentsClient::GetUploadDetails(
const int detected_values,
const std::string& pan_first_six,
const std::vector<const char*>& active_experiments,
- const std::string& app_locale) {
- DCHECK(save_delegate_);
- IssueRequest(std::make_unique<GetUploadDetailsRequest>(
- addresses, detected_values, pan_first_six,
- active_experiments, app_locale, save_delegate_),
- false);
+ const std::string& app_locale,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const base::string16&,
+ std::unique_ptr<base::DictionaryValue>)> callback,
+ const int billable_service_number) {
+ IssueRequest(
+ std::make_unique<GetUploadDetailsRequest>(
+ addresses, detected_values, pan_first_six, active_experiments,
+ account_info_getter_->IsSyncFeatureEnabled(), app_locale,
+ std::move(callback), billable_service_number),
+ false);
}
void PaymentsClient::UploadCard(
- const PaymentsClient::UploadRequestDetails& request_details) {
- DCHECK(save_delegate_);
+ const PaymentsClient::UploadRequestDetails& request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback) {
IssueRequest(
- std::make_unique<UploadCardRequest>(request_details, save_delegate_),
+ std::make_unique<UploadCardRequest>(
+ request_details, account_info_getter_->IsSyncFeatureEnabled(),
+ std::move(callback)),
true);
}
+void PaymentsClient::MigrateCards(
+ const MigrationRequestDetails& request_details,
+ const std::vector<MigratableCreditCard>& migratable_credit_cards,
+ MigrateCardsCallback callback) {
+ IssueRequest(
+ std::make_unique<MigrateCardsRequest>(
+ request_details, migratable_credit_cards,
+ account_info_getter_->IsSyncFeatureEnabled(), std::move(callback)),
+ /*authenticate=*/true);
+}
+
void PaymentsClient::CancelRequest() {
request_.reset();
resource_request_.reset();
@@ -670,20 +895,23 @@ void PaymentsClient::StartTokenFetch(bool invalidate_old) {
if (!invalidate_old && token_fetcher_)
return;
+ DCHECK(account_info_getter_);
+
OAuth2TokenService::ScopeSet payments_scopes;
payments_scopes.insert(kPaymentsOAuth2Scope);
+ std::string account_id =
+ account_info_getter_->GetAccountInfoForPaymentsServer().account_id;
if (invalidate_old) {
DCHECK(!access_token_.empty());
- identity_manager_->RemoveAccessTokenFromCache(
- identity_manager_->GetPrimaryAccountInfo().account_id, payments_scopes,
- access_token_);
+ identity_manager_->RemoveAccessTokenFromCache(account_id, payments_scopes,
+ access_token_);
}
access_token_.clear();
- token_fetcher_ = std::make_unique<identity::PrimaryAccountAccessTokenFetcher>(
- kTokenFetchId, identity_manager_, payments_scopes,
+ token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
+ account_id, kTokenFetchId, payments_scopes,
base::BindOnce(&PaymentsClient::AccessTokenFetchFinished,
base::Unretained(this)),
- identity::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+ identity::AccessTokenFetcher::Mode::kImmediate);
}
void PaymentsClient::SetOAuth2TokenAndStartRequest() {
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h
index e8eef9d974b..95b36dce181 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/payments_client.h
@@ -15,11 +15,11 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/prefs/pref_service.h"
#include "google_apis/gaia/google_service_auth_error.h"
+#include "services/identity/public/cpp/access_token_fetcher.h"
#include "services/identity/public/cpp/access_token_info.h"
namespace identity {
class IdentityManager;
-class PrimaryAccountAccessTokenFetcher;
} // namespace identity
namespace network {
@@ -30,34 +30,28 @@ class SharedURLLoaderFactory;
namespace autofill {
-namespace payments {
+class AccountInfoGetter;
+class MigratableCreditCard;
-class PaymentsRequest;
+namespace payments {
-class PaymentsClientUnmaskDelegate {
- public:
- // Returns the real PAN retrieved from Payments. |real_pan| will be empty
- // on failure.
- virtual void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) = 0;
-};
+// Callback type for MigrateCards callback. |result| is the Payments Rpc result.
+// |save_result| is an unordered_map parsed from the response whose key is the
+// unique id (guid) for each card and value is the server save result string.
+// |display_text| is the returned tip from Payments to show on the UI.
+typedef base::OnceCallback<void(
+ AutofillClient::PaymentsRpcResult result,
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result,
+ const std::string& display_text)>
+ MigrateCardsCallback;
+
+// Billable service number is defined in Payments server to distinguish
+// different requests.
+const int kUnmaskCardBillableServiceNumber = 70154;
+const int kUploadCardBillableServiceNumber = 70073;
+const int kMigrateCardsBillableServiceNumber = 70264;
-class PaymentsClientSaveDelegate {
- public:
- // Returns the legal message retrieved from Payments. On failure or not
- // meeting Payments's conditions for upload, |legal_message| will contain
- // nullptr.
- virtual void OnDidGetUploadDetails(
- AutofillClient::PaymentsRpcResult result,
- const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) = 0;
-
- // Returns the result of an upload request.
- // If |result| == |AutofillClient::SUCCESS|, |server_id| may, optionally,
- // contain the opaque identifier for the card on the server.
- virtual void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
- const std::string& server_id) = 0;
-};
+class PaymentsRequest;
// PaymentsClient issues Payments RPCs and manages responses and failure
// conditions. Only one request may be active at a time. Initiating a new
@@ -93,6 +87,7 @@ class PaymentsClient {
~UploadRequestDetails();
int64_t billing_customer_number = 0;
+ int detected_values;
CreditCard card;
base::string16 cvc;
std::vector<AutofillProfile> profiles;
@@ -102,17 +97,29 @@ class PaymentsClient {
std::vector<const char*> active_experiments;
};
+ // A collection of the information required to make local credit cards
+ // migration request.
+ struct MigrationRequestDetails {
+ MigrationRequestDetails();
+ MigrationRequestDetails(const MigrationRequestDetails& other);
+ ~MigrationRequestDetails();
+
+ int64_t billing_customer_number = 0;
+ base::string16 context_token;
+ std::string risk_data;
+ std::string app_locale;
+ };
+
// |url_loader_factory| is reference counted so it has no lifetime or
// ownership requirements. |pref_service| is used to get the registered
- // preference value, |identity_manager|, |unmask_delegate| and |save_delegate|
+ // preference value, |identity_manager| and |account_info_getter|
// must all outlive |this|. Either delegate might be nullptr.
// |is_off_the_record| denotes incognito mode.
PaymentsClient(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
- PrefService* pref_service,
- identity::IdentityManager* identity_manager,
- PaymentsClientUnmaskDelegate* unmask_delegate,
- PaymentsClientSaveDelegate* save_delegate,
+ PrefService* const pref_service,
+ identity::IdentityManager* const identity_manager,
+ AccountInfoGetter* const account_info_getter,
bool is_off_the_record = false);
virtual ~PaymentsClient();
@@ -124,15 +131,12 @@ class PaymentsClient {
// accepted an upload prompt.
void Prepare();
- // Sets up the |save_delegate_|. Necessary because CreditCardSaveManager
- // requires PaymentsClient during initialization, so PaymentsClient can't
- // start with save_delegate_ initialized.
- virtual void SetSaveDelegate(PaymentsClientSaveDelegate* save_delegate);
-
PrefService* GetPrefService() const;
// The user has attempted to unmask a card with the given cvc.
- void UnmaskCard(const UnmaskRequestDetails& request_details);
+ void UnmaskCard(const UnmaskRequestDetails& request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback);
// Determine if the user meets the Payments service's conditions for upload.
// The service uses |addresses| (from which names and phone numbers are
@@ -141,20 +145,38 @@ class PaymentsClient {
// being considered for upload. |detected_values| is a bitmask of
// CreditCardSaveManager::DetectedValue values that relays what data is
// actually available for upload in order to make more informed upload
- // decisions. If the conditions are met, the legal message will be returned
- // via OnDidGetUploadDetails. |active_experiments| is used by Payments server
- // to track requests that were triggered by enabled features.
+ // decisions. |callback| is the callback function when get response from
+ // server. |billable_service_number| is used to set the 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.
virtual void GetUploadDetails(
const std::vector<AutofillProfile>& addresses,
const int detected_values,
const std::string& pan_first_six,
const std::vector<const char*>& active_experiments,
- const std::string& app_locale);
+ const std::string& app_locale,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const base::string16&,
+ std::unique_ptr<base::DictionaryValue>)> callback,
+ const int billable_service_number);
// 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
// GetUploadDetails has not already been made.
- virtual void UploadCard(const UploadRequestDetails& details);
+ virtual void UploadCard(
+ const UploadRequestDetails& details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback);
+
+ // The user has indicated that they would like to migrate their local credit
+ // cards. This request will fail server-side if a successful call to
+ // GetUploadDetails has not already been made.
+ virtual void MigrateCards(
+ const MigrationRequestDetails& details,
+ const std::vector<MigratableCreditCard>& migratable_credit_cards,
+ MigrateCardsCallback callback);
// Cancels and clears the current |request_|.
void CancelRequest();
@@ -202,12 +224,11 @@ class PaymentsClient {
// The pref service for this client.
PrefService* const pref_service_;
+ // Provided in constructor; not owned by PaymentsClient.
identity::IdentityManager* const identity_manager_;
- // Delegates for the results of the various requests to Payments. Both must
- // outlive |this|.
- PaymentsClientUnmaskDelegate* const unmask_delegate_;
- PaymentsClientSaveDelegate* save_delegate_;
+ // Provided in constructor; not owned by PaymentsClient.
+ AccountInfoGetter* const account_info_getter_;
// The current request.
std::unique_ptr<PaymentsRequest> request_;
@@ -218,8 +239,8 @@ class PaymentsClient {
// The URL loader being used to issue the current request.
std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
- // The current OAuth2 token fetcher.
- std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> token_fetcher_;
+ // The OAuth2 token fetcher for any account.
+ std::unique_ptr<identity::AccessTokenFetcher> token_fetcher_;
// The OAuth2 token, or empty if not fetched.
std::string access_token_;
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 2d2027de3be..7e824766c4f 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -17,9 +17,10 @@
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card_save_manager.h"
+#include "components/autofill/core/browser/local_card_migration_manager.h"
#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
@@ -48,11 +49,10 @@ int kAllDetectableValues =
} // namespace
-class PaymentsClientTest : public testing::Test,
- public PaymentsClientUnmaskDelegate,
- public PaymentsClientSaveDelegate {
+class PaymentsClientTest : public testing::Test {
public:
- PaymentsClientTest() : result_(AutofillClient::NONE) {}
+ PaymentsClientTest()
+ : result_(AutofillClient::NONE), weak_ptr_factory_(this) {}
~PaymentsClientTest() override {}
void SetUp() override {
@@ -74,15 +74,28 @@ class PaymentsClientTest : public testing::Test,
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_);
TestingPrefServiceSimple pref_service_;
- client_.reset(
- new PaymentsClient(test_shared_loader_factory_, &pref_service_,
- identity_test_env_.identity_manager(), this, this));
+ client_ = std::make_unique<PaymentsClient>(
+ test_shared_loader_factory_, &pref_service_,
+ identity_test_env_.identity_manager(), &test_personal_data_);
+ test_personal_data_.SetAccountInfoForPayments(
+ identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com"));
}
void TearDown() override { client_.reset(); }
void EnableAutofillUpstreamSendPanFirstSixExperiment() {
- scoped_feature_list_.InitAndEnableFeature(kAutofillUpstreamSendPanFirstSix);
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillUpstreamSendPanFirstSix);
+ }
+
+ void EnableAutofillSendExperimentIdsInPaymentsRPCs() {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillSendExperimentIdsInPaymentsRPCs);
+ }
+
+ void EnableAutofillGetPaymentsIdentityFromSync() {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillGetPaymentsIdentityFromSync);
}
void DisableAutofillSendExperimentIdsInPaymentsRPCs() {
@@ -101,55 +114,65 @@ class PaymentsClientTest : public testing::Test,
base::FieldTrialList::CreateFieldTrial(trial_name, group_name)->group();
}
- // PaymentsClientUnmaskDelegate:
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
- const std::string& real_pan) override {
+ const std::string& real_pan) {
result_ = result;
real_pan_ = real_pan;
}
- // PaymentsClientSaveDelegate:
void OnDidGetUploadDetails(
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
- std::unique_ptr<base::DictionaryValue> legal_message) override {
+ std::unique_ptr<base::DictionaryValue> legal_message) {
result_ = result;
legal_message_ = std::move(legal_message);
}
+
void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
- const std::string& server_id) override {
+ const std::string& server_id) {
result_ = result;
server_id_ = server_id;
}
+ void OnDidMigrateLocalCards(
+ AutofillClient::PaymentsRpcResult result,
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result,
+ const std::string& display_text) {
+ result_ = result;
+ save_result_ = std::move(save_result);
+ display_text_ = display_text;
+ }
+
protected:
base::test::ScopedFeatureList scoped_feature_list_;
+ // Issue an UnmaskCard request. This requires an OAuth token before starting
+ // the request.
void StartUnmasking() {
- if (!identity_test_env_.identity_manager()->HasPrimaryAccount())
- identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
-
PaymentsClient::UnmaskRequestDetails request_details;
request_details.billing_customer_number = 111222333444;
request_details.card = test::GetMaskedServerCard();
request_details.user_response.cvc = base::ASCIIToUTF16("123");
request_details.risk_data = "some risk data";
- client_->UnmaskCard(request_details);
+ client_->UnmaskCard(request_details,
+ base::BindOnce(&PaymentsClientTest::OnDidGetRealPan,
+ weak_ptr_factory_.GetWeakPtr()));
}
+ // Issue a GetUploadDetails request.
void StartGettingUploadDetails() {
- if (!identity_test_env_.identity_manager()->HasPrimaryAccount())
- identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
-
- client_->GetUploadDetails(BuildTestProfiles(), kAllDetectableValues,
- /*pan_first_six=*/"411111",
- std::vector<const char*>(), "language-LOCALE");
+ client_->GetUploadDetails(
+ BuildTestProfiles(), kAllDetectableValues,
+ /*pan_first_six=*/"411111", std::vector<const char*>(),
+ "language-LOCALE",
+ base::BindOnce(&PaymentsClientTest::OnDidGetUploadDetails,
+ weak_ptr_factory_.GetWeakPtr()),
+ /*billable_service_number=*/12345);
}
+ // Issue an UploadCard request. This requires an OAuth token before starting
+ // the request.
void StartUploading(bool include_cvc) {
- if (!identity_test_env_.identity_manager()->HasPrimaryAccount())
- identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
-
PaymentsClient::UploadRequestDetails request_details;
request_details.billing_customer_number = 111222333444;
request_details.card = test::GetCreditCard();
@@ -159,7 +182,32 @@ class PaymentsClientTest : public testing::Test,
request_details.risk_data = "some risk data";
request_details.app_locale = "language-LOCALE";
request_details.profiles = BuildTestProfiles();
- client_->UploadCard(request_details);
+ client_->UploadCard(request_details,
+ base::BindOnce(&PaymentsClientTest::OnDidUploadCard,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ void StartMigrating(bool uncheck_last_card, bool has_cardholder_name) {
+ PaymentsClient::MigrationRequestDetails request_details;
+ request_details.context_token = base::ASCIIToUTF16("context token");
+ request_details.risk_data = "some risk data";
+ request_details.app_locale = "language-LOCALE";
+
+ migratable_credit_cards_.clear();
+ CreditCard card1 = test::GetCreditCard();
+ CreditCard card2 = test::GetCreditCard2();
+ if (!has_cardholder_name) {
+ card1.SetRawInfo(CREDIT_CARD_NAME_FULL, base::UTF8ToUTF16(""));
+ card2.SetRawInfo(CREDIT_CARD_NAME_FULL, base::UTF8ToUTF16(""));
+ }
+ migratable_credit_cards_.push_back(MigratableCreditCard(card1));
+ migratable_credit_cards_.push_back(MigratableCreditCard(card2));
+ if (uncheck_last_card)
+ migratable_credit_cards_.back().ToggleChosen();
+ client_->MigrateCards(
+ request_details, migratable_credit_cards_,
+ base::BindOnce(&PaymentsClientTest::OnDidMigrateLocalCards,
+ weak_ptr_factory_.GetWeakPtr()));
}
network::TestURLLoaderFactory* factory() { return &test_url_loader_factory_; }
@@ -168,6 +216,8 @@ class PaymentsClientTest : public testing::Test,
net::HttpRequestHeaders* GetRequestHeaders() { return &intercepted_headers_; }
+ // Issues access token in response to any access token request. This will
+ // start the Payments Request which requires the authentication.
void IssueOAuthToken() {
identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"totally_real_token",
@@ -190,15 +240,20 @@ class PaymentsClientTest : public testing::Test,
std::string server_id_;
std::string real_pan_;
std::unique_ptr<base::DictionaryValue> legal_message_;
+ std::vector<MigratableCreditCard> migratable_credit_cards_;
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_;
+ std::string display_text_;
base::test::ScopedTaskEnvironment scoped_task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
+ TestPersonalDataManager test_personal_data_;
std::unique_ptr<PaymentsClient> client_;
identity::IdentityTestEnvironment identity_test_env_;
net::HttpRequestHeaders intercepted_headers_;
std::string intercepted_body_;
+ base::WeakPtrFactory<PaymentsClientTest> weak_ptr_factory_;
private:
DISALLOW_COPY_AND_ASSIGN(PaymentsClientTest);
@@ -261,6 +316,60 @@ TEST_F(PaymentsClientTest, UnmaskSuccess) {
EXPECT_EQ("1234", real_pan_);
}
+TEST_F(PaymentsClientTest, UnmaskSuccessAccountFromSyncTest) {
+ EnableAutofillGetPaymentsIdentityFromSync();
+ StartUnmasking();
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK, "{ \"pan\": \"1234\" }");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_EQ("1234", real_pan_);
+}
+
+TEST_F(PaymentsClientTest, UnmaskIncludesChromeUserContext) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage}); // Disabled
+
+ StartUnmasking();
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK, "{}");
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ UnmaskIncludesChromeUserContextIfWalletStorageFlagEnabled) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillEnableAccountWalletStorage}, // Enabled
+ {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartUnmasking();
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK, "{}");
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, UnmaskExcludesChromeUserContextIfExperimentsOff) {
+ scoped_feature_list_.InitWithFeatures(
+ {}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage,
+ features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartUnmasking();
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK, "{}");
+
+ // ChromeUserContext was not set.
+ EXPECT_TRUE(!GetUploadData().empty());
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos);
+}
+
TEST_F(PaymentsClientTest, GetDetailsSuccess) {
StartGettingUploadDetails();
ReturnResponse(
@@ -303,6 +412,69 @@ TEST_F(PaymentsClientTest, GetDetailsIncludesDetectedValuesInRequest) {
std::string::npos);
}
+TEST_F(PaymentsClientTest, GetDetailsIncludesChromeUserContext) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage}); // Disabled
+
+ StartGettingUploadDetails();
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ GetDetailsIncludesChromeUserContextIfWalletStorageFlagEnabled) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillEnableAccountWalletStorage}, // Enabled
+ {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartGettingUploadDetails();
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ GetDetailsExcludesChromeUserContextIfExperimentsOff) {
+ scoped_feature_list_.InitWithFeatures(
+ {}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage,
+ features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartGettingUploadDetails();
+
+ // ChromeUserContext was not set.
+ EXPECT_TRUE(!GetUploadData().empty());
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, GetUploadAccountFromSyncTest) {
+ EnableAutofillGetPaymentsIdentityFromSync();
+ // Set up a different account.
+ const AccountInfo& secondary_account_info =
+ identity_test_env_.MakeAccountAvailable("secondary@gmail.com");
+ test_personal_data_.SetAccountInfoForPayments(secondary_account_info);
+
+ StartUploading(/*include_cvc=*/true);
+ ReturnResponse(net::HTTP_OK, "{}");
+
+ // Issue a token for the secondary account.
+ identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ secondary_account_info.account_id, "secondary_account_token",
+ base::Time::Now() + base::TimeDelta::FromDays(10));
+
+ // Verify the auth header.
+ std::string auth_header_value;
+ EXPECT_TRUE(intercepted_headers_.GetHeader(
+ net::HttpRequestHeaders::kAuthorization, &auth_header_value))
+ << intercepted_headers_.ToString();
+ EXPECT_EQ("Bearer secondary_account_token", auth_header_value);
+}
+
TEST_F(PaymentsClientTest, GetUploadDetailsVariationsTest) {
// Register a trial and variation id, so that there is data in variations
// headers. Also, the variations header provider may have been registered to
@@ -410,6 +582,43 @@ TEST_F(PaymentsClientTest, UnmaskCardVariationsTestExperimentOff) {
variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
}
+TEST_F(PaymentsClientTest, MigrateCardsVariationsTest) {
+ // Register a trial and variation id, so that there is data in variations
+ // headers. Also, the variations header provider may have been registered to
+ // observe some other field trial list, so reset it.
+ EnableAutofillSendExperimentIdsInPaymentsRPCs();
+ variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
+ base::FieldTrialList field_trial_list_(nullptr);
+ CreateFieldTrialWithId("AutofillTest", "Group", 369);
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ std::string value;
+ EXPECT_TRUE(GetRequestHeaders()->GetHeader("X-Client-Data", &value));
+ // Note that experiment information is stored in X-Client-Data.
+ EXPECT_FALSE(value.empty());
+
+ variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
+}
+
+TEST_F(PaymentsClientTest, MigrateCardsVariationsTestExperimentFlagOff) {
+ // Register a trial and variation id, so that there is data in variations
+ // headers. Also, the variations header provider may have been registered to
+ // observe some other field trial list, so reset it.
+ DisableAutofillSendExperimentIdsInPaymentsRPCs();
+ variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
+ base::FieldTrialList field_trial_list_(nullptr);
+ CreateFieldTrialWithId("AutofillTest", "Group", 369);
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+
+ std::string value;
+ EXPECT_FALSE(GetRequestHeaders()->GetHeader("X-Client-Data", &value));
+ // Note that experiment information is stored in X-Client-Data.
+ EXPECT_TRUE(value.empty());
+
+ variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting();
+}
+
TEST_F(PaymentsClientTest,
GetDetailsIncludesPanFirstSixInRequestIfExperimentOn) {
EnableAutofillUpstreamSendPanFirstSixExperiment();
@@ -430,6 +639,14 @@ TEST_F(PaymentsClientTest,
std::string::npos);
}
+TEST_F(PaymentsClientTest, GetDetailsIncludeBillableServiceNumber) {
+ StartGettingUploadDetails();
+
+ // Verify that billable service number was included in the request.
+ EXPECT_TRUE(GetUploadData().find("\"billable_service\":12345") !=
+ std::string::npos);
+}
+
TEST_F(PaymentsClientTest, UploadSuccessWithoutServerId) {
StartUploading(/*include_cvc=*/true);
IssueOAuthToken();
@@ -492,9 +709,53 @@ TEST_F(PaymentsClientTest, UploadIncludesCvcInRequestIfProvided) {
EXPECT_TRUE(GetUploadData().find("&s7e_13_cvc=") != std::string::npos);
}
+TEST_F(PaymentsClientTest, UploadIncludesChromeUserContext) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage}); // Disabled
+
+ StartUploading(/*include_cvc=*/true);
+ IssueOAuthToken();
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ UploadIncludesChromeUserContextIfWalletStorageFlagEnabled) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillEnableAccountWalletStorage}, // Enabled
+ {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartUploading(/*include_cvc=*/true);
+ IssueOAuthToken();
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, UploadExcludesChromeUserContextIfExperimentsOff) {
+ scoped_feature_list_.InitWithFeatures(
+ {}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage,
+ features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartUploading(/*include_cvc=*/true);
+ IssueOAuthToken();
+
+ // ChromeUserContext was not set.
+ EXPECT_TRUE(!GetUploadData().empty());
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos);
+}
+
TEST_F(PaymentsClientTest, UploadDoesNotIncludeCvcInRequestIfNotProvided) {
StartUploading(/*include_cvc=*/false);
+ IssueOAuthToken();
+ EXPECT_TRUE(!GetUploadData().empty());
// Verify that the encrypted_cvc and s7e_13_cvc parameters were not included
// in the request.
EXPECT_TRUE(GetUploadData().find("encrypted_cvc") == std::string::npos);
@@ -502,6 +763,147 @@ TEST_F(PaymentsClientTest, UploadDoesNotIncludeCvcInRequestIfNotProvided) {
EXPECT_TRUE(GetUploadData().find("&s7e_13_cvc=") == std::string::npos);
}
+TEST_F(PaymentsClientTest, MigrationRequestIncludesUniqueId) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ // Verify that the unique id was included in the request.
+ EXPECT_TRUE(GetUploadData().find("unique_id") != std::string::npos);
+ EXPECT_TRUE(
+ GetUploadData().find(migratable_credit_cards_[0].credit_card().guid()) !=
+ std::string::npos);
+ EXPECT_TRUE(
+ GetUploadData().find(migratable_credit_cards_[1].credit_card().guid()) !=
+ std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, MigrationRequestIncludesEncryptedPan) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ // Verify that the encrypted_pan and s7e_1_pan parameters were included
+ // in the request.
+ EXPECT_TRUE(GetUploadData().find("encrypted_pan") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("__param:s7e_1_pan0") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("&s7e_1_pan0=4111111111111111") !=
+ std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("__param:s7e_1_pan1") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("&s7e_1_pan1=378282246310005") !=
+ std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, MigrationRequestExcludesUncheckedCard) {
+ StartMigrating(/*uncheck_last_card=*/true, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ // Verify that the encrypted_pan and s7e_1_pan parameters were included
+ // in the request.
+ EXPECT_TRUE(GetUploadData().find("encrypted_pan") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("__param:s7e_1_pan0") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("&s7e_1_pan0=4111111111111111") !=
+ std::string::npos);
+ EXPECT_FALSE(GetUploadData().find("__param:s7e_1_pan1") != std::string::npos);
+ EXPECT_FALSE(GetUploadData().find("&s7e_1_pan1=378282246310005") !=
+ std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, MigrationRequestIncludesCardholderNameWhenItExists) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ EXPECT_TRUE(!GetUploadData().empty());
+ // Verify that the cardholder name is sent if it exists.
+ EXPECT_TRUE(GetUploadData().find("cardholder_name") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ MigrationRequestExcludesCardholderNameWhenItDoesNotExist) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/false);
+ IssueOAuthToken();
+
+ EXPECT_TRUE(!GetUploadData().empty());
+ // Verify that the cardholder name is not sent if it doesn't exist.
+ EXPECT_TRUE(GetUploadData().find("cardholder_name") == std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, MigrationRequestIncludesChromeUserContext) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillGetPaymentsIdentityFromSync}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage}); // Disabled
+
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ MigrationRequestIncludesChromeUserContextIfWalletStorageFlagEnabled) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillEnableAccountWalletStorage}, // Enabled
+ {features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ // ChromeUserContext was set.
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") != std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") != std::string::npos);
+}
+
+TEST_F(PaymentsClientTest,
+ MigrationRequestExcludesChromeUserContextIfExperimentsOff) {
+ scoped_feature_list_.InitWithFeatures(
+ {}, // Enabled
+ {features::kAutofillEnableAccountWalletStorage,
+ features::kAutofillGetPaymentsIdentityFromSync}); // Disabled
+
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+
+ // ChromeUserContext was not set.
+ EXPECT_TRUE(!GetUploadData().empty());
+ EXPECT_TRUE(GetUploadData().find("chrome_user_context") == std::string::npos);
+ EXPECT_TRUE(GetUploadData().find("full_sync_enabled") == std::string::npos);
+}
+
+TEST_F(PaymentsClientTest, MigrationSuccessWithSaveResult) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK,
+ "{\"save_result\":[{\"unique_id\":\"0\",\"status\":"
+ "\"SUCCESS\"},{\"unique_id\":\"1\",\"status\":\"TEMPORARY_"
+ "FAILURE\"}],\"value_prop_display_text\":\"display text\"}");
+
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_TRUE(save_result_.get());
+ EXPECT_TRUE(save_result_->find("0") != save_result_->end());
+ EXPECT_TRUE(save_result_->at("0") == "SUCCESS");
+ EXPECT_TRUE(save_result_->find("1") != save_result_->end());
+ EXPECT_TRUE(save_result_->at("1") == "TEMPORARY_FAILURE");
+}
+
+TEST_F(PaymentsClientTest, MigrationMissingSaveResult) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK,
+ "{\"value_prop_display_text\":\"display text\"}");
+ EXPECT_EQ(AutofillClient::PERMANENT_FAILURE, result_);
+ EXPECT_EQ(nullptr, save_result_.get());
+}
+
+TEST_F(PaymentsClientTest, MigrationSuccessWithDisplayText) {
+ StartMigrating(/*uncheck_last_card=*/false, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+ ReturnResponse(net::HTTP_OK,
+ "{\"save_result\":[{\"unique_id\":\"0\",\"status\":"
+ "\"SUCCESS\"}],\"value_prop_display_text\":\"display text\"}");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+ EXPECT_EQ("display text", display_text_);
+}
+
TEST_F(PaymentsClientTest, GetDetailsFollowedByUploadSuccess) {
StartGettingUploadDetails();
ReturnResponse(
@@ -517,6 +919,23 @@ TEST_F(PaymentsClientTest, GetDetailsFollowedByUploadSuccess) {
EXPECT_EQ(AutofillClient::SUCCESS, result_);
}
+TEST_F(PaymentsClientTest, GetDetailsFollowedByMigrationSuccess) {
+ StartGettingUploadDetails();
+ ReturnResponse(
+ net::HTTP_OK,
+ "{ \"context_token\": \"some_token\", \"legal_message\": {} }");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+
+ result_ = AutofillClient::NONE;
+
+ StartMigrating(/*uncheck_last_card=*/true, /*has_cardholder_name=*/true);
+ IssueOAuthToken();
+ ReturnResponse(
+ net::HTTP_OK,
+ "{\"save_result\":[],\"value_prop_display_text\":\"display text\"}");
+ EXPECT_EQ(AutofillClient::SUCCESS, result_);
+}
+
TEST_F(PaymentsClientTest, UnmaskMissingPan) {
StartUnmasking();
ReturnResponse(net::HTTP_OK, "{}");
diff --git a/chromium/components/autofill/core/browser/payments/payments_customer_data.h b/chromium/components/autofill/core/browser/payments/payments_customer_data.h
new file mode 100644
index 00000000000..7f95892ac09
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/payments_customer_data.h
@@ -0,0 +1,30 @@
+// 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_PAYMENTS_PAYMENTS_CUSTOMER_DATA_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CUSTOMER_DATA_H_
+
+#include <string>
+
+namespace autofill {
+
+// Represents the Google Payments customer data.
+struct PaymentsCustomerData {
+ explicit PaymentsCustomerData(const std::string& customer_id)
+ : customer_id(customer_id) {}
+
+ bool operator==(const PaymentsCustomerData& other) const {
+ return customer_id == other.customer_id;
+ }
+ bool operator!=(const PaymentsCustomerData& other) const {
+ return !(*this == other);
+ }
+
+ // The identifier by which a Google Payments account is identified.
+ std::string customer_id;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CUSTOMER_DATA_H_
diff --git a/chromium/components/autofill/core/browser/payments/payments_util.cc b/chromium/components/autofill/core/browser/payments/payments_util.cc
new file mode 100644
index 00000000000..6f181414143
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/payments_util.cc
@@ -0,0 +1,49 @@
+// 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/payments/payments_util.h"
+
+#include "base/feature_list.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/prefs/pref_service.h"
+
+namespace autofill {
+namespace payments {
+
+int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
+ PrefService* pref_service) {
+ DCHECK(personal_data_manager);
+ DCHECK(pref_service);
+
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillUsePaymentsCustomerData) ||
+ base::FeatureList::IsEnabled(
+ features::kAutofillEnableAccountWalletStorage)) {
+ // Get billing customer ID from the synced PaymentsCustomerData.
+ PaymentsCustomerData* customer_data =
+ personal_data_manager->GetPaymentsCustomerData();
+ if (customer_data && !customer_data->customer_id.empty()) {
+ int64_t billing_customer_id = 0;
+ if (base::StringToInt64(base::StringPiece(customer_data->customer_id),
+ &billing_customer_id)) {
+ AutofillMetrics::LogPaymentsCustomerDataBillingIdIsValid(true);
+ return billing_customer_id;
+ }
+ }
+ AutofillMetrics::LogPaymentsCustomerDataBillingIdIsValid(false);
+ }
+
+ // Get billing customer ID from priority preferences.
+ return static_cast<int64_t>(
+ pref_service->GetDouble(prefs::kAutofillBillingCustomerNumber));
+}
+
+} // namespace payments
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/payments_util.h b/chromium/components/autofill/core/browser/payments/payments_util.h
new file mode 100644
index 00000000000..364284a1397
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/payments_util.h
@@ -0,0 +1,27 @@
+// 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_PAYMENTS_PAYMENTS_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_UTIL_H_
+
+#include <stdint.h>
+
+class PrefService;
+
+namespace autofill {
+
+class PersonalDataManager;
+
+namespace payments {
+
+// Returns the billing customer ID (a.k.a. the customer number) for the Google
+// Payments account for this user. Obtains it from the synced data. Returns 0
+// if the customer ID was not found.
+int64_t GetBillingCustomerId(PersonalDataManager* personal_data_manager,
+ PrefService* pref_service);
+
+} // namespace payments
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_UTIL_H_
diff --git a/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc b/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc
new file mode 100644
index 00000000000..057bade43f3
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/payments_util_unittest.cc
@@ -0,0 +1,103 @@
+// 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/payments/payments_util.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace payments {
+
+class PaymentsUtilTest : public testing::Test {
+ public:
+ PaymentsUtilTest() {}
+ ~PaymentsUtilTest() override {}
+
+ protected:
+ void SetUp() override {
+ pref_service_.registry()->RegisterDoublePref(
+ prefs::kAutofillBillingCustomerNumber, 0.0);
+ }
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+ TestPersonalDataManager personal_data_manager_;
+ TestingPrefServiceSimple pref_service_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PaymentsUtilTest);
+};
+
+TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_Normal) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillUsePaymentsCustomerData);
+ base::HistogramTester histogram_tester;
+
+ personal_data_manager_.SetPaymentsCustomerData(
+ std::make_unique<PaymentsCustomerData>(/*customer_id=*/"123456"));
+
+ EXPECT_EQ(123456,
+ GetBillingCustomerId(&personal_data_manager_, &pref_service_));
+
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.PaymentsCustomerDataBillingIdIsValid", true, 1);
+}
+
+TEST_F(PaymentsUtilTest, GetBillingCustomerId_PaymentsCustomerData_NoData) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillUsePaymentsCustomerData);
+ base::HistogramTester histogram_tester;
+
+ // Explictly do not set PaymentsCustomerData. Nothing crashes and the returned
+ // customer ID is 0.
+ EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_, &pref_service_));
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.PaymentsCustomerDataBillingIdIsValid", false, 1);
+}
+
+TEST_F(PaymentsUtilTest,
+ GetBillingCustomerId_PaymentsCustomerData_NoDataFallback) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillUsePaymentsCustomerData);
+ base::HistogramTester histogram_tester;
+
+ // Explictly do not set PaymentsCustomerData but set a fallback to prefs.
+ pref_service_.SetDouble(prefs::kAutofillBillingCustomerNumber, 123456.0);
+
+ // We got the data from prefs and log that the PaymentsCustomerData is
+ // invalid.
+ EXPECT_EQ(123456,
+ GetBillingCustomerId(&personal_data_manager_, &pref_service_));
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.PaymentsCustomerDataBillingIdIsValid", false, 1);
+}
+
+TEST_F(PaymentsUtilTest, GetBillingCustomerId_PriorityPrefs_Normal) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillUsePaymentsCustomerData);
+
+ pref_service_.SetDouble(prefs::kAutofillBillingCustomerNumber, 123456.0);
+
+ EXPECT_EQ(123456,
+ GetBillingCustomerId(&personal_data_manager_, &pref_service_));
+}
+
+TEST_F(PaymentsUtilTest, GetBillingCustomerId_PriorityPrefs_NoData) {
+ scoped_feature_list_.InitAndDisableFeature(
+ features::kAutofillUsePaymentsCustomerData);
+
+ // Explictly do not set Prefs data. Nothing crashes and the returned customer
+ // ID is 0.
+ EXPECT_EQ(0, GetBillingCustomerId(&personal_data_manager_, &pref_service_));
+}
+
+} // namespace payments
+} // namespace autofill
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 104864965a2..3918e35b143 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.cc
@@ -5,6 +5,7 @@
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace autofill {
@@ -14,14 +15,11 @@ TestPaymentsClient::TestPaymentsClient(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_,
PrefService* pref_service,
identity::IdentityManager* identity_manager,
- payments::PaymentsClientUnmaskDelegate* unmask_delegate,
- payments::PaymentsClientSaveDelegate* save_delegate)
+ PersonalDataManager* personal_data_manager)
: PaymentsClient(url_loader_factory_,
pref_service,
identity_manager,
- unmask_delegate,
- save_delegate),
- save_delegate_(save_delegate) {}
+ personal_data_manager) {}
TestPaymentsClient::~TestPaymentsClient() {}
@@ -30,33 +28,47 @@ void TestPaymentsClient::GetUploadDetails(
const int detected_values,
const std::string& pan_first_six,
const std::vector<const char*>& active_experiments,
- const std::string& app_locale) {
+ const std::string& app_locale,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const base::string16&,
+ std::unique_ptr<base::DictionaryValue>)> callback,
+ const int billable_service_number) {
upload_details_addresses_ = addresses;
detected_values_ = detected_values;
pan_first_six_ = pan_first_six;
active_experiments_ = active_experiments;
- save_delegate_->OnDidGetUploadDetails(
- app_locale == "en-US" ? AutofillClient::SUCCESS
- : AutofillClient::PERMANENT_FAILURE,
- base::ASCIIToUTF16("this is a context token"),
- std::unique_ptr<base::DictionaryValue>(nullptr));
+ 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));
}
void TestPaymentsClient::UploadCard(
- const payments::PaymentsClient::UploadRequestDetails& request_details) {
+ const payments::PaymentsClient::UploadRequestDetails& request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback) {
+ upload_card_addresses_ = request_details.profiles;
active_experiments_ = request_details.active_experiments;
- save_delegate_->OnDidUploadCard(AutofillClient::SUCCESS, server_id_);
+ std::move(callback).Run(AutofillClient::SUCCESS, server_id_);
}
-void TestPaymentsClient::SetSaveDelegate(
- payments::PaymentsClientSaveDelegate* save_delegate) {
- save_delegate_ = save_delegate;
- payments::PaymentsClient::SetSaveDelegate(save_delegate);
+void TestPaymentsClient::MigrateCards(
+ const MigrationRequestDetails& details,
+ const std::vector<MigratableCreditCard>& migratable_credit_cards,
+ MigrateCardsCallback callback) {
+ std::move(callback).Run(AutofillClient::SUCCESS, std::move(save_result_),
+ "this is display text");
}
void TestPaymentsClient::SetServerIdForCardUpload(std::string server_id) {
server_id_ = server_id;
}
+void TestPaymentsClient::SetSaveResultForCardsMigration(
+ std::unique_ptr<std::unordered_map<std::string, std::string>> save_result) {
+ save_result_ = std::move(save_result);
+}
+
} // namespace payments
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/test_payments_client.h b/chromium/components/autofill/core/browser/payments/test_payments_client.h
index 13d24e010ba..da2dba35eaf 100644
--- a/chromium/components/autofill/core/browser/payments/test_payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/test_payments_client.h
@@ -23,41 +23,57 @@ class TestPaymentsClient : public payments::PaymentsClient {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_,
PrefService* pref_service,
identity::IdentityManager* identity_manager,
- payments::PaymentsClientUnmaskDelegate* unmask_delegate,
- payments::PaymentsClientSaveDelegate* save_delegate);
+ PersonalDataManager* personal_data_manager);
~TestPaymentsClient() override;
- void GetUploadDetails(const std::vector<AutofillProfile>& addresses,
- const int detected_values,
- const std::string& pan_first_six,
- const std::vector<const char*>& active_experiments,
- const std::string& app_locale) override;
-
- void UploadCard(const payments::PaymentsClient::UploadRequestDetails&
- request_details) override;
-
- void SetSaveDelegate(
- payments::PaymentsClientSaveDelegate* save_delegate) override;
+ void GetUploadDetails(
+ const std::vector<AutofillProfile>& addresses,
+ const int detected_values,
+ const std::string& pan_first_six,
+ const std::vector<const char*>& active_experiments,
+ const std::string& app_locale,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const base::string16&,
+ std::unique_ptr<base::DictionaryValue>)> callback,
+ const int billable_service_number) override;
+
+ void UploadCard(
+ const payments::PaymentsClient::UploadRequestDetails& request_details,
+ base::OnceCallback<void(AutofillClient::PaymentsRpcResult,
+ const std::string&)> callback) override;
+
+ void MigrateCards(
+ const MigrationRequestDetails& details,
+ const std::vector<MigratableCreditCard>& migratable_credit_cards,
+ MigrateCardsCallback callback) override;
void SetServerIdForCardUpload(std::string);
+ void SetSaveResultForCardsMigration(
+ std::unique_ptr<std::unordered_map<std::string, std::string>>
+ save_result);
+
int detected_values_in_upload_details() const { return detected_values_; }
const std::vector<AutofillProfile>& addresses_in_upload_details() const {
return upload_details_addresses_;
}
std::string pan_first_six_in_upload_details() const { return pan_first_six_; }
+ const std::vector<AutofillProfile>& addresses_in_upload_card() const {
+ return upload_card_addresses_;
+ }
const std::vector<const char*>& active_experiments_in_request() const {
return active_experiments_;
}
private:
- payments::PaymentsClientSaveDelegate* save_delegate_;
std::string server_id_;
std::vector<AutofillProfile> upload_details_addresses_;
+ std::vector<AutofillProfile> upload_card_addresses_;
int detected_values_;
std::string pan_first_six_;
std::vector<const char*> active_experiments_;
+ 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 a53c36fb032..502dd53b8bb 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -40,7 +40,7 @@
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/prefs/pref_service.h"
@@ -405,6 +405,12 @@ class PersonalDatabaseHelper
return server_database_;
}
+ // Whether we're currently using the ephemeral account storage for saving
+ // server cards.
+ bool IsUsingAccountStorageForServerCards() {
+ return server_database_ != profile_database_;
+ }
+
// Set whether this should use the passed in account storage for server
// addresses. If false, this will use the profile_storage.
// It's an error to call this if no account storage was passed in at
@@ -427,9 +433,11 @@ class PersonalDatabaseHelper
return;
}
- if (server_database_ != nullptr && server_database_ != profile_database_) {
- // Remove the previous observer if we had any.
- server_database_->RemoveObserver(personal_data_manager_);
+ if (server_database_ != nullptr) {
+ if (server_database_ != profile_database_) {
+ // Remove the previous observer if we had any.
+ server_database_->RemoveObserver(personal_data_manager_);
+ }
personal_data_manager_->CancelPendingServerQueries();
}
server_database_ = new_server_database;
@@ -456,18 +464,7 @@ class PersonalDatabaseHelper
};
PersonalDataManager::PersonalDataManager(const std::string& app_locale)
- : is_data_loaded_(false),
- pending_profiles_query_(0),
- pending_server_profiles_query_(0),
- pending_creditcards_query_(0),
- pending_server_creditcards_query_(0),
- app_locale_(app_locale),
- pref_service_(nullptr),
- identity_manager_(nullptr),
- sync_service_(nullptr),
- is_off_the_record_(false),
- has_logged_stored_profile_metrics_(false),
- has_logged_stored_credit_card_metrics_(false) {
+ : app_locale_(app_locale) {
database_helper_ = std::make_unique<PersonalDatabaseHelper>(this);
}
@@ -479,7 +476,16 @@ void PersonalDataManager::Init(
bool is_off_the_record) {
CountryNames::SetLocaleString(app_locale_);
database_helper_->Init(profile_database, account_database);
+
SetPrefService(pref_service);
+
+ // Listen for the preference changes.
+ pref_registrar_.Init(pref_service);
+ pref_registrar_.Add(
+ prefs::kAutofillProfileValidity,
+ base::BindRepeating(&PersonalDataManager::ResetProfileValidity,
+ base::Unretained(this)));
+
identity_manager_ = identity_manager;
is_off_the_record_ = is_off_the_record;
@@ -492,7 +498,7 @@ void PersonalDataManager::Init(
}
LoadProfiles();
LoadCreditCards();
-
+ LoadPaymentsCustomerData();
// Check if profile cleanup has already been performed this major version.
is_autofill_profile_cleanup_pending_ =
@@ -509,6 +515,7 @@ PersonalDataManager::~PersonalDataManager() {
CancelPendingLocalQuery(&pending_server_profiles_query_);
CancelPendingLocalQuery(&pending_creditcards_query_);
CancelPendingServerQuery(&pending_server_creditcards_query_);
+ CancelPendingServerQuery(&pending_customer_data_query_);
}
void PersonalDataManager::Shutdown() {
@@ -553,20 +560,22 @@ void PersonalDataManager::OnSyncServiceInitialized(
ResetFullServerCards(/*dry_run=*/!base::FeatureList::IsEnabled(
features::kAutofillResetFullServerCardsOnAuthError));
}
+ if (base::FeatureList::IsEnabled(
+ autofill::features::kAutofillEnableAccountWalletStorage)) {
+ // Use the ephemeral account storage when the user didn't enable the sync
+ // feature explicitly.
+ database_helper_->SetUseAccountStorageForServerCards(
+ !sync_service->IsSyncFeatureEnabled());
+ }
}
}
-void PersonalDataManager::SetUseAccountStorageForServerCards(
- bool use_account_storage_for_server_cards) {
- database_helper_->SetUseAccountStorageForServerCards(
- use_account_storage_for_server_cards);
-}
-
void PersonalDataManager::OnWebDataServiceRequestDone(
WebDataServiceBase::Handle h,
std::unique_ptr<WDTypedResult> result) {
DCHECK(pending_profiles_query_ || pending_server_profiles_query_ ||
- pending_creditcards_query_ || pending_server_creditcards_query_);
+ pending_creditcards_query_ || pending_server_creditcards_query_ ||
+ pending_customer_data_query_);
if (!result) {
// Error from the web database.
@@ -578,6 +587,8 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
pending_server_creditcards_query_ = 0;
else if (h == pending_server_profiles_query_)
pending_server_profiles_query_ = 0;
+ else if (h == pending_server_creditcards_query_)
+ pending_server_profiles_query_ = 0;
} else {
switch (result->GetType()) {
case AUTOFILL_PROFILES_RESULT:
@@ -609,6 +620,16 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
ResetFullServerCards();
}
break;
+ case AUTOFILL_CUSTOMERDATA_RESULT:
+ DCHECK_EQ(h, pending_customer_data_query_)
+ << "received customer data from invalid request.";
+ pending_customer_data_query_ = 0;
+
+ payments_customer_data_ =
+ static_cast<WDResult<std::unique_ptr<PaymentsCustomerData>>*>(
+ result.get())
+ ->GetValue();
+ break;
default:
NOTREACHED();
}
@@ -620,6 +641,7 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0 &&
pending_server_profiles_query_ == 0 &&
pending_server_creditcards_query_ == 0 &&
+ pending_customer_data_query_ == 0 &&
database_helper_->GetServerDatabase()) {
// On initial data load, is_data_loaded_ will be false here.
if (!is_data_loaded_) {
@@ -676,6 +698,13 @@ void PersonalDataManager::OnStateChanged(syncer::SyncService* sync_service) {
ResetFullServerCards(/*dry_run=*/!base::FeatureList::IsEnabled(
features::kAutofillResetFullServerCardsOnAuthError));
}
+ if (base::FeatureList::IsEnabled(
+ autofill::features::kAutofillEnableAccountWalletStorage)) {
+ // Use the ephemeral account storage when the user didn't enable the sync
+ // feature explicitly.
+ database_helper_->SetUseAccountStorageForServerCards(
+ !sync_service->IsSyncFeatureEnabled());
+ }
}
void PersonalDataManager::OnSyncShutdown(syncer::SyncService* sync_service) {
@@ -684,6 +713,26 @@ void PersonalDataManager::OnSyncShutdown(syncer::SyncService* sync_service) {
sync_service_ = nullptr;
}
+AccountInfo PersonalDataManager::GetAccountInfoForPaymentsServer() const {
+ // If butter is enabled or the feature to get the Payment Identity from Sync
+ // is enabled, return the account of the active signed-in user irrespective of
+ // whether they enabled sync or not.
+ // Otherwise, return the latest cached AccountInfo of the user's primary
+ // account, which is empty if the user has disabled sync.
+ // In both cases, the AccountInfo will be empty if the user is not signed in.
+ return ShouldUseActiveSignedInAccount() && sync_service_
+ ? sync_service_->GetAuthenticatedAccountInfo()
+ : identity_manager_->GetPrimaryAccountInfo();
+}
+
+bool PersonalDataManager::IsSyncFeatureEnabled() const {
+ if (!sync_service_)
+ return false;
+
+ return !sync_service_->GetAuthenticatedAccountInfo().IsEmpty() &&
+ !database_helper_->IsUsingAccountStorageForServerCards();
+}
+
void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) {
observers_.AddObserver(observer);
}
@@ -1145,9 +1194,14 @@ std::vector<CreditCard*> PersonalDataManager::GetCreditCards() const {
return result;
}
+PaymentsCustomerData* PersonalDataManager::GetPaymentsCustomerData() const {
+ return payments_customer_data_ ? payments_customer_data_.get() : nullptr;
+}
+
void PersonalDataManager::Refresh() {
LoadProfiles();
LoadCreditCards();
+ LoadPaymentsCustomerData();
}
std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest()
@@ -1188,8 +1242,8 @@ void PersonalDataManager::RemoveProfilesNotUsedSinceTimestamp(
void PersonalDataManager::MaybeRemoveInvalidSuggestions(
const AutofillType& type,
std::vector<AutofillProfile*>* profiles) {
- const bool suggest_invalid =
- base::FeatureList::IsEnabled(kAutofillSuggestInvalidProfileData);
+ const bool suggest_invalid = base::FeatureList::IsEnabled(
+ features::kAutofillSuggestInvalidProfileData);
for (size_t i = 0; i < profiles->size(); ++i) {
bool is_invalid = (*profiles)[i]->GetValidityState(
@@ -1228,7 +1282,8 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions(
// When suggesting with no prefix to match, consider suppressing disused
// address suggestions as well as those based on invalid profile data.
if (field_contents_canon.empty()) {
- if (base::FeatureList::IsEnabled(kAutofillSuppressDisusedAddresses)) {
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillSuppressDisusedAddresses)) {
const base::Time min_last_used =
AutofillClock::Now() - kDisusedProfileTimeDelta;
RemoveProfilesNotUsedSinceTimestamp(min_last_used, &profiles);
@@ -1387,7 +1442,8 @@ std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
// If enabled, suppress disused address profiles when triggered from an empty
// field.
if (field_contents.empty() &&
- base::FeatureList::IsEnabled(kAutofillSuppressDisusedCreditCards)) {
+ base::FeatureList::IsEnabled(
+ features::kAutofillSuppressDisusedCreditCards)) {
const base::Time min_last_used =
AutofillClock::Now() - kDisusedCreditCardTimeDelta;
RemoveExpiredCreditCardsNotUsedSinceTimestamp(AutofillClock::Now(),
@@ -1398,19 +1454,19 @@ std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
}
bool PersonalDataManager::IsAutofillEnabled() const {
- return ::autofill::IsAutofillEnabled(pref_service_);
+ return ::autofill::prefs::IsAutofillEnabled(pref_service_);
}
bool PersonalDataManager::IsAutofillProfileEnabled() const {
- return pref_service_->GetBoolean(prefs::kAutofillProfileEnabled);
+ return ::autofill::prefs::IsProfileAutofillEnabled(pref_service_);
}
bool PersonalDataManager::IsAutofillCreditCardEnabled() const {
- return pref_service_->GetBoolean(prefs::kAutofillCreditCardEnabled);
+ return ::autofill::prefs::IsCreditCardAutofillEnabled(pref_service_);
}
bool PersonalDataManager::IsAutofillWalletImportEnabled() const {
- return pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled);
+ return ::autofill::prefs::IsPaymentsIntegrationEnabled(pref_service_);
}
bool PersonalDataManager::ShouldSuggestServerCards() const {
@@ -1437,27 +1493,26 @@ std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
}
void PersonalDataManager::SetPrefService(PrefService* pref_service) {
- enabled_pref_ = std::make_unique<BooleanPrefMember>();
wallet_enabled_pref_ = std::make_unique<BooleanPrefMember>();
profile_enabled_pref_ = std::make_unique<BooleanPrefMember>();
credit_card_enabled_pref_ = std::make_unique<BooleanPrefMember>();
pref_service_ = pref_service;
- // |pref_service_| can be nullptr in tests.
+ // |pref_service_| can be nullptr in tests. Using base::Unretained(this) is
+ // safe because observer instances are destroyed once |this| is destroyed.
if (pref_service_) {
credit_card_enabled_pref_->Init(
prefs::kAutofillCreditCardEnabled, pref_service_,
- base::Bind(&PersonalDataManager::Refresh, base::Unretained(this)));
+ base::BindRepeating(&PersonalDataManager::EnableAutofillPrefChanged,
+ base::Unretained(this)));
profile_enabled_pref_->Init(
prefs::kAutofillProfileEnabled, pref_service_,
- base::BindRepeating(&PersonalDataManager::Refresh,
+ base::BindRepeating(&PersonalDataManager::EnableAutofillPrefChanged,
base::Unretained(this)));
- enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
- base::Bind(&PersonalDataManager::EnabledPrefChanged,
- base::Unretained(this)));
wallet_enabled_pref_->Init(
prefs::kAutofillWalletImportEnabled, pref_service_,
- base::Bind(&PersonalDataManager::EnabledPrefChanged,
- base::Unretained(this)));
+ base::BindRepeating(
+ &PersonalDataManager::EnableWalletIntegrationPrefChanged,
+ base::Unretained(this)));
}
}
@@ -1495,6 +1550,60 @@ void PersonalDataManager::ClearCreditCardNonSettingsOrigins() {
Refresh();
}
+void PersonalDataManager::MoveJapanCityToStreetAddress() {
+ if (!database_helper_->GetLocalDatabase())
+ return;
+
+ // Don't run if the migration has already been performed.
+ if (pref_service_->GetBoolean(prefs::kAutofillJapanCityFieldMigrated))
+ return;
+
+ bool has_updated = false;
+ base::string16 japan_country_code = base::ASCIIToUTF16("JP");
+ base::string16 line_separator = base::ASCIIToUTF16("\n");
+ for (AutofillProfile* profile : GetProfiles()) {
+ base::string16 country_code = profile->GetRawInfo(ADDRESS_HOME_COUNTRY);
+ base::string16 city = profile->GetRawInfo(ADDRESS_HOME_CITY);
+ if (country_code == japan_country_code && !city.empty()) {
+ base::string16 street_address =
+ profile->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS);
+ street_address = street_address.empty()
+ ? city
+ : street_address + line_separator + city;
+ profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, street_address);
+ profile->SetRawInfo(ADDRESS_HOME_CITY, base::EmptyString16());
+
+ // Make the update.
+ database_helper_->GetLocalDatabase()->UpdateAutofillProfile(*profile);
+ has_updated = true;
+ }
+ }
+
+ // 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);
+}
+
+const ProfileValidityMap& PersonalDataManager::GetProfileValidityByGUID(
+ std::string& guid) {
+ static const ProfileValidityMap& empty_validity_map = ProfileValidityMap();
+ if (!synced_profile_validity_) {
+ synced_profile_validity_ = std::make_unique<UserProfileValidityMap>();
+ if (!synced_profile_validity_->ParseFromString(
+ ::autofill::prefs::GetAllProfilesValidityMapsEncodedString(
+ pref_service_)))
+ return empty_validity_map;
+ }
+ auto it = synced_profile_validity_->profile_validity().find(guid);
+ if (it != synced_profile_validity_->profile_validity().end())
+ return it->second;
+ return empty_validity_map;
+}
+
// TODO(crbug.com/618448): Refactor MergeProfile to not depend on class
// variables.
std::string PersonalDataManager::MergeProfile(
@@ -1634,9 +1743,7 @@ void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
return;
// Remove empty profiles from input.
- profiles->erase(std::remove_if(profiles->begin(), profiles->end(),
- IsEmptyFunctor<AutofillProfile>(app_locale_)),
- profiles->end());
+ base::EraseIf(*profiles, IsEmptyFunctor<AutofillProfile>(app_locale_));
if (!database_helper_->GetLocalDatabase())
return;
@@ -1677,9 +1784,7 @@ void PersonalDataManager::SetCreditCards(
return;
// Remove empty credit cards from input.
- credit_cards->erase(std::remove_if(credit_cards->begin(), credit_cards->end(),
- IsEmptyFunctor<CreditCard>(app_locale_)),
- credit_cards->end());
+ base::EraseIf(*credit_cards, IsEmptyFunctor<CreditCard>(app_locale_));
if (!database_helper_->GetLocalDatabase())
return;
@@ -1773,10 +1878,23 @@ void PersonalDataManager::CancelPendingServerQueries() {
if (pending_server_creditcards_query_) {
CancelPendingServerQuery(&pending_server_creditcards_query_);
}
+ if (pending_customer_data_query_) {
+ CancelPendingServerQuery(&pending_customer_data_query_);
+ }
// TODO(crbug.com/864519): also cancel the server addresses query once they
// use the account storage.
}
+void PersonalDataManager::LoadPaymentsCustomerData() {
+ if (!database_helper_->GetServerDatabase())
+ return;
+
+ CancelPendingServerQuery(&pending_customer_data_query_);
+
+ pending_customer_data_query_ =
+ database_helper_->GetServerDatabase()->GetPaymentsCustomerData(this);
+}
+
std::string PersonalDataManager::SaveImportedProfile(
const AutofillProfile& imported_profile) {
if (is_off_the_record_)
@@ -1904,14 +2022,20 @@ std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
return std::string();
}
-void PersonalDataManager::EnabledPrefChanged() {
- default_country_code_.clear();
- if (!pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
+void PersonalDataManager::EnableWalletIntegrationPrefChanged() {
+ if (!prefs::IsPaymentsIntegrationEnabled(pref_service_)) {
// Re-mask all server cards when the user turns off wallet card
// integration.
ResetFullServerCards();
+ NotifyPersonalDataChanged();
}
- NotifyPersonalDataChanged();
+}
+
+void PersonalDataManager::EnableAutofillPrefChanged() {
+ default_country_code_.clear();
+
+ // Refresh our local cache and send notifications to observers.
+ Refresh();
}
bool PersonalDataManager::IsKnownCard(const CreditCard& credit_card) {
@@ -1940,6 +2064,20 @@ bool PersonalDataManager::IsKnownCard(const CreditCard& credit_card) {
return false;
}
+bool PersonalDataManager::IsServerCard(const CreditCard* credit_card) const {
+ // Check whether the current card itself is a server card.
+ if (credit_card->record_type() != autofill::CreditCard::LOCAL_CARD)
+ return true;
+
+ std::vector<CreditCard*> server_credit_cards = GetServerCreditCards();
+ // Check whether the current card is already uploaded.
+ for (const CreditCard* server_card : server_credit_cards) {
+ if (credit_card->HasSameNumberAs(*server_card))
+ return true;
+ }
+ return false;
+}
+
std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards(
const AutofillType& type,
const base::string16& field_contents,
@@ -2373,7 +2511,7 @@ void PersonalDataManager::MaybeCreateTestAddresses() {
return;
has_created_test_addresses_ = true;
- if (!base::FeatureList::IsEnabled(kAutofillCreateDataForTest))
+ if (!base::FeatureList::IsEnabled(features::kAutofillCreateDataForTest))
return;
AddProfile(CreateBasicTestAddress(app_locale_));
@@ -2386,7 +2524,7 @@ void PersonalDataManager::MaybeCreateTestCreditCards() {
return;
has_created_test_credit_cards_ = true;
- if (!base::FeatureList::IsEnabled(kAutofillCreateDataForTest))
+ if (!base::FeatureList::IsEnabled(features::kAutofillCreateDataForTest))
return;
AddCreditCard(CreateBasicTestCreditCard(app_locale_));
@@ -2403,7 +2541,8 @@ bool PersonalDataManager::IsCreditCardDeletable(CreditCard* card) {
}
bool PersonalDataManager::DeleteDisusedCreditCards() {
- if (!base::FeatureList::IsEnabled(kAutofillDeleteDisusedCreditCards)) {
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillDeleteDisusedCreditCards)) {
return false;
}
@@ -2465,7 +2604,8 @@ bool PersonalDataManager::IsAddressDeletable(
}
bool PersonalDataManager::DeleteDisusedAddresses() {
- if (!base::FeatureList::IsEnabled(kAutofillDeleteDisusedAddresses)) {
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillDeleteDisusedAddresses)) {
DVLOG(1) << "Deletion is disabled";
return false;
}
@@ -2527,6 +2667,7 @@ void PersonalDataManager::ApplyAddressFixesAndCleanups() {
DeleteDisusedAddresses(); // Once per major version, otherwise NOP.
MaybeCreateTestAddresses(); // Once per user profile startup.
ClearProfileNonSettingsOrigins(); // Ran everytime it is called.
+ MoveJapanCityToStreetAddress(); // One-time fix, otherwise NOP.
}
void PersonalDataManager::ApplyCardFixesAndCleanups() {
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index b79c908f5a0..59718eb1f75 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -18,15 +18,19 @@
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/account_info_getter.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
+#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
+#include "components/signin/core/browser/account_info.h"
#include "components/sync/driver/sync_service_observer.h"
#include "components/webdata/common/web_data_service_consumer.h"
@@ -66,7 +70,8 @@ extern const char kFrecencyFieldTrialLimitParam[];
class PersonalDataManager : public KeyedService,
public WebDataServiceConsumer,
public AutofillWebDataServiceObserverOnUISequence,
- public syncer::SyncServiceObserver {
+ public syncer::SyncServiceObserver,
+ public AccountInfoGetter {
public:
explicit PersonalDataManager(const std::string& app_locale);
~PersonalDataManager() override;
@@ -93,13 +98,6 @@ class PersonalDataManager : public KeyedService,
// not be started, but it's preferences can be queried.
virtual void OnSyncServiceInitialized(syncer::SyncService* sync_service);
- // Set whether this should use the passed in account storage for server
- // cards. If false, this will use the profile_storage.
- // It's an error to call this if no account storage was passed in at
- // initialization time.
- void SetUseAccountStorageForServerCards(
- bool use_account_storage_for_server_cards);
-
// WebDataServiceConsumer:
void OnWebDataServiceRequestDone(
WebDataServiceBase::Handle h,
@@ -113,6 +111,10 @@ class PersonalDataManager : public KeyedService,
void OnStateChanged(syncer::SyncService* sync) override;
void OnSyncShutdown(syncer::SyncService* sync) override;
+ // AccountInfoGetter:
+ AccountInfo GetAccountInfoForPaymentsServer() const override;
+ bool IsSyncFeatureEnabled() const override;
+
// Adds a listener to be notified of PersonalDataManager events.
virtual void AddObserver(PersonalDataManagerObserver* observer);
@@ -227,6 +229,9 @@ class PersonalDataManager : public KeyedService,
// Returns all credit cards, server and local.
virtual std::vector<CreditCard*> GetCreditCards() const;
+ // Returns the Payments customer data. Returns nullptr if no data is present.
+ virtual PaymentsCustomerData* GetPaymentsCustomerData() const;
+
// Returns the profiles to suggest to the user, ordered by frecency.
std::vector<AutofillProfile*> GetProfilesToSuggest() const;
@@ -335,6 +340,9 @@ class PersonalDataManager : public KeyedService,
// |credit_card| is equal to any masked server card known by the browser.
bool IsKnownCard(const CreditCard& credit_card);
+ // Check whether a card is a server card or has a duplicated server card.
+ bool IsServerCard(const CreditCard* credit_card) const;
+
// Sets the value that can skip the checks to see if we are syncing in a test.
void SetSyncingForTest(bool is_syncing_for_test) {
is_syncing_for_test_ = is_syncing_for_test;
@@ -415,6 +423,9 @@ class PersonalDataManager : public KeyedService,
ClearProfileNonSettingsOrigins);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
ClearCreditCardNonSettingsOrigins);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ MoveJapanCityToStreetAddress);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, RequestProfileValidity);
friend class autofill::AutofillInteractiveTest;
friend class autofill::PersonalDataManagerFactory;
@@ -457,6 +468,9 @@ class PersonalDataManager : public KeyedService,
// Loads the saved credit cards from the web database.
virtual void LoadCreditCards();
+ // Loads the payments customer data from the web database.
+ virtual void LoadPaymentsCustomerData();
+
// Cancels a pending query to the local web database. |handle| is a pointer
// to the query handle.
void CancelPendingLocalQuery(WebDataServiceBase::Handle* handle);
@@ -503,11 +517,20 @@ class PersonalDataManager : public KeyedService,
void ClearProfileNonSettingsOrigins();
void ClearCreditCardNonSettingsOrigins();
+ // Appends the value of the city field of a JP address to its street address
+ // field, separated by a newline, and clears the city field.
+ // TODO(rouslan): Remove this migration in or after October 2019. See bug:
+ // https://crbug.com/871301
+ void MoveJapanCityToStreetAddress();
+
+ // Get the profiles fields validity map by |guid|.
+ const ProfileValidityMap& GetProfileValidityByGUID(std::string& guid);
+
// Decides which database type to use for server and local cards.
std::unique_ptr<PersonalDatabaseHelper> database_helper_;
// True if personal data has been loaded from the web database.
- bool is_data_loaded_;
+ bool is_data_loaded_ = false;
// The loaded web profiles. These are constructed from entries on web pages
// and from manually editing in the settings.
@@ -516,6 +539,9 @@ class PersonalDataManager : public KeyedService,
// Profiles read from the user's account stored on the server.
mutable std::vector<std::unique_ptr<AutofillProfile>> server_profiles_;
+ // Stores the PaymentsCustomerData obtained from the database.
+ std::unique_ptr<PaymentsCustomerData> payments_customer_data_;
+
// Storage for web profiles. Contents are weak references. Lifetime managed
// by |web_profiles_|.
mutable std::vector<AutofillProfile*> profiles_;
@@ -528,13 +554,14 @@ class PersonalDataManager : public KeyedService,
// is queried on another sequence, we record the query handle until we
// get called back. We store handles for both profile and credit card queries
// so they can be loaded at the same time.
- WebDataServiceBase::Handle pending_profiles_query_;
- WebDataServiceBase::Handle pending_server_profiles_query_;
- WebDataServiceBase::Handle pending_creditcards_query_;
- WebDataServiceBase::Handle pending_server_creditcards_query_;
+ WebDataServiceBase::Handle pending_profiles_query_ = 0;
+ WebDataServiceBase::Handle pending_server_profiles_query_ = 0;
+ WebDataServiceBase::Handle pending_creditcards_query_ = 0;
+ WebDataServiceBase::Handle pending_server_creditcards_query_ = 0;
+ WebDataServiceBase::Handle pending_customer_data_query_ = 0;
// The observers.
- base::ObserverList<PersonalDataManagerObserver> observers_;
+ base::ObserverList<PersonalDataManagerObserver>::Unchecked observers_;
private:
// Saves |imported_credit_card| to the WebDB if it exists. Returns the guid of
@@ -546,8 +573,12 @@ class PersonalDataManager : public KeyedService,
// Prefers verified profiles over unverified ones.
std::string MostCommonCountryCodeFromProfiles() const;
- // Called when the value of prefs::kAutofillEnabled changes.
- void EnabledPrefChanged();
+ // Called when the value of prefs::kAutofillWalletImportEnabled changes.
+ void EnableWalletIntegrationPrefChanged();
+
+ // Called when the value of prefs::kAutofillCreditCardEnabled or
+ // prefs::kAutofillProfileEnabled changes.
+ void EnableAutofillPrefChanged();
// Returns credit card suggestions based on the |cards_to_suggest| and the
// |type| and |field_contents| of the credit card field.
@@ -655,29 +686,39 @@ class PersonalDataManager : public KeyedService,
// Applies various fixes and cleanups on autofill credit cards.
void ApplyCardFixesAndCleanups();
+ // Resets |synced_profile_validity_|.
+ void ResetProfileValidity() { synced_profile_validity_.reset(); };
+
const std::string app_locale_;
// The default country code for new addresses.
mutable std::string default_country_code_;
// The PrefService that this instance uses. Must outlive this instance.
- PrefService* pref_service_;
+ PrefService* pref_service_ = nullptr;
+
+ // Pref registrar for managing the change observers.
+ PrefChangeRegistrar pref_registrar_;
+
+ // Profiles validity read from the prefs. They are kept updated by
+ // observing changes in pref_services.
+ std::unique_ptr<UserProfileValidityMap> synced_profile_validity_;
// The identity manager that this instance uses. Must outlive this instance.
- identity::IdentityManager* identity_manager_;
+ identity::IdentityManager* identity_manager_ = nullptr;
// The sync service this instances uses. Must outlive this instance.
- syncer::SyncService* sync_service_;
+ syncer::SyncService* sync_service_ = nullptr;
// Whether the user is currently operating in an off-the-record context.
// Default value is false.
- bool is_off_the_record_;
+ bool is_off_the_record_ = false;
// Whether we have already logged the stored profile metrics this session.
- mutable bool has_logged_stored_profile_metrics_;
+ mutable bool has_logged_stored_profile_metrics_ = false;
// Whether we have already logged the stored credit card metrics this session.
- mutable bool has_logged_stored_credit_card_metrics_;
+ mutable bool has_logged_stored_credit_card_metrics_ = false;
// An observer to listen for changes to prefs::kAutofillCreditCardEnabled.
std::unique_ptr<BooleanPrefMember> credit_card_enabled_pref_;
@@ -685,9 +726,6 @@ class PersonalDataManager : public KeyedService,
// An observer to listen for changes to prefs::kAutofillProfileEnabled.
std::unique_ptr<BooleanPrefMember> profile_enabled_pref_;
- // An observer to listen for changes to prefs::kAutofillEnabled.
- std::unique_ptr<BooleanPrefMember> enabled_pref_;
-
// An observer to listen for changes to prefs::kAutofillWalletImportEnabled.
std::unique_ptr<BooleanPrefMember> wallet_enabled_pref_;
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 ad871584de3..5cc8958d85b 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -44,7 +44,7 @@
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/os_crypt/os_crypt_mocker.h"
@@ -112,7 +112,12 @@ void ExpectSameElements(const std::vector<T*>& expectations,
class PersonalDataManagerTestBase {
protected:
- PersonalDataManagerTestBase() : profile_autofill_table_(nullptr) {}
+ PersonalDataManagerTestBase() : profile_autofill_table_(nullptr) {
+ // Enable account storage by default, some tests will override this to be
+ // false.
+ scoped_features_.InitAndEnableFeature(
+ features::kAutofillEnableAccountWalletStorage);
+ }
void SetUpTest() {
OSCryptMocker::SetUp();
@@ -174,9 +179,9 @@ class PersonalDataManagerTestBase {
: nullptr,
prefs_.get(), identity_test_env_.identity_manager(), is_incognito);
personal_data_->AddObserver(&personal_data_observer_);
+ sync_service_.SetIsAuthenticatedAccountPrimary(!use_account_server_storage);
personal_data_->OnSyncServiceInitialized(&sync_service_);
- personal_data_->SetUseAccountStorageForServerCards(
- use_account_server_storage);
+ personal_data_->OnStateChanged(&sync_service_);
// Verify that the web database has been updated and the notification sent.
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
@@ -368,6 +373,7 @@ class PersonalDataManagerTestBase {
AutofillTable* account_autofill_table_; // weak ref
PersonalDataLoadedObserverMock personal_data_observer_;
std::unique_ptr<PersonalDataManager> personal_data_;
+ base::test::ScopedFeatureList scoped_features_;
};
class PersonalDataManagerTest : public PersonalDataManagerTestBase,
@@ -1576,17 +1582,16 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeIsCached) {
EXPECT_EQ(default_country,
personal_data_->GetDefaultCountryCodeForNewAddress());
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(2);
-
// Disabling Autofill blows away this cache and shouldn't account for Autofill
// profiles.
- prefs_->SetBoolean(prefs::kAutofillEnabled, false);
+ prefs::SetAutofillEnabled(prefs_.get(), false);
+ WaitForOnPersonalDataChanged();
EXPECT_EQ(default_country,
personal_data_->GetDefaultCountryCodeForNewAddress());
// Enabling Autofill blows away the cached value and should reflect the new
// value (accounting for profiles).
- prefs_->SetBoolean(prefs::kAutofillEnabled, true);
+ prefs::SetAutofillEnabled(prefs_.get(), true);
EXPECT_EQ(base::UTF16ToUTF8(moose.GetRawInfo(ADDRESS_HOME_COUNTRY)),
personal_data_->GetDefaultCountryCodeForNewAddress());
}
@@ -1874,7 +1879,8 @@ TEST_F(PersonalDataManagerTest,
ResetPersonalDataManager(USER_MODE_NORMAL);
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillSuppressDisusedAddresses);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillSuppressDisusedAddresses);
// Query with empty string only returns profile2.
{
@@ -1917,7 +1923,8 @@ TEST_F(PersonalDataManagerTest,
// When suppression is disabled, returns all suggestions.
{
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndDisableFeature(kAutofillSuppressDisusedAddresses);
+ scoped_features.InitAndDisableFeature(
+ features::kAutofillSuppressDisusedAddresses);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(ADDRESS_HOME_STREET_ADDRESS), base::string16(), false,
std::vector<ServerFieldType>());
@@ -1954,7 +1961,8 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_InvalidData) {
{
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndDisableFeature(kAutofillSuggestInvalidProfileData);
+ scoped_features.InitAndDisableFeature(
+ features::kAutofillSuggestInvalidProfileData);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(PHONE_HOME_WHOLE_NUMBER), base::string16(), false,
std::vector<ServerFieldType>());
@@ -1967,7 +1975,8 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_InvalidData) {
{
base::HistogramTester histogram_tester;
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillSuggestInvalidProfileData);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillSuggestInvalidProfileData);
std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
AutofillType(PHONE_HOME_WHOLE_NUMBER), base::string16(), false,
std::vector<ServerFieldType>());
@@ -2008,9 +2017,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfileAutofillDisabled) {
profile_autofill_table_->SetServerProfiles(GetServerProfiles);
// Disable Profile autofill.
- personal_data_->pref_service_->SetBoolean(prefs::kAutofillProfileEnabled,
- false);
- personal_data_->Refresh();
+ prefs::SetProfileAutofillEnabled(personal_data_->pref_service_, false);
WaitForOnPersonalDataChanged();
personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
@@ -2062,9 +2069,8 @@ TEST_F(PersonalDataManagerTest,
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetProfilesToSuggest().size());
- // Disable CProfile autofill.
- personal_data_->pref_service_->SetBoolean(prefs::kAutofillProfileEnabled,
- false);
+ // Disable Profile autofill.
+ prefs::SetProfileAutofillEnabled(personal_data_->pref_service_, false);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -2082,8 +2088,7 @@ TEST_F(PersonalDataManagerTest,
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_NoProfilesAddedIfDisabled) {
// Disable Profile autofill.
- personal_data_->pref_service_->SetBoolean(prefs::kAutofillProfileEnabled,
- false);
+ prefs::SetProfileAutofillEnabled(personal_data_->pref_service_, false);
// Add a local profile.
AutofillProfile local_profile(base::GenerateGUID(), test::kEmptyOrigin);
@@ -2193,6 +2198,102 @@ TEST_F(PersonalDataManagerTest, IsKnownCard_LastFourDoesNotMatch) {
ASSERT_FALSE(personal_data_->IsKnownCard(cardToCompare));
}
+TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfFullServerCard) {
+ // Add a full server card.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b459"));
+ test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
+ "4234567890122110" /* Visa */, "12", "2999", "1");
+
+ SetServerCards(server_cards);
+
+ // Add a dupe local card of a full server card.
+ CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ test::kEmptyOrigin);
+ test::SetCreditCardInfo(&local_card, "Emmet Dalton",
+ "4234 5678 9012 2110" /* Visa */, "12", "2999", "1");
+ personal_data_->AddCreditCard(local_card);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(base::ASCIIToUTF16("4234 5678 9012 2110") /* Visa */);
+ ASSERT_TRUE(personal_data_->IsServerCard(&cardToCompare));
+ ASSERT_TRUE(personal_data_->IsServerCard(&local_card));
+}
+
+TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfMaskedServerCard) {
+ // Add a masked server card.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
+ "2110" /* last 4 digits */, "12", "2999", "1");
+ server_cards.back().SetNetworkForMaskedCard(kVisaCard);
+
+ SetServerCards(server_cards);
+
+ // Add a dupe local card of a full server card.
+ CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ test::kEmptyOrigin);
+ test::SetCreditCardInfo(&local_card, "Emmet Dalton",
+ "4234 5678 9012 2110" /* Visa */, "12", "2999", "1");
+ personal_data_->AddCreditCard(local_card);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(base::ASCIIToUTF16("4234 5678 9012 2110") /* Visa */);
+ ASSERT_TRUE(personal_data_->IsServerCard(&cardToCompare));
+ ASSERT_TRUE(personal_data_->IsServerCard(&local_card));
+}
+
+TEST_F(PersonalDataManagerTest, IsServerCard_AlreadyServerCard) {
+ std::vector<CreditCard> server_cards;
+ // Create a full server card.
+ CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789");
+ test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
+ "4234567890123456" /* Visa */, "01", "2999", "1");
+ server_cards.push_back(full_server_card);
+ // Create a masked server card.
+ CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
+ test::SetCreditCardInfo(&masked_card, "Homer Simpson", "2110" /* Visa */,
+ "01", "2999", "1");
+ masked_card.SetNetworkForMaskedCard(kVisaCard);
+ server_cards.push_back(masked_card);
+
+ SetServerCards(server_cards);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ ASSERT_TRUE(personal_data_->IsServerCard(&full_server_card));
+ ASSERT_TRUE(personal_data_->IsServerCard(&masked_card));
+}
+
+TEST_F(PersonalDataManagerTest, IsServerCard_UniqueLocalCard) {
+ // Add a unique local card.
+ CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
+ test::kEmptyOrigin);
+ test::SetCreditCardInfo(&local_card, "Homer Simpson",
+ "4234567890123456" /* Visa */, "01", "2999", "1");
+ personal_data_->AddCreditCard(local_card);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ ASSERT_FALSE(personal_data_->IsServerCard(&local_card));
+}
+
// Test that a masked server card is not suggested if more that six numbers have
// been typed in the field.
TEST_F(PersonalDataManagerTest,
@@ -2317,11 +2418,11 @@ TEST_F(PersonalDataManagerTest,
base::TimeDelta::FromDays(1));
SetServerCards(server_cards);
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
// Disable Credit card autofill.
- personal_data_->pref_service_->SetBoolean(prefs::kAutofillCreditCardEnabled,
- false);
- personal_data_->Refresh();
+ prefs::SetCreditCardAutofillEnabled(personal_data_->pref_service_, false);
WaitForOnPersonalDataChanged();
// Check that profiles were saved.
@@ -2372,8 +2473,7 @@ TEST_F(PersonalDataManagerTest,
EXPECT_EQ(5U, personal_data_->GetCreditCards().size());
// Disable Credit card autofill.
- personal_data_->pref_service_->SetBoolean(prefs::kAutofillCreditCardEnabled,
- false);
+ prefs::SetCreditCardAutofillEnabled(personal_data_->pref_service_, false);
// Reload the database.
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -2395,8 +2495,7 @@ TEST_F(PersonalDataManagerTest,
TEST_F(PersonalDataManagerTest,
GetCreditCardSuggestions_NoCreditCardsAddedIfDisabled) {
// Disable Profile autofill.
- personal_data_->pref_service_->SetBoolean(prefs::kAutofillCreditCardEnabled,
- false);
+ prefs::SetCreditCardAutofillEnabled(personal_data_->pref_service_, false);
// Add a local credit card.
CreditCard credit_card("002149C1-EE28-4213-A3B9-DA243FFF021B",
@@ -2516,7 +2615,8 @@ TEST_F(PersonalDataManagerTest,
// Verify no suppression if feature is disabled.
{
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndDisableFeature(kAutofillSuppressDisusedCreditCards);
+ scoped_features.InitAndDisableFeature(
+ features::kAutofillSuppressDisusedCreditCards);
std::vector<Suggestion> suggestions =
personal_data_->GetCreditCardSuggestions(
@@ -2530,7 +2630,8 @@ TEST_F(PersonalDataManagerTest,
}
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillSuppressDisusedCreditCards);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillSuppressDisusedCreditCards);
// Query with empty string only returns card0 and card1. Note expired
// masked card2 is not suggested on empty fields.
@@ -4531,8 +4632,9 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_OncePerVersion) {
// Tests that DeleteDisusedAddresses is not run if the feature is disabled.
TEST_F(PersonalDataManagerTest, DeleteDisusedAddresses_DoNothingWhenDisabled) {
- // Make sure feature is disabled by default.
- EXPECT_FALSE(base::FeatureList::IsEnabled(kAutofillDeleteDisusedAddresses));
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndDisableFeature(
+ features::kAutofillDeleteDisusedAddresses);
CreateDeletableDisusedProfile();
@@ -4549,7 +4651,8 @@ TEST_F(PersonalDataManagerTest, DeleteDisusedAddresses_DoNothingWhenDisabled) {
TEST_F(PersonalDataManagerTest, DeleteDisusedAddresses_OncePerVersion) {
// Enable the feature.
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedAddresses);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillDeleteDisusedAddresses);
CreateDeletableDisusedProfile();
@@ -4575,7 +4678,8 @@ TEST_F(PersonalDataManagerTest,
DeleteDisusedAddresses_DeleteDesiredAddressesOnly) {
// Enable the feature.
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedAddresses);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillDeleteDisusedAddresses);
auto now = AutofillClock::Now();
@@ -4658,8 +4762,9 @@ TEST_F(PersonalDataManagerTest,
// Tests that DeleteDisusedCreditCards is not run if the feature is disabled.
TEST_F(PersonalDataManagerTest,
DeleteDisusedCreditCards_DoNothingWhenDisabled) {
- // Make sure feature is disabled by default.
- EXPECT_FALSE(base::FeatureList::IsEnabled(kAutofillDeleteDisusedCreditCards));
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndDisableFeature(
+ features::kAutofillDeleteDisusedCreditCards);
CreateDeletableExpiredAndDisusedCreditCard();
@@ -4676,7 +4781,8 @@ TEST_F(PersonalDataManagerTest,
TEST_F(PersonalDataManagerTest, DeleteDisusedCreditCards_OncePerVersion) {
// Enable the feature.
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedCreditCards);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillDeleteDisusedCreditCards);
CreateDeletableExpiredAndDisusedCreditCard();
@@ -4702,7 +4808,8 @@ TEST_F(PersonalDataManagerTest,
DeleteDisusedCreditCards_OnlyDeleteExpiredDisusedLocalCards) {
// Enable the feature.
base::test::ScopedFeatureList scoped_features;
- scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedCreditCards);
+ scoped_features.InitAndEnableFeature(
+ features::kAutofillDeleteDisusedCreditCards);
const char kHistogramName[] = "Autofill.CreditCardsDeletedForDisuse";
auto now = AutofillClock::Now();
@@ -5801,7 +5908,7 @@ TEST_F(PersonalDataManagerTest, CreateDataForTest) {
// Turn on test data creation for the rest of this scope.
base::test::ScopedFeatureList enabled;
- enabled.InitAndEnableFeature(kAutofillCreateDataForTest);
+ enabled.InitAndEnableFeature(features::kAutofillCreateDataForTest);
// Reloading the test profile should result in test data being created.
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -6099,6 +6206,8 @@ TEST_F(PersonalDataManagerTest,
// Call OnSyncServiceInitialized with a sync service in auth error.
TestSyncService sync_service;
+ sync_service.SetIsAuthenticatedAccountPrimary(
+ /*is_authenticated_account_primary=*/false);
sync_service.SetInAuthError(true);
personal_data_->OnSyncServiceInitialized(&sync_service);
WaitForOnPersonalDataChanged();
@@ -6271,6 +6380,105 @@ TEST_F(PersonalDataManagerTest, ClearCreditCardNonSettingsOrigins) {
personal_data_->GetCreditCardsToSuggest(false)[3]->origin());
}
+// Tests that all city fields in a Japan profile are moved to the street address
+// field.
+TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) {
+ // A US profile with both street address and a city.
+ std::string guid0 = base::GenerateGUID();
+ {
+ AutofillProfile profile0(guid0, test::kEmptyOrigin);
+ test::SetProfileInfo(&profile0, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "", "742. Evergreen Terrace",
+ "", "Springfield", "IL", "91601", "US", "");
+ personal_data_->AddProfile(profile0);
+ }
+
+ // A JP profile with both street address and a city.
+ std::string guid1 = base::GenerateGUID();
+ {
+ AutofillProfile profile1(guid1, test::kEmptyOrigin);
+ test::SetProfileInfo(&profile1, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "", "742. Evergreen Terrace",
+ "", "Springfield", "IL", "91601", "JP", "");
+ personal_data_->AddProfile(profile1);
+ }
+
+ // A JP profile with only a city.
+ std::string guid2 = base::GenerateGUID();
+ {
+ AutofillProfile profile2(guid2, test::kEmptyOrigin);
+ test::SetProfileInfo(&profile2, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "", "", "", "Springfield",
+ "IL", "91601", "JP", "");
+ personal_data_->AddProfile(profile2);
+ }
+
+ // A JP profile with only a street address.
+ std::string guid3 = base::GenerateGUID();
+ {
+ AutofillProfile profile3(guid3, test::kEmptyOrigin);
+ test::SetProfileInfo(&profile3, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "", "742. Evergreen Terrace",
+ "", "", "IL", "91601", "JP", "");
+ personal_data_->AddProfile(profile3);
+ }
+
+ // A JP profile with neither a street address nor a city.
+ std::string guid4 = base::GenerateGUID();
+ {
+ AutofillProfile profile4(guid4, test::kEmptyOrigin);
+ test::SetProfileInfo(&profile4, "Homer", "J", "Simpson",
+ "homer.simpson@abc.com", "", "", "", "", "IL", "91601",
+ "JP", "");
+ personal_data_->AddProfile(profile4);
+ }
+
+ WaitForOnPersonalDataChanged();
+
+ personal_data_->MoveJapanCityToStreetAddress();
+
+ WaitForOnPersonalDataChanged();
+
+ {
+ AutofillProfile* profile0 = personal_data_->GetProfileByGUID(guid0);
+ EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace"),
+ profile0->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(base::ASCIIToUTF16("Springfield"),
+ profile0->GetRawInfo(ADDRESS_HOME_CITY));
+ }
+
+ {
+ AutofillProfile* profile1 = personal_data_->GetProfileByGUID(guid1);
+ EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace\nSpringfield"),
+ profile1->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace"),
+ profile1->GetRawInfo(ADDRESS_HOME_LINE1));
+ EXPECT_EQ(base::ASCIIToUTF16("Springfield"),
+ profile1->GetRawInfo(ADDRESS_HOME_LINE2));
+ EXPECT_TRUE(profile1->GetRawInfo(ADDRESS_HOME_CITY).empty());
+ }
+
+ {
+ AutofillProfile* profile2 = personal_data_->GetProfileByGUID(guid2);
+ EXPECT_EQ(base::ASCIIToUTF16("Springfield"),
+ profile2->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_TRUE(profile2->GetRawInfo(ADDRESS_HOME_CITY).empty());
+ }
+
+ {
+ AutofillProfile* profile3 = personal_data_->GetProfileByGUID(guid3);
+ EXPECT_EQ(base::ASCIIToUTF16("742. Evergreen Terrace"),
+ profile3->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_TRUE(profile3->GetRawInfo(ADDRESS_HOME_CITY).empty());
+ }
+
+ {
+ AutofillProfile* profile4 = personal_data_->GetProfileByGUID(guid4);
+ EXPECT_TRUE(profile4->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS).empty());
+ EXPECT_TRUE(profile4->GetRawInfo(ADDRESS_HOME_CITY).empty());
+ }
+}
+
// Tests that all the non settings origins of autofill profiles are cleared even
// if sync is disabled.
TEST_F(
@@ -6353,6 +6561,42 @@ TEST_F(PersonalDataManagerTest, UsePersistentServerStorage) {
EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
}
+// Verify that PDM can switch at runtime between the different storages.
+TEST_F(PersonalDataManagerTest, SwitchServerStorages) {
+ // Start with account storage.
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+ SetUpThreeCardTypes();
+
+ // Check that we do have 2 server cards, as expected.
+ ASSERT_EQ(2U, personal_data_->GetServerCreditCards().size());
+
+ // Switch to persistent storage.
+ sync_service_.SetIsAuthenticatedAccountPrimary(true);
+ personal_data_->OnStateChanged(&sync_service_);
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(0U, personal_data_->GetServerCreditCards().size());
+
+ CreditCard server_card;
+ test::SetCreditCardInfo(&server_card, "Server Card",
+ "4234567890123456", // Visa
+ "04", "2999", "1");
+ server_card.set_guid("00000000-0000-0000-0000-000000000007");
+ server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
+ server_card.set_server_id("server_id");
+ personal_data_->AddFullServerCreditCard(server_card);
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(1U, personal_data_->GetServerCreditCards().size());
+
+ // Switch back to the account storage.
+ sync_service_.SetIsAuthenticatedAccountPrimary(false);
+ personal_data_->OnStateChanged(&sync_service_);
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size());
+}
+
// Sanity check that the mode where we use the regular, persistent storage for
// cards still works.
TEST_F(PersonalDataManagerTest, UseCorrectStorageForDifferentCards) {
@@ -6413,4 +6657,132 @@ TEST_F(PersonalDataManagerTest, UseCorrectStorageForDifferentCards) {
EXPECT_EQ(profile, *profiles[0]);
}
+// Requests profiles fields validities: empty profiles, non-existent profiles,
+// and normal ones.
+TEST_F(PersonalDataManagerTest, RequestProfileValidity) {
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+
+ ProfileValidityMap profile_validity_map;
+ UserProfileValidityMap user_profile_validity_map;
+ std::string autofill_profile_validity;
+
+ // Empty validity map.
+ ASSERT_TRUE(
+ user_profile_validity_map.SerializeToString(&autofill_profile_validity));
+ personal_data_->pref_service_->SetString(prefs::kAutofillProfileValidity,
+ autofill_profile_validity);
+
+ std::string guid = "00000000-0000-0000-0000-0000000000001";
+ EXPECT_TRUE(personal_data_->GetProfileValidityByGUID(guid)
+ .field_validity_states()
+ .empty());
+
+ // Non-empty validity map.
+ std::vector<ServerFieldType> types = {
+ ADDRESS_HOME_LINE1, ADDRESS_HOME_STATE, ADDRESS_HOME_COUNTRY,
+ EMAIL_ADDRESS, ADDRESS_HOME_ZIP, NAME_FULL};
+ std::vector<AutofillProfile::ValidityState> states = {
+ AutofillProfile::UNSUPPORTED, AutofillProfile::EMPTY,
+ AutofillProfile::INVALID, AutofillProfile::VALID,
+ AutofillProfile::UNVALIDATED, AutofillProfile::INVALID};
+ ASSERT_EQ(types.size(), states.size());
+ for (unsigned long i = 0; i < types.size(); ++i) {
+ (*profile_validity_map
+ .mutable_field_validity_states())[static_cast<int>(types[i])] =
+ static_cast<int>(states[i]);
+ }
+ (*user_profile_validity_map.mutable_profile_validity())[guid] =
+ profile_validity_map;
+ ASSERT_TRUE(
+ user_profile_validity_map.SerializeToString(&autofill_profile_validity));
+ personal_data_->pref_service_->SetString(prefs::kAutofillProfileValidity,
+ autofill_profile_validity);
+
+ // Add another non-empty valdity profile.
+ guid = "00000000-0000-0000-0000-0000000000002";
+ profile_validity_map.Clear();
+ autofill_profile_validity.clear();
+ (*profile_validity_map
+ .mutable_field_validity_states())[static_cast<int>(EMAIL_ADDRESS)] =
+ static_cast<int>(AutofillProfile::VALID);
+ (*user_profile_validity_map.mutable_profile_validity())[guid] =
+ profile_validity_map;
+ ASSERT_TRUE(
+ user_profile_validity_map.SerializeToString(&autofill_profile_validity));
+ personal_data_->pref_service_->SetString(prefs::kAutofillProfileValidity,
+ autofill_profile_validity);
+
+ // Profile not found.
+ guid = "00000000-0000-0000-0000-0000000000003";
+ EXPECT_TRUE(personal_data_->GetProfileValidityByGUID(guid)
+ .field_validity_states()
+ .empty());
+
+ // Existing Profiles.
+ guid = "00000000-0000-0000-0000-0000000000001";
+ auto validities =
+ personal_data_->GetProfileValidityByGUID(guid).field_validity_states();
+ ASSERT_EQ(validities.size(), types.size());
+ for (unsigned long i = 0; i < types.size(); ++i)
+ EXPECT_EQ(validities.at(types[i]), states[i]);
+
+ guid = "00000000-0000-0000-0000-0000000000002";
+ validities =
+ personal_data_->GetProfileValidityByGUID(guid).field_validity_states();
+ ASSERT_FALSE(validities.empty());
+ EXPECT_EQ(validities.at(EMAIL_ADDRESS), AutofillProfile::VALID);
+}
+
+TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) {
+ const std::string kIdentityManagerAccountEmail = "identity_account@email.com";
+ const std::string kSyncServiceAccountEmail = "active_sync_account@email.com";
+
+ // Make the IdentityManager return a non-empty AccountInfo when
+ // GetPrimaryAccountInfo() is called.
+ identity_test_env_.SetPrimaryAccount(kIdentityManagerAccountEmail);
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+
+ // Make the sync service return a non-empty AccountInfo when
+ // GetAuthenticatedAccountInfo() is called.
+ AccountInfo active_info;
+ active_info.email = kSyncServiceAccountEmail;
+ sync_service_.SetAuthenticatedAccountInfo(active_info);
+
+ // The IdentityManager's AccountInfo should be returned by default.
+ {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitWithFeatures(
+ /*enabled_features=*/{},
+ /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage,
+ features::kAutofillGetPaymentsIdentityFromSync});
+
+ EXPECT_EQ(kIdentityManagerAccountEmail,
+ personal_data_->GetAccountInfoForPaymentsServer().email);
+ }
+
+ // The Active Sync AccountInfo should be returned if
+ // kAutofillEnableAccountWalletStorage is enabled.
+ {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitWithFeatures(
+ /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage},
+ /*disabled_features=*/{features::kAutofillGetPaymentsIdentityFromSync});
+
+ EXPECT_EQ(kSyncServiceAccountEmail,
+ personal_data_->GetAccountInfoForPaymentsServer().email);
+ }
+
+ // The Active Sync AccountInfo should be returned if
+ // kAutofillGetPaymentsIdentityFromSync is enabled.
+ {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitWithFeatures(
+ /*enabled_features=*/{features::kAutofillGetPaymentsIdentityFromSync},
+ /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage});
+
+ EXPECT_EQ(kSyncServiceAccountEmail,
+ personal_data_->GetAccountInfoForPaymentsServer().email);
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/proto/BUILD.gn b/chromium/components/autofill/core/browser/proto/BUILD.gn
index c6cb42e9272..04f9f54c8da 100644
--- a/chromium/components/autofill/core/browser/proto/BUILD.gn
+++ b/chromium/components/autofill/core/browser/proto/BUILD.gn
@@ -2,9 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//third_party/protobuf/proto_library.gni")
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
-proto_library("proto") {
+fuzzable_proto_library("proto") {
sources = [
"autofill_sync.proto",
"password_requirements.proto",
diff --git a/chromium/components/autofill/core/browser/proto/server.proto b/chromium/components/autofill/core/browser/proto/server.proto
index b450b8550f9..ba53eb41ea0 100644
--- a/chromium/components/autofill/core/browser/proto/server.proto
+++ b/chromium/components/autofill/core/browser/proto/server.proto
@@ -52,7 +52,7 @@ message AutofillQueryResponseContents {
// 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: 30
+// Next available id: 31
message AutofillUploadContents {
required string client_version = 1;
required fixed64 form_signature = 2;
@@ -76,7 +76,7 @@ message AutofillUploadContents {
// enum of types located at
// components/autofill/core/browser/field_types.h
// AutoFillFieldType
- required fixed32 autofill_type = 7;
+ repeated fixed32 autofill_type = 7;
// The value of the name attribute on the field, if present. Otherwise, the
// value of the id attribute. See HTMLFormControlElement::nameForAutofill.
@@ -99,14 +99,6 @@ message AutofillUploadContents {
// The type of password generation, if it happened.
optional PasswordGenerationType generation_type = 17;
- enum FormClassifierOutcome {
- NO_OUTCOME = 0;
- NON_GENERATION_ELEMENT = 1;
- GENERATION_ELEMENT = 2;
- }
- // The outcome of HTML parsing based form classifier.
- optional FormClassifierOutcome form_classifier_outcome = 18;
-
// The value of the class attribute on the field, if present.
optional string css_classes = 19;
@@ -189,4 +181,45 @@ message AutofillUploadContents {
// Noisifed password length.
optional uint32 password_length = 29;
// The end of the section of password attributes.
+
+ // Event observed by the password manager which indicated that the form was
+ // successfully submitted. Corresponds to
+ // |PasswordForm::SubmissionIndicatorEvent|.
+ enum SubmissionIndicatorEvent {
+ NONE = 0;
+ HTML_FORM_SUBMISSION = 1;
+ SAME_DOCUMENT_NAVIGATION = 2;
+ XHR_SUCCEEDED = 3;
+ FRAME_DETACHED = 4;
+ DEPRECATED_MANUAL_SAVE = 5; // obsolete
+ DOM_MUTATION_AFTER_XHR = 6;
+ PROVISIONALLY_SAVED_FORM_ON_START_PROVISIONAL_LOAD = 7;
+ DEPRECATED_FILLED_FORM_ON_START_PROVISIONAL_LOAD = 8; // unused
+ DEPRECATED_FILLED_INPUT_ELEMENTS_ON_START_PROVISIONAL_LOAD = 9; // unused
+ }
+
+ // The type of the event that was taken as an indication that the form has
+ // been successfully submitted.
+ optional SubmissionIndicatorEvent submission_event = 30;
+}
+
+// This proto contains information about the validity of each field in an
+// autofill profile. It is used to transfer the results of running the profile
+// validation pipeline on the server side to the client via ChromeSync
+// PriorityPreferences. An identical copy of this proto is maintained in
+// the server code base.
+message ProfileValidityMap {
+ // Map from autofill type to the validity of its value in the profile.
+ //
+ // Key should be one of the enum values from ServerFieldType. Values should be
+ // from the AutofillProfile::ValidityState enum above. Plain integers are used
+ // instead of enums because proto2 treats unknown enum values as unknown
+ // fields, which is confusing when the enums are in maps.
+ map<int32, int32> field_validity_states = 1;
+}
+
+// Map from profile GUIDs to profile validity maps for that profile. Each
+// message should contain entries for all profiles from a single user.
+message UserProfileValidityMap {
+ map<string, ProfileValidityMap> profile_validity = 1;
}
diff --git a/chromium/components/autofill/core/browser/region_combobox_model.h b/chromium/components/autofill/core/browser/region_combobox_model.h
index e6a89b29fe3..f42d897a35b 100644
--- a/chromium/components/autofill/core/browser/region_combobox_model.h
+++ b/chromium/components/autofill/core/browser/region_combobox_model.h
@@ -70,7 +70,7 @@ class RegionComboboxModel : public ui::ComboboxModel {
std::vector<std::pair<std::string, std::string>> regions_;
// To be called when the data for the given country code was loaded.
- base::ObserverList<ui::ComboboxModelObserver> observers_;
+ base::ObserverList<ui::ComboboxModelObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(RegionComboboxModel);
};
diff --git a/chromium/components/autofill/core/browser/region_data_loader_impl.cc b/chromium/components/autofill/core/browser/region_data_loader_impl.cc
index 9415cc247a0..698c425dda9 100644
--- a/chromium/components/autofill/core/browser/region_data_loader_impl.cc
+++ b/chromium/components/autofill/core/browser/region_data_loader_impl.cc
@@ -34,8 +34,8 @@ void RegionDataLoaderImpl::LoadRegionData(
*region_data_supplier_callback_);
timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(timeout_ms),
- base::Bind(&RegionDataLoaderImpl::OnRegionDataLoaded,
- base::Unretained(this), false, country_code, 0));
+ base::BindOnce(&RegionDataLoaderImpl::OnRegionDataLoaded,
+ base::Unretained(this), false, country_code, 0));
}
void RegionDataLoaderImpl::ClearCallback() {
@@ -61,8 +61,8 @@ void RegionDataLoaderImpl::OnRegionDataLoaded(bool success,
// The deletion must be asynchronous since the caller is not quite done with
// the preload supplier.
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&RegionDataLoaderImpl::DeleteThis, base::Unretained(this)));
+ FROM_HERE, base::BindOnce(&RegionDataLoaderImpl::DeleteThis,
+ base::Unretained(this)));
}
void RegionDataLoaderImpl::DeleteThis() {
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index 19a108d7b27..3c7897a6f46 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -60,8 +60,7 @@ TestAutofillClient::GetSecurityLevelForUmaHistograms() {
return security_level_;
}
-void TestAutofillClient::ShowAutofillSettings() {
-}
+void TestAutofillClient::ShowAutofillSettings(bool show_credit_card_settings) {}
void TestAutofillClient::ShowUnmaskPrompt(
const CreditCard& card,
@@ -72,9 +71,16 @@ void TestAutofillClient::ShowUnmaskPrompt(
void TestAutofillClient::OnUnmaskVerificationResult(PaymentsRpcResult result) {
}
-void TestAutofillClient::ShowLocalCardMigrationPrompt(
- base::OnceClosure closure) {
- std::move(closure).Run();
+void TestAutofillClient::ShowLocalCardMigrationDialog(
+ base::OnceClosure show_migration_dialog_closure) {
+ std::move(show_migration_dialog_closure).Run();
+}
+
+void TestAutofillClient::ConfirmMigrateLocalCardToCloud(
+ std::unique_ptr<base::DictionaryValue> legal_message,
+ std::vector<MigratableCreditCard>& migratable_credit_cards,
+ base::OnceClosure start_migrating_cards_closure) {
+ std::move(start_migrating_cards_closure).Run();
}
void TestAutofillClient::ConfirmSaveAutofillProfile(
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index cff3e370029..8cb300f8f81 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -37,12 +37,17 @@ class TestAutofillClient : public AutofillClient {
ukm::SourceId GetUkmSourceId() override;
AddressNormalizer* GetAddressNormalizer() override;
security_state::SecurityLevel GetSecurityLevelForUmaHistograms() override;
- void ShowAutofillSettings() override;
+ void ShowAutofillSettings(bool show_credit_card_settings) override;
void ShowUnmaskPrompt(const CreditCard& card,
UnmaskCardReason reason,
base::WeakPtr<CardUnmaskDelegate> delegate) override;
void OnUnmaskVerificationResult(PaymentsRpcResult result) override;
- void ShowLocalCardMigrationPrompt(base::OnceClosure closure) override;
+ void ShowLocalCardMigrationDialog(
+ base::OnceClosure show_migration_dialog_closure) override;
+ void ConfirmMigrateLocalCardToCloud(
+ std::unique_ptr<base::DictionaryValue> legal_message,
+ std::vector<MigratableCreditCard>& migratable_credit_cards,
+ base::OnceClosure start_migrating_cards_closure) override;
void ConfirmSaveAutofillProfile(const AutofillProfile& profile,
base::OnceClosure callback) override;
void ConfirmSaveCreditCardLocally(const CreditCard& card,
diff --git a/chromium/components/autofill/core/browser/test_autofill_manager.cc b/chromium/components/autofill/core/browser/test_autofill_manager.cc
index dfbe4a78d74..c8ac474c824 100644
--- a/chromium/components/autofill/core/browser/test_autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_manager.cc
@@ -26,8 +26,7 @@ TestAutofillManager::TestAutofillManager(AutofillDriver* driver,
client_(client) {
set_payments_client(new payments::PaymentsClient(
url_loader_factory_, client->GetPrefs(), client->GetIdentityManager(),
- /*unmask_delegate=*/this,
- /*save_delegate=*/nullptr));
+ personal_data));
}
TestAutofillManager::TestAutofillManager(
@@ -150,8 +149,8 @@ void TestAutofillManager::AddSeenForm(
void TestAutofillManager::AddSeenFormStructure(
std::unique_ptr<FormStructure> form_structure) {
- form_structure->set_form_parsed_timestamp(base::TimeTicks::Now());
- mutable_form_structures()->push_back(std::move(form_structure));
+ const auto signature = form_structure->form_signature();
+ (*mutable_form_structures())[signature] = std::move(form_structure);
}
void TestAutofillManager::ClearFormStructures() {
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 c06d9507ac4..ab8a64099d2 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
@@ -16,12 +16,7 @@ TestCreditCardSaveManager::TestCreditCardSaveManager(
: CreditCardSaveManager(client,
payments_client,
"en-US",
- personal_data_manager),
- test_payments_client_(payments_client) {
- if (test_payments_client_) {
- test_payments_client_->SetSaveDelegate(this);
- }
-}
+ personal_data_manager) {}
TestCreditCardSaveManager::~TestCreditCardSaveManager() {}
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 b00211b3b17..cc157fc47fa 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
@@ -38,7 +38,6 @@ class TestCreditCardSaveManager : public CreditCardSaveManager {
void OnDidUploadCard(AutofillClient::PaymentsRpcResult result,
const std::string& server_id) override;
- payments::TestPaymentsClient* test_payments_client_; // Weak reference.
bool credit_card_upload_enabled_ = false;
bool credit_card_was_uploaded_ = false;
diff --git a/chromium/components/autofill/core/browser/test_event_waiter.h b/chromium/components/autofill/core/browser/test_event_waiter.h
index b7f7102e80c..be100f8fc53 100644
--- a/chromium/components/autofill/core/browser/test_event_waiter.h
+++ b/chromium/components/autofill/core/browser/test_event_waiter.h
@@ -31,7 +31,7 @@ template <typename Event>
class EventWaiter {
public:
explicit EventWaiter(
- std::list<Event> event_sequence,
+ std::list<Event> expected_event_sequence,
base::TimeDelta timeout = base::TimeDelta::FromSeconds(0));
~EventWaiter();
@@ -44,16 +44,16 @@ class EventWaiter {
void OnEvent(Event event);
private:
- std::list<Event> events_;
+ std::list<Event> expected_events_;
base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(EventWaiter);
};
template <typename Event>
-EventWaiter<Event>::EventWaiter(std::list<Event> event_sequence,
+EventWaiter<Event>::EventWaiter(std::list<Event> expected_event_sequence,
base::TimeDelta timeout)
- : events_(std::move(event_sequence)) {
+ : expected_events_(std::move(expected_event_sequence)) {
if (!timeout.is_zero()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop_.QuitClosure(), timeout);
@@ -65,23 +65,23 @@ EventWaiter<Event>::~EventWaiter() {}
template <typename Event>
bool EventWaiter<Event>::Wait() {
- if (events_.empty())
+ if (expected_events_.empty())
return true;
DCHECK(!run_loop_.running());
run_loop_.Run();
- return events_.empty();
+ return expected_events_.empty();
}
template <typename Event>
-void EventWaiter<Event>::OnEvent(Event event) {
- if (events_.empty())
+void EventWaiter<Event>::OnEvent(Event actual_event) {
+ if (expected_events_.empty())
return;
- ASSERT_EQ(events_.front(), event);
- events_.pop_front();
+ ASSERT_EQ(expected_events_.front(), actual_event);
+ expected_events_.pop_front();
// Only quit the loop if no other events are expected.
- if (events_.empty() && run_loop_.running())
+ if (expected_events_.empty() && run_loop_.running())
run_loop_.Quit();
}
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 9ef4888c8a0..657a894d146 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
@@ -4,9 +4,10 @@
#include "components/autofill/core/browser/test_local_card_migration_manager.h"
-#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/payments/test_payments_client.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "services/identity/public/cpp/identity_manager.h"
namespace autofill {
@@ -19,17 +20,14 @@ TestLocalCardMigrationManager::TestLocalCardMigrationManager(
: LocalCardMigrationManager(client,
payments_client,
"en-US",
- personal_data_manager),
- test_payments_client_(payments_client) {
- if (test_payments_client_)
- test_payments_client_->SetSaveDelegate(this);
-}
+ personal_data_manager) {}
TestLocalCardMigrationManager::~TestLocalCardMigrationManager() {}
bool TestLocalCardMigrationManager::IsCreditCardMigrationEnabled() {
bool migration_experiment_enabled =
- IsAutofillCreditCardLocalCardMigrationExperimentEnabled();
+ features::GetLocalCardMigrationExperimentalFlag() !=
+ features::LocalCardMigrationExperimentalFlag::kMigrationDisabled;
bool has_google_payments_account =
(static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble(
prefs::kAutofillBillingCustomerNumber)) != 0);
@@ -40,14 +38,34 @@ bool TestLocalCardMigrationManager::LocalCardMigrationWasTriggered() {
return local_card_migration_was_triggered_;
}
+bool TestLocalCardMigrationManager::IntermediatePromptWasShown() {
+ return intermediate_prompt_was_shown_;
+}
+
+bool TestLocalCardMigrationManager::MainPromptWasShown() {
+ return main_prompt_was_shown_;
+}
+
+void TestLocalCardMigrationManager::
+ OnUserAcceptedIntermediateMigrationDialog() {
+ intermediate_prompt_was_shown_ = true;
+ LocalCardMigrationManager::OnUserAcceptedIntermediateMigrationDialog();
+}
+
+void TestLocalCardMigrationManager::OnUserAcceptedMainMigrationDialog() {
+ main_prompt_was_shown_ = true;
+ LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog();
+}
+
void TestLocalCardMigrationManager::OnDidGetUploadDetails(
+ bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
std::unique_ptr<base::DictionaryValue> legal_message) {
if (result == AutofillClient::SUCCESS) {
local_card_migration_was_triggered_ = true;
- LocalCardMigrationManager::OnDidGetUploadDetails(result, context_token,
- std::move(legal_message));
+ LocalCardMigrationManager::OnDidGetUploadDetails(
+ is_from_settings_page, result, context_token, std::move(legal_message));
}
}
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 07041a9dd45..944019e3252 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
@@ -32,18 +32,36 @@ class TestLocalCardMigrationManager : public LocalCardMigrationManager {
// user is signed in/syncing.
bool IsCreditCardMigrationEnabled() override;
- // Returns whether the first round migration pop-up window was triggered.
+ // Returns whether the local card migration was triggered.
bool LocalCardMigrationWasTriggered();
+ // Returns whether the first round intermediate pop-up window was shown.
+ bool IntermediatePromptWasShown();
+
+ // Returns whether the main prompt window was shown.
+ bool MainPromptWasShown();
+
+ // Override the base function. When called, represents the intermediate prompt
+ // is shown. Set the |intermediate_prompt_was_shown_|.
+ void OnUserAcceptedIntermediateMigrationDialog() override;
+
+ // Override the base function. When called, represent the main prompt is
+ // shown. Set the |main_prompt_was_shown_|.
+ void OnUserAcceptedMainMigrationDialog() override;
+
private:
void OnDidGetUploadDetails(
+ bool is_from_settings_page,
AutofillClient::PaymentsRpcResult result,
const base::string16& context_token,
std::unique_ptr<base::DictionaryValue> legal_message) override;
- payments::TestPaymentsClient* test_payments_client_; // Weak reference.
bool local_card_migration_was_triggered_ = false;
+ bool intermediate_prompt_was_shown_ = false;
+
+ bool main_prompt_was_shown_ = false;
+
DISALLOW_COPY_AND_ASSIGN(TestLocalCardMigrationManager);
};
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 583ac99edda..af7a2afcddf 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
@@ -218,6 +218,14 @@ bool TestPersonalDataManager::IsDataLoaded() const {
return true;
}
+bool TestPersonalDataManager::IsSyncFeatureEnabled() const {
+ return sync_feature_enabled_;
+}
+
+AccountInfo TestPersonalDataManager::GetAccountInfoForPaymentsServer() const {
+ return account_info_;
+}
+
void TestPersonalDataManager::ClearProfiles() {
web_profiles_.clear();
}
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 2c2b6cd9d01..1ecacaecfaa 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h
@@ -10,7 +10,9 @@
#include "base/optional.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/signin/core/browser/account_info.h"
namespace autofill {
@@ -50,6 +52,8 @@ class TestPersonalDataManager : public PersonalDataManager {
std::string CountryCodeForCurrentTimezone() const override;
void ClearAllLocalData() override;
bool IsDataLoaded() const override;
+ bool IsSyncFeatureEnabled() const override;
+ AccountInfo GetAccountInfoForPaymentsServer() const override;
// Unique to TestPersonalDataManager:
@@ -100,6 +104,17 @@ class TestPersonalDataManager : public PersonalDataManager {
autofill_wallet_import_enabled_ = autofill_wallet_import_enabled;
}
+ void SetPaymentsCustomerData(
+ std::unique_ptr<PaymentsCustomerData> customer_data) {
+ payments_customer_data_ = std::move(customer_data);
+ }
+
+ void SetSyncFeatureEnabled(bool enabled) { sync_feature_enabled_ = enabled; }
+
+ void SetAccountInfoForPayments(const AccountInfo& account_info) {
+ account_info_ = account_info;
+ }
+
private:
std::string timezone_country_code_;
std::string default_country_code_;
@@ -109,6 +124,8 @@ class TestPersonalDataManager : public PersonalDataManager {
base::Optional<bool> autofill_profile_enabled_;
base::Optional<bool> autofill_credit_card_enabled_;
base::Optional<bool> autofill_wallet_import_enabled_;
+ bool sync_feature_enabled_;
+ AccountInfo account_info_;
DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager);
};
diff --git a/chromium/components/autofill/core/browser/test_sync_service.cc b/chromium/components/autofill/core/browser/test_sync_service.cc
index c1680e26a38..2f42009a83e 100644
--- a/chromium/components/autofill/core/browser/test_sync_service.cc
+++ b/chromium/components/autofill/core/browser/test_sync_service.cc
@@ -30,10 +30,6 @@ syncer::ModelTypeSet TestSyncService::GetActiveDataTypes() const {
return data_types_;
}
-bool TestSyncService::IsEngineInitialized() const {
- return is_engine_initialized_;
-}
-
bool TestSyncService::IsFirstSetupComplete() const {
return true;
}
@@ -42,6 +38,10 @@ bool TestSyncService::IsUsingSecondaryPassphrase() const {
return is_using_secondary_passphrase_;
}
+bool TestSyncService::IsAuthenticatedAccountPrimary() const {
+ return is_authenticated_account_primary_;
+}
+
const GoogleServiceAuthError& TestSyncService::GetAuthError() const {
return auth_error_;
}
@@ -73,6 +73,10 @@ syncer::SyncTokenStatus TestSyncService::GetSyncTokenStatus() const {
return token;
}
+AccountInfo TestSyncService::GetAuthenticatedAccountInfo() const {
+ return account_info_;
+}
+
void TestSyncService::SetInAuthError(bool is_in_auth_error) {
is_in_auth_error_ = is_in_auth_error;
diff --git a/chromium/components/autofill/core/browser/test_sync_service.h b/chromium/components/autofill/core/browser/test_sync_service.h
index 2be40aa0dec..cecf626d84e 100644
--- a/chromium/components/autofill/core/browser/test_sync_service.h
+++ b/chromium/components/autofill/core/browser/test_sync_service.h
@@ -19,23 +19,24 @@ class TestSyncService : public syncer::FakeSyncService {
int GetDisableReasons() const override;
syncer::ModelTypeSet GetPreferredDataTypes() const override;
syncer::ModelTypeSet GetActiveDataTypes() const override;
- bool IsEngineInitialized() const override;
bool IsFirstSetupComplete() const override;
bool IsUsingSecondaryPassphrase() const override;
syncer::SyncCycleSnapshot GetLastCycleSnapshot() const override;
const GoogleServiceAuthError& GetAuthError() const override;
syncer::SyncTokenStatus GetSyncTokenStatus() const override;
+ bool IsAuthenticatedAccountPrimary() const override;
+ AccountInfo GetAuthenticatedAccountInfo() const override;
void SetDisableReasons(int disable_reasons) {
disable_reasons_ = disable_reasons;
}
- void SetDataTypes(syncer::ModelTypeSet data_types) {
- data_types_ = data_types;
+ void SetIsAuthenticatedAccountPrimary(bool is_authenticated_account_primary) {
+ is_authenticated_account_primary_ = is_authenticated_account_primary;
}
- void SetIsEngineInitialized(bool is_engine_initialized) {
- is_engine_initialized_ = is_engine_initialized;
+ void SetDataTypes(syncer::ModelTypeSet data_types) {
+ data_types_ = data_types;
}
void SetIsUsingSecondaryPassphrase(bool is_using_secondary_passphrase) {
@@ -46,15 +47,20 @@ class TestSyncService : public syncer::FakeSyncService {
void SetInAuthError(bool is_in_auth_error);
+ void SetAuthenticatedAccountInfo(const AccountInfo& account_info) {
+ account_info_ = account_info;
+ }
+
private:
int disable_reasons_ = DISABLE_REASON_NONE;
// Used as both "preferred" and "active" data types.
syncer::ModelTypeSet data_types_;
- bool is_engine_initialized_ = true;
bool is_using_secondary_passphrase_ = false;
bool sync_cycle_complete_ = true;
GoogleServiceAuthError auth_error_;
bool is_in_auth_error_ = false;
+ bool is_authenticated_account_primary_ = true;
+ AccountInfo account_info_;
DISALLOW_COPY_AND_ASSIGN(TestSyncService);
};
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 16f4d9d4846..69818085c4a 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
@@ -17,7 +17,7 @@
#include "components/autofill/core/browser/ui/card_unmask_prompt_view.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_clock.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/grit/components_scaled_resources.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
diff --git a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl_unittest.cc b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl_unittest.cc
index e34a39c3cf3..529554614e0 100644
--- a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl_unittest.cc
@@ -17,7 +17,7 @@
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/ui/card_unmask_prompt_view.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/autofill/core/browser/ui/local_card_migration_bubble_controller.h b/chromium/components/autofill/core/browser/ui/local_card_migration_bubble_controller.h
index a2dc6206656..8afce255edb 100644
--- a/chromium/components/autofill/core/browser/ui/local_card_migration_bubble_controller.h
+++ b/chromium/components/autofill/core/browser/ui/local_card_migration_bubble_controller.h
@@ -20,8 +20,8 @@ class LocalCardMigrationBubbleController {
LocalCardMigrationBubbleController() {}
virtual ~LocalCardMigrationBubbleController() {}
- // Returns the title that should be displayed in the bubble.
- virtual base::string16 GetWindowTitle() const = 0;
+ // Returns the explanatory message that should be displayed in the bubble.
+ virtual base::string16 GetBubbleMessage() const = 0;
// Interaction.
virtual void OnConfirmButtonClicked() = 0;
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
new file mode 100644
index 00000000000..8288b82b0a4
--- /dev/null
+++ b/chromium/components/autofill/core/browser/ui/local_card_migration_dialog_controller.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_UI_LOCAL_CARD_MIGRATION_DIALOG_CONTROLLER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_LOCAL_CARD_MIGRATION_DIALOG_CONTROLLER_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/autofill/core/browser/legal_message_line.h"
+
+namespace autofill {
+
+enum class LocalCardMigrationDialogState;
+class MigratableCreditCard;
+
+// TODO(crbug.com/867194): Add legal message.
+// Interface that exposes controller functionality to local card migration
+// dialog views.
+class LocalCardMigrationDialogController {
+ public:
+ LocalCardMigrationDialogController() {}
+ virtual ~LocalCardMigrationDialogController() {}
+
+ virtual LocalCardMigrationDialogState GetViewState() const = 0;
+ virtual void SetViewState(LocalCardMigrationDialogState view_state) = 0;
+ virtual const std::vector<MigratableCreditCard>& GetCardList() const = 0;
+ // TODO(crbug.com/867194): Ensure this would not be called when migration is
+ // happending.
+ virtual void SetCardList(std::vector<MigratableCreditCard>& card_list) = 0;
+ virtual const LegalMessageLines& GetLegalMessageLines() const = 0;
+ virtual void OnCardSelected(int index) = 0;
+ virtual void OnDialogClosed() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationDialogController);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_LOCAL_CARD_MIGRATION_DIALOG_CONTROLLER_H_
diff --git a/chromium/components/autofill/core/browser/ui/save_card_bubble_controller.h b/chromium/components/autofill/core/browser/ui/save_card_bubble_controller.h
index 371fc523b0c..cfc1fff5113 100644
--- a/chromium/components/autofill/core/browser/ui/save_card_bubble_controller.h
+++ b/chromium/components/autofill/core/browser/ui/save_card_bubble_controller.h
@@ -14,10 +14,17 @@
#include "components/signin/core/browser/account_info.h"
#include "url/gurl.h"
+class Profile;
+
+namespace signin_metrics {
+enum class AccessPoint;
+}
+
namespace autofill {
class CreditCard;
class SaveCardBubbleView;
+enum class BubbleType;
// Interface that exposes controller functionality to SaveCardBubbleView.
class SaveCardBubbleController {
@@ -35,6 +42,9 @@ class SaveCardBubbleController {
// Returns the account info of the signed-in user.
virtual const AccountInfo& GetAccountInfo() const = 0;
+ // Returns the profile.
+ virtual Profile* GetProfile() const = 0;
+
// Returns the card that will be uploaded if the user accepts.
virtual const CreditCard& GetCard() const = 0;
@@ -42,19 +52,36 @@ class SaveCardBubbleController {
// to confirm/provide cardholder name.
virtual bool ShouldRequestNameFromUser() const = 0;
+ // Returns whether or not a sign in / sync promo needs to be shown.
+ virtual bool ShouldShowSignInPromo() const = 0;
+
+ // Returns true iff the card saved animation can be shown.
+ virtual bool CanAnimate() const = 0;
+
// Interaction.
+ // OnSyncPromoAccepted is called when the Dice Sign-in promo is clicked.
+ virtual void OnSyncPromoAccepted(const AccountInfo& account,
+ signin_metrics::AccessPoint access_point,
+ bool is_default_promo_account) = 0;
// OnSaveButton takes in a string value representing the cardholder name
// confirmed/entered by the user if it was requested, or an empty string
// otherwise.
virtual void OnSaveButton(const base::string16& cardholder_name) = 0;
virtual void OnCancelButton() = 0;
virtual void OnLegalMessageLinkClicked(const GURL& url) = 0;
+ virtual void OnManageCardsClicked() = 0;
virtual void OnBubbleClosed() = 0;
+ // Once the animation ends, it shows a new bubble if needed.
+ virtual void OnAnimationEnded() = 0;
// State.
// Returns empty vector if no legal message should be shown.
virtual const LegalMessageLines& GetLegalMessageLines() const = 0;
+ // Returns true iff is showing or has showed bubble for upload save.
+ virtual bool IsUploadSave() const = 0;
+ // Returns the current state of the bubble.
+ virtual BubbleType GetBubbleType() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleController);
diff --git a/chromium/components/autofill/core/browser/webdata/OWNERS b/chromium/components/autofill/core/browser/webdata/OWNERS
new file mode 100644
index 00000000000..edcc64dbae7
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/OWNERS
@@ -0,0 +1,2 @@
+per-file *sync_bridge*=jkrcal@chromium.org
+per-file *sync_bridge*=file://components/sync/OWNERS
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 088149b3c7d..664b9e74879 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -50,7 +50,7 @@ const char kAutocompleteTagDelimiter[] = "|";
return ret_val; \
}
-void* UserDataKey() {
+void* AutocompleteSyncBridgeUserDataKey() {
// Use the address of a static that COMDAT folding won't ever collide
// with something else.
static int user_data_key = 0;
@@ -283,7 +283,7 @@ void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend(
AutofillWebDataService* web_data_service,
AutofillWebDataBackend* web_data_backend) {
web_data_service->GetDBUserData()->SetUserData(
- UserDataKey(),
+ AutocompleteSyncBridgeUserDataKey(),
std::make_unique<AutocompleteSyncBridge>(
web_data_backend,
std::make_unique<ClientTagBasedModelTypeProcessor>(
@@ -294,7 +294,8 @@ void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend(
ModelTypeSyncBridge* AutocompleteSyncBridge::FromWebDataService(
AutofillWebDataService* web_data_service) {
return static_cast<AutocompleteSyncBridge*>(
- web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+ web_data_service->GetDBUserData()->GetUserData(
+ AutocompleteSyncBridgeUserDataKey()));
}
AutocompleteSyncBridge::AutocompleteSyncBridge(
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 0dc61f9ed08..a3fae5e9209 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
@@ -300,7 +300,7 @@ class AutocompleteSyncBridgeTest : public testing::Test {
void VerifyAllData(const std::vector<AutofillSpecifics>& expected) {
bridge()->GetAllDataForDebugging(
- base::Bind(&VerifyDataBatch, ExpectedMap(expected)));
+ base::BindOnce(&VerifyDataBatch, ExpectedMap(expected)));
}
AutocompleteSyncBridge* bridge() { return bridge_.get(); }
@@ -424,7 +424,7 @@ TEST_F(AutocompleteSyncBridgeTest, GetData) {
SaveSpecificsToTable({specifics1, specifics2, specifics3});
bridge()->GetData(
{GetStorageKey(specifics1), GetStorageKey(specifics3)},
- base::Bind(&VerifyDataBatch, ExpectedMap({specifics1, specifics3})));
+ base::BindOnce(&VerifyDataBatch, ExpectedMap({specifics1, specifics3})));
}
TEST_F(AutocompleteSyncBridgeTest, GetDataNotExist) {
@@ -435,7 +435,7 @@ TEST_F(AutocompleteSyncBridgeTest, GetDataNotExist) {
bridge()->GetData(
{GetStorageKey(specifics1), GetStorageKey(specifics2),
GetStorageKey(specifics3)},
- base::Bind(&VerifyDataBatch, ExpectedMap({specifics1, specifics2})));
+ base::BindOnce(&VerifyDataBatch, ExpectedMap({specifics1, specifics2})));
}
TEST_F(AutocompleteSyncBridgeTest, GetAllData) {
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 5f88eac4c24..9566edcf3a2 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
@@ -10,7 +10,7 @@
#include "base/metrics/histogram.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_service.h"
#include "components/sync/base/experiments.h"
#include "components/sync/driver/sync_client.h"
@@ -36,7 +36,7 @@ AutofillProfileDataTypeController::AutofillProfileDataTypeController(
currently_enabled_(IsEnabled()) {
pref_registrar_.Init(sync_client_->GetPrefService());
pref_registrar_.Add(
- autofill::prefs::kAutofillEnabled,
+ autofill::prefs::kAutofillProfileEnabled,
base::Bind(&AutofillProfileDataTypeController::OnUserPrefChanged,
base::AsWeakPtr(this)));
}
@@ -134,8 +134,8 @@ bool AutofillProfileDataTypeController::IsEnabled() {
DCHECK(CalledOnValidThread());
// Require the user-visible pref to be enabled to sync Autofill Profile data.
- PrefService* ps = sync_client_->GetPrefService();
- return ps->GetBoolean(autofill::prefs::kAutofillEnabled);
+ return autofill::prefs::IsProfileAutofillEnabled(
+ sync_client_->GetPrefService());
}
void AutofillProfileDataTypeController::DisableForPolicy() {
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 c83262a2a2c..c9d5b41ca0e 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
@@ -42,7 +42,7 @@ std::string LimitData(const std::string& data) {
return sanitized_value;
}
-void* UserDataKey() {
+void* AutofillProfileSyncableServiceUserDataKey() {
// Use the address of a static that COMDAT folding won't ever fold
// with something else.
static int user_data_key = 0;
@@ -74,8 +74,9 @@ void AutofillProfileSyncableService::CreateForWebDataServiceAndBackend(
AutofillWebDataBackend* webdata_backend,
const std::string& app_locale) {
web_data_service->GetDBUserData()->SetUserData(
- UserDataKey(), base::WrapUnique(new AutofillProfileSyncableService(
- webdata_backend, app_locale)));
+ AutofillProfileSyncableServiceUserDataKey(),
+ base::WrapUnique(
+ new AutofillProfileSyncableService(webdata_backend, app_locale)));
}
// static
@@ -83,7 +84,8 @@ AutofillProfileSyncableService*
AutofillProfileSyncableService::FromWebDataService(
AutofillWebDataService* web_data_service) {
return static_cast<AutofillProfileSyncableService*>(
- web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+ web_data_service->GetDBUserData()->GetUserData(
+ AutofillProfileSyncableServiceUserDataKey()));
}
AutofillProfileSyncableService::AutofillProfileSyncableService()
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc
new file mode 100644
index 00000000000..593ce4bc14c
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.cc
@@ -0,0 +1,61 @@
+// 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/webdata/autofill_sync_bridge_test_util.h"
+
+namespace autofill {
+
+AutofillProfile CreateServerProfile(const std::string& server_id) {
+ // TODO(sebsg): Set data.
+ return AutofillProfile(AutofillProfile::SERVER_PROFILE, server_id);
+}
+
+CreditCard CreateServerCreditCard(const std::string& server_id) {
+ // TODO(sebsg): Set data.
+ return CreditCard(CreditCard::MASKED_SERVER_CARD, server_id);
+}
+
+sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForCard(
+ const std::string& specifics_id,
+ const std::string& billing_address_id) {
+ sync_pb::AutofillWalletSpecifics wallet_specifics;
+ wallet_specifics.set_type(
+ sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_MASKED_CREDIT_CARD);
+
+ sync_pb::WalletMaskedCreditCard* card_specifics =
+ wallet_specifics.mutable_masked_card();
+ card_specifics->set_id(specifics_id);
+ card_specifics->set_billing_address_id(billing_address_id);
+ return wallet_specifics;
+}
+
+sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForAddress(
+ const std::string& specifics_id) {
+ sync_pb::AutofillWalletSpecifics wallet_specifics;
+ wallet_specifics.set_type(
+ sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_POSTAL_ADDRESS);
+
+ sync_pb::WalletPostalAddress* profile_specifics =
+ wallet_specifics.mutable_address();
+ profile_specifics->set_id(specifics_id);
+ return wallet_specifics;
+}
+
+sync_pb::AutofillWalletSpecifics
+CreateAutofillWalletSpecificsForPaymentsCustomerData(
+ const std::string& specifics_id) {
+ sync_pb::AutofillWalletSpecifics wallet_specifics;
+ wallet_specifics.set_type(
+ sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_CUSTOMER_DATA);
+
+ sync_pb::PaymentsCustomerData* customer_data_specifics =
+ wallet_specifics.mutable_customer_data();
+ customer_data_specifics->set_id(specifics_id);
+ return wallet_specifics;
+}
+
+} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h
new file mode 100644
index 00000000000..a3119a1f4ca
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_test_util.h
@@ -0,0 +1,33 @@
+// 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_WEBDATA_AUTOFILL_SYNC_BRIDGE_TEST_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_SYNC_BRIDGE_TEST_UTIL_H_
+
+#include <string>
+
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/sync/protocol/sync.pb.h"
+
+namespace autofill {
+
+AutofillProfile CreateServerProfile(const std::string& server_id);
+
+CreditCard CreateServerCreditCard(const std::string& server_id);
+
+sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForAddress(
+ const std::string& specifics_id);
+
+sync_pb::AutofillWalletSpecifics CreateAutofillWalletSpecificsForCard(
+ const std::string& specifics_id,
+ const std::string& billing_address_id = "");
+
+sync_pb::AutofillWalletSpecifics
+CreateAutofillWalletSpecificsForPaymentsCustomerData(
+ const std::string& specifics_id);
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_SYNC_BRIDGE_TEST_UTIL_H_
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
new file mode 100644
index 00000000000..0bea08e6a85
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
@@ -0,0 +1,422 @@
+// 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/webdata/autofill_sync_bridge_util.h"
+
+#include "base/base64.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/common/autofill_util.h"
+#include "components/sync/model/entity_data.h"
+
+using autofill::data_util::TruncateUTF8;
+using sync_pb::AutofillWalletSpecifics;
+using syncer::EntityData;
+
+namespace autofill {
+namespace {
+sync_pb::WalletMaskedCreditCard::WalletCardStatus LocalToServerStatus(
+ const CreditCard& card) {
+ switch (card.GetServerStatus()) {
+ case CreditCard::OK:
+ return sync_pb::WalletMaskedCreditCard::VALID;
+ case CreditCard::EXPIRED:
+ return sync_pb::WalletMaskedCreditCard::EXPIRED;
+ }
+}
+
+CreditCard::ServerStatus ServerToLocalStatus(
+ sync_pb::WalletMaskedCreditCard::WalletCardStatus status) {
+ switch (status) {
+ case sync_pb::WalletMaskedCreditCard::VALID:
+ return CreditCard::OK;
+ case sync_pb::WalletMaskedCreditCard::EXPIRED:
+ return CreditCard::EXPIRED;
+ }
+}
+
+sync_pb::WalletMaskedCreditCard::WalletCardType WalletCardTypeFromCardNetwork(
+ const std::string& network) {
+ if (network == kAmericanExpressCard)
+ return sync_pb::WalletMaskedCreditCard::AMEX;
+ if (network == kDiscoverCard)
+ return sync_pb::WalletMaskedCreditCard::DISCOVER;
+ if (network == kJCBCard)
+ return sync_pb::WalletMaskedCreditCard::JCB;
+ if (network == kMasterCard)
+ return sync_pb::WalletMaskedCreditCard::MASTER_CARD;
+ if (network == kUnionPay)
+ return sync_pb::WalletMaskedCreditCard::UNIONPAY;
+ if (network == kVisaCard)
+ return sync_pb::WalletMaskedCreditCard::VISA;
+
+ // Some cards aren't supported by the client, so just return unknown.
+ return sync_pb::WalletMaskedCreditCard::UNKNOWN;
+}
+
+const char* CardNetworkFromWalletCardType(
+ sync_pb::WalletMaskedCreditCard::WalletCardType type) {
+ switch (type) {
+ case sync_pb::WalletMaskedCreditCard::AMEX:
+ return kAmericanExpressCard;
+ case sync_pb::WalletMaskedCreditCard::DISCOVER:
+ return kDiscoverCard;
+ case sync_pb::WalletMaskedCreditCard::JCB:
+ return kJCBCard;
+ case sync_pb::WalletMaskedCreditCard::MASTER_CARD:
+ return kMasterCard;
+ case sync_pb::WalletMaskedCreditCard::UNIONPAY:
+ return kUnionPay;
+ case sync_pb::WalletMaskedCreditCard::VISA:
+ return kVisaCard;
+
+ // These aren't supported by the client, so just declare a generic card.
+ case sync_pb::WalletMaskedCreditCard::MAESTRO:
+ case sync_pb::WalletMaskedCreditCard::SOLO:
+ case sync_pb::WalletMaskedCreditCard::SWITCH:
+ case sync_pb::WalletMaskedCreditCard::UNKNOWN:
+ return kGenericCard;
+ }
+}
+
+sync_pb::WalletMaskedCreditCard::WalletCardClass WalletCardClassFromCardType(
+ CreditCard::CardType card_type) {
+ switch (card_type) {
+ case CreditCard::CARD_TYPE_CREDIT:
+ return sync_pb::WalletMaskedCreditCard::CREDIT;
+ case CreditCard::CARD_TYPE_DEBIT:
+ return sync_pb::WalletMaskedCreditCard::DEBIT;
+ case CreditCard::CARD_TYPE_PREPAID:
+ return sync_pb::WalletMaskedCreditCard::PREPAID;
+ case CreditCard::CARD_TYPE_UNKNOWN:
+ return sync_pb::WalletMaskedCreditCard::UNKNOWN_CARD_CLASS;
+ }
+}
+
+CreditCard::CardType CardTypeFromWalletCardClass(
+ sync_pb::WalletMaskedCreditCard::WalletCardClass card_class) {
+ switch (card_class) {
+ case sync_pb::WalletMaskedCreditCard::CREDIT:
+ return CreditCard::CARD_TYPE_CREDIT;
+ case sync_pb::WalletMaskedCreditCard::DEBIT:
+ return CreditCard::CARD_TYPE_DEBIT;
+ case sync_pb::WalletMaskedCreditCard::PREPAID:
+ return CreditCard::CARD_TYPE_PREPAID;
+ case sync_pb::WalletMaskedCreditCard::UNKNOWN_CARD_CLASS:
+ return CreditCard::CARD_TYPE_UNKNOWN;
+ }
+}
+
+} // namespace
+
+std::string GetBase64EncodedServerId(const std::string& server_id) {
+ std::string encoded_id;
+ base::Base64Encode(server_id, &encoded_id);
+ return encoded_id;
+}
+
+std::string GetSpecificsIdForEntryServerId(const std::string& server_id) {
+ return GetBase64EncodedServerId(server_id);
+}
+
+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;
+}
+
+std::string GetStorageKeyForEntryServerId(const std::string& server_id) {
+ return GetStorageKeyForSpecificsId(GetSpecificsIdForEntryServerId(server_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 "";
+ }
+}
+
+void SetAutofillWalletSpecificsFromServerProfile(
+ const AutofillProfile& address,
+ AutofillWalletSpecifics* wallet_specifics) {
+ wallet_specifics->set_type(AutofillWalletSpecifics::POSTAL_ADDRESS);
+
+ sync_pb::WalletPostalAddress* wallet_address =
+ wallet_specifics->mutable_address();
+
+ wallet_address->set_id(address.server_id());
+ wallet_address->set_language_code(TruncateUTF8(address.language_code()));
+
+ if (address.HasRawInfo(NAME_FULL)) {
+ wallet_address->set_recipient_name(
+ TruncateUTF8(base::UTF16ToUTF8(address.GetRawInfo(NAME_FULL))));
+ }
+ if (address.HasRawInfo(COMPANY_NAME)) {
+ wallet_address->set_company_name(
+ TruncateUTF8(base::UTF16ToUTF8(address.GetRawInfo(COMPANY_NAME))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_STREET_ADDRESS)) {
+ wallet_address->add_street_address(TruncateUTF8(
+ base::UTF16ToUTF8(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_STATE)) {
+ wallet_address->set_address_1(TruncateUTF8(
+ base::UTF16ToUTF8(address.GetRawInfo(ADDRESS_HOME_STATE))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_CITY)) {
+ wallet_address->set_address_2(
+ TruncateUTF8(base::UTF16ToUTF8(address.GetRawInfo(ADDRESS_HOME_CITY))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)) {
+ wallet_address->set_address_3(TruncateUTF8(base::UTF16ToUTF8(
+ address.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_ZIP)) {
+ wallet_address->set_postal_code(
+ TruncateUTF8(base::UTF16ToUTF8(address.GetRawInfo(ADDRESS_HOME_ZIP))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_COUNTRY)) {
+ wallet_address->set_country_code(TruncateUTF8(
+ base::UTF16ToUTF8(address.GetRawInfo(ADDRESS_HOME_COUNTRY))));
+ }
+ if (address.HasRawInfo(PHONE_HOME_WHOLE_NUMBER)) {
+ wallet_address->set_phone_number(TruncateUTF8(
+ base::UTF16ToUTF8(address.GetRawInfo(PHONE_HOME_WHOLE_NUMBER))));
+ }
+ if (address.HasRawInfo(ADDRESS_HOME_SORTING_CODE)) {
+ wallet_address->set_sorting_code(TruncateUTF8(
+ base::UTF16ToUTF8(address.GetRawInfo(ADDRESS_HOME_SORTING_CODE))));
+ }
+}
+
+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) {
+ 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());
+ wallet_card->set_status(LocalToServerStatus(card));
+ if (card.HasRawInfo(CREDIT_CARD_NAME_FULL)) {
+ wallet_card->set_name_on_card(TruncateUTF8(
+ base::UTF16ToUTF8(card.GetRawInfo(CREDIT_CARD_NAME_FULL))));
+ }
+ wallet_card->set_type(WalletCardTypeFromCardNetwork(card.network()));
+ 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) {
+ wallet_specifics->set_type(AutofillWalletSpecifics::CUSTOMER_DATA);
+
+ sync_pb::PaymentsCustomerData* mutable_customer_data =
+ wallet_specifics->mutable_customer_data();
+ 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) {
+ std::vector<std::unique_ptr<CreditCard>> cards_on_disk;
+ table.GetServerCreditCards(&cards_on_disk);
+
+ // Since the number of cards is fairly small, the brute-force search is good
+ // enough.
+ for (const auto& saved_card : cards_on_disk) {
+ for (CreditCard& server_card : *cards_from_server) {
+ if (saved_card->server_id() == server_card.server_id()) {
+ // The wallet data doesn't have the use stats. Use the ones present on
+ // disk to not overwrite them with bad data.
+ server_card.set_use_count(saved_card->use_count());
+ server_card.set_use_date(saved_card->use_date());
+
+ // Keep the billing address id of the saved cards only if it points to
+ // a local address.
+ if (saved_card->billing_address_id().length() == kLocalGuidSize) {
+ server_card.set_billing_address_id(saved_card->billing_address_id());
+ break;
+ }
+ }
+ }
+ }
+}
+
+void PopulateWalletTypesFromSyncData(
+ const syncer::EntityChangeList& entity_data,
+ std::vector<CreditCard>* wallet_cards,
+ std::vector<AutofillProfile>* wallet_addresses,
+ std::vector<PaymentsCustomerData>* customer_data) {
+ std::map<std::string, std::string> ids;
+
+ for (const syncer::EntityChange& change : entity_data) {
+ DCHECK(change.data().specifics.has_autofill_wallet());
+
+ const sync_pb::AutofillWalletSpecifics& autofill_specifics =
+ change.data().specifics.autofill_wallet();
+
+ switch (autofill_specifics.type()) {
+ case sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD:
+ wallet_cards->push_back(
+ CardFromSpecifics(autofill_specifics.masked_card()));
+ break;
+ case sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS:
+ // Unlike other pointers, |wallet_addresses| can be nullptr. This means
+ // that addresses should not get populated (and billing address ids not
+ // get translated to local profile ids).
+ if (wallet_addresses) {
+ wallet_addresses->push_back(
+ ProfileFromSpecifics(autofill_specifics.address()));
+
+ // Map the sync billing address id to the profile's id.
+ ids[autofill_specifics.address().id()] =
+ wallet_addresses->back().server_id();
+ }
+ break;
+ case sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA:
+ customer_data->push_back(
+ CustomerDataFromSpecifics(autofill_specifics.customer_data()));
+ break;
+ case sync_pb::AutofillWalletSpecifics::UNKNOWN:
+ // Just ignore new entry types that the client doesn't know about.
+ break;
+ }
+ }
+
+ // Set the billing address of the wallet cards to the id of the appropriate
+ // profile.
+ for (CreditCard& card : *wallet_cards) {
+ auto it = ids.find(card.billing_address_id());
+ if (it != ids.end())
+ card.set_billing_address_id(it->second);
+ }
+}
+
+} // namespace autofill
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
new file mode 100644
index 00000000000..c4893d7f57f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.h
@@ -0,0 +1,101 @@
+// 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_WEBDATA_AUTOFILL_SYNC_BRIDGE_UTIL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_SYNC_BRIDGE_UTIL_H_
+
+#include <memory>
+#include <string>
+
+#include "components/sync/model/entity_change.h"
+#include "components/sync/model/entity_data.h"
+
+namespace autofill {
+
+class AutofillProfile;
+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 wallet specifics id for the specified |server_id|.
+std::string GetSpecificsIdForEntryServerId(const std::string& server_id);
+
+// Returns the storage key for the specified |server_id|.
+std::string GetStorageKeyForSpecificsId(const std::string& specifics_id);
+
+// Returns the wallet specifics storage key for the specified |server_id|.
+std::string GetStorageKeyForEntryServerId(const std::string& server_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);
+
+// Sets the fields of the |wallet_specifics| based on the the specified
+// |address|.
+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);
+
+// Sets the fields of the |wallet_specifics| based on the the specified |card|.
+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);
+
+// Sets the fields of the |wallet_specifics| based on the specified
+// |customer_data|.
+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
+// server cards so that they don't get overwritten. This is because the wallet
+// data does not include those. They are handled by the
+// AutofillWalletMetadataSyncBridge.
+void CopyRelevantWalletMetadataFromDisk(
+ const AutofillTable& table,
+ std::vector<CreditCard>* cards_from_server);
+
+// Populates the wallet datatypes from the sync data and uses the sync data to
+// link the card to its billing address. If |wallet_addresses| is a nullptr,
+// this function will not extract addresses.
+void PopulateWalletTypesFromSyncData(
+ const ::syncer::EntityChangeList& entity_data,
+ std::vector<CreditCard>* wallet_cards,
+ std::vector<AutofillProfile>* wallet_addresses,
+ std::vector<PaymentsCustomerData>* customer_data);
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_SYNC_BRIDGE_UTIL_H_
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
new file mode 100644
index 00000000000..eb1f65eba3e
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.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/webdata/autofill_sync_bridge_util.h"
+
+#include <vector>
+
+#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/browser/payments/payments_customer_data.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_table.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/sync/base/hash_util.h"
+#include "components/sync/model/entity_data.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace {
+
+using syncer::EntityChange;
+using syncer::EntityData;
+
+class TestAutofillTable : public AutofillTable {
+ public:
+ explicit TestAutofillTable(std::vector<CreditCard> cards_on_disk)
+ : cards_on_disk_(cards_on_disk) {}
+
+ ~TestAutofillTable() override {}
+
+ bool GetServerCreditCards(
+ std::vector<std::unique_ptr<CreditCard>>* cards) const override {
+ for (const auto& card_on_disk : cards_on_disk_)
+ cards->push_back(std::make_unique<CreditCard>(card_on_disk));
+ return true;
+ }
+
+ private:
+ std::vector<CreditCard> cards_on_disk_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAutofillTable);
+};
+
+EntityData SpecificsToEntity(const sync_pb::AutofillWalletSpecifics& specifics,
+ const std::string& client_tag) {
+ EntityData data;
+ *data.specifics.mutable_autofill_wallet() = specifics;
+ data.client_tag_hash =
+ syncer::GenerateSyncableHash(syncer::AUTOFILL_WALLET_DATA, client_tag);
+ return data;
+}
+
+class AutofillSyncBridgeUtilTest : public testing::Test {
+ public:
+ AutofillSyncBridgeUtilTest() {}
+ ~AutofillSyncBridgeUtilTest() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AutofillSyncBridgeUtilTest);
+};
+
+// Tests that PopulateWalletTypesFromSyncData behaves as expected.
+TEST_F(AutofillSyncBridgeUtilTest, PopulateWalletTypesFromSyncData) {
+ // Add an address and a card that has its billing address id set to the
+ // address' id.
+ syncer::EntityChangeList entity_data;
+ std::string address_id("address1");
+ entity_data.push_back(EntityChange::CreateAdd(
+ address_id,
+ SpecificsToEntity(CreateAutofillWalletSpecificsForAddress(address_id),
+ /*client_tag=*/"address-address1")
+ .PassToPtr()));
+ entity_data.push_back(EntityChange::CreateAdd(
+ "card1",
+ SpecificsToEntity(CreateAutofillWalletSpecificsForCard(
+ /*id=*/"card1", /*billing_address_id=*/address_id),
+ /*client_tag=*/"card-card1")
+ .PassToPtr()));
+ entity_data.push_back(EntityChange::CreateAdd(
+ "deadbeef",
+ SpecificsToEntity(CreateAutofillWalletSpecificsForPaymentsCustomerData(
+ /*specifics_id=*/"deadbeef"),
+ /*client_tag=*/"customer-deadbeef")
+ .PassToPtr()));
+
+ std::vector<CreditCard> wallet_cards;
+ std::vector<AutofillProfile> wallet_addresses;
+ std::vector<PaymentsCustomerData> customer_data;
+ PopulateWalletTypesFromSyncData(entity_data, &wallet_cards, &wallet_addresses,
+ &customer_data);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+ ASSERT_EQ(1U, wallet_addresses.size());
+
+ EXPECT_EQ("deadbeef", customer_data.back().customer_id);
+
+ // Make sure the card's billing address id is equal to the address' server id.
+ EXPECT_EQ(wallet_addresses.back().server_id(),
+ wallet_cards.back().billing_address_id());
+}
+
+// Verify that the billing address id from the card saved on disk is kept if it
+// is a local profile guid.
+TEST_F(AutofillSyncBridgeUtilTest,
+ CopyRelevantWalletMetadataFromDisk_KeepLocalAddresses) {
+ std::vector<CreditCard> cards_on_disk;
+ std::vector<CreditCard> wallet_cards;
+
+ // Create a local profile to be used as a billing address.
+ AutofillProfile billing_address;
+
+ // Create a card on disk that refers to that local profile as its billing
+ // address.
+ cards_on_disk.push_back(CreditCard());
+ cards_on_disk.back().set_billing_address_id(billing_address.guid());
+
+ // Create a card pulled from wallet with the same id, but a different billing
+ // address id.
+ wallet_cards.push_back(CreditCard(cards_on_disk.back()));
+ wallet_cards.back().set_billing_address_id("1234");
+
+ // Setup the TestAutofillTable with the cards_on_disk.
+ TestAutofillTable table(cards_on_disk);
+
+ CopyRelevantWalletMetadataFromDisk(table, &wallet_cards);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // Make sure the wallet card replace its billing address id for the one that
+ // was saved on disk.
+ EXPECT_EQ(cards_on_disk.back().billing_address_id(),
+ wallet_cards.back().billing_address_id());
+}
+
+// Verify that the billing address id from the card saved on disk is overwritten
+// if it does not refer to a local profile.
+TEST_F(AutofillSyncBridgeUtilTest,
+ CopyRelevantWalletMetadataFromDisk_OverwriteOtherAddresses) {
+ std::string old_billing_id = "1234";
+ std::string new_billing_id = "9876";
+ std::vector<CreditCard> cards_on_disk;
+ std::vector<CreditCard> wallet_cards;
+
+ // Create a card on disk that does not refer to a local profile (which have 36
+ // chars ids).
+ cards_on_disk.push_back(CreditCard());
+ cards_on_disk.back().set_billing_address_id(old_billing_id);
+
+ // Create a card pulled from wallet with the same id, but a different billing
+ // address id.
+ wallet_cards.push_back(CreditCard(cards_on_disk.back()));
+ wallet_cards.back().set_billing_address_id(new_billing_id);
+
+ // Setup the TestAutofillTable with the cards_on_disk.
+ TestAutofillTable table(cards_on_disk);
+
+ CopyRelevantWalletMetadataFromDisk(table, &wallet_cards);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // Make sure the local address billing id that was saved on disk did not
+ // replace the new one.
+ EXPECT_EQ(new_billing_id, wallet_cards.back().billing_address_id());
+}
+
+// Verify that the use stats on disk are kept when server cards are synced.
+TEST_F(AutofillSyncBridgeUtilTest,
+ CopyRelevantWalletMetadataFromDisk_KeepUseStats) {
+ TestAutofillClock test_clock;
+ base::Time arbitrary_time = base::Time::FromDoubleT(25);
+ base::Time disk_time = base::Time::FromDoubleT(10);
+ test_clock.SetNow(arbitrary_time);
+
+ std::vector<CreditCard> cards_on_disk;
+ std::vector<CreditCard> wallet_cards;
+
+ // Create a card on disk with specific use stats.
+ cards_on_disk.push_back(CreditCard());
+ cards_on_disk.back().set_use_count(3U);
+ cards_on_disk.back().set_use_date(disk_time);
+
+ // Create a card pulled from wallet with the same id, but a different billing
+ // address id.
+ wallet_cards.push_back(CreditCard());
+ wallet_cards.back().set_use_count(10U);
+
+ // Setup the TestAutofillTable with the cards_on_disk.
+ TestAutofillTable table(cards_on_disk);
+
+ CopyRelevantWalletMetadataFromDisk(table, &wallet_cards);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // Make sure the use stats from disk were kept
+ EXPECT_EQ(3U, wallet_cards.back().use_count());
+ EXPECT_EQ(disk_time, wallet_cards.back().use_date());
+}
+
+} // namespace
+} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index e64990856d6..4c7baa94eb5 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -26,6 +26,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
@@ -194,7 +195,7 @@ std::unique_ptr<CreditCard> CreditCardFromStatement(
return credit_card;
}
-bool AddAutofillProfileNamesToProfile(sql::Connection* db,
+bool AddAutofillProfileNamesToProfile(sql::Database* db,
AutofillProfile* profile) {
// TODO(estade): update schema so that multiple names are not associated per
// unique profile guid. Please refer https://crbug.com/497934.
@@ -218,7 +219,7 @@ bool AddAutofillProfileNamesToProfile(sql::Connection* db,
return s.Succeeded();
}
-bool AddAutofillProfileEmailsToProfile(sql::Connection* db,
+bool AddAutofillProfileEmailsToProfile(sql::Database* db,
AutofillProfile* profile) {
// TODO(estade): update schema so that multiple emails are not associated per
// unique profile guid. Please refer https://crbug.com/497934.
@@ -236,7 +237,7 @@ bool AddAutofillProfileEmailsToProfile(sql::Connection* db,
return s.Succeeded();
}
-bool AddAutofillProfilePhonesToProfile(sql::Connection* db,
+bool AddAutofillProfilePhonesToProfile(sql::Database* db,
AutofillProfile* profile) {
// TODO(estade): update schema so that multiple phone numbers are not
// associated per unique profile guid. Please refer https://crbug.com/497934.
@@ -255,7 +256,7 @@ bool AddAutofillProfilePhonesToProfile(sql::Connection* db,
}
bool AddAutofillProfileNames(const AutofillProfile& profile,
- sql::Connection* db) {
+ sql::Database* db) {
// Add the new name.
sql::Statement s(db->GetUniqueStatement(
"INSERT INTO autofill_profile_names"
@@ -271,7 +272,7 @@ bool AddAutofillProfileNames(const AutofillProfile& profile,
}
bool AddAutofillProfileEmails(const AutofillProfile& profile,
- sql::Connection* db) {
+ sql::Database* db) {
// Add the new email.
sql::Statement s(db->GetUniqueStatement(
"INSERT INTO autofill_profile_emails (guid, email) VALUES (?,?)"));
@@ -282,7 +283,7 @@ bool AddAutofillProfileEmails(const AutofillProfile& profile,
}
bool AddAutofillProfilePhones(const AutofillProfile& profile,
- sql::Connection* db) {
+ sql::Database* db) {
// Add the new number.
sql::Statement s(db->GetUniqueStatement(
"INSERT INTO autofill_profile_phones (guid, number) VALUES (?,?)"));
@@ -293,7 +294,7 @@ bool AddAutofillProfilePhones(const AutofillProfile& profile,
}
bool AddAutofillProfilePieces(const AutofillProfile& profile,
- sql::Connection* db) {
+ sql::Database* db) {
if (!AddAutofillProfileNames(profile, db))
return false;
@@ -306,7 +307,7 @@ bool AddAutofillProfilePieces(const AutofillProfile& profile,
return true;
}
-bool RemoveAutofillProfilePieces(const std::string& guid, sql::Connection* db) {
+bool RemoveAutofillProfilePieces(const std::string& guid, sql::Database* db) {
sql::Statement s1(db->GetUniqueStatement(
"DELETE FROM autofill_profile_names WHERE guid = ?"));
s1.BindString(0, guid);
@@ -413,7 +414,7 @@ bool AutofillTable::CreateTablesIfNecessary() {
InitMaskedCreditCardsTable() && InitUnmaskedCreditCardsTable() &&
InitServerCardMetadataTable() && InitServerAddressesTable() &&
InitServerAddressMetadataTable() && InitAutofillSyncMetadataTable() &&
- InitModelTypeStateTable());
+ InitModelTypeStateTable() && InitPaymentsCustomerDataTable());
}
bool AutofillTable::IsSyncable() {
@@ -1345,6 +1346,39 @@ bool AutofillTable::UpdateServerAddressMetadata(
return db_->GetLastChangeCount() > 0;
}
+void AutofillTable::SetPaymentsCustomerData(
+ const PaymentsCustomerData* customer_data) {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return;
+
+ // Delete all old values.
+ sql::Statement customer_data_delete(
+ db_->GetUniqueStatement("DELETE FROM payments_customer_data"));
+ customer_data_delete.Run();
+
+ if (customer_data) {
+ sql::Statement insert_customer_data(db_->GetUniqueStatement(
+ "INSERT INTO payments_customer_data (customer_id) VALUES (?)"));
+ insert_customer_data.BindString(0, customer_data->customer_id);
+ insert_customer_data.Run();
+ }
+
+ transaction.Commit();
+}
+
+bool AutofillTable::GetPaymentsCustomerData(
+ std::unique_ptr<PaymentsCustomerData>* customer_data) const {
+ sql::Statement s(db_->GetUniqueStatement(
+ "SELECT customer_id FROM payments_customer_data"));
+ if (s.Step()) {
+ customer_data->reset(
+ new PaymentsCustomerData(/*customer_id=*/s.ColumnString(0)));
+ }
+
+ return s.Succeeded();
+}
+
bool AutofillTable::ClearAllServerData() {
sql::Transaction transaction(db_);
if (!transaction.Begin())
@@ -2393,7 +2427,9 @@ bool AutofillTable::AddFormFieldValueTime(const FormFieldData& element,
bool AutofillTable::SupportsMetadataForModelType(
syncer::ModelType model_type) const {
return (model_type == syncer::AUTOFILL ||
- model_type == syncer::AUTOFILL_PROFILE);
+ model_type == syncer::AUTOFILL_PROFILE ||
+ model_type == syncer::AUTOFILL_WALLET_DATA ||
+ model_type == syncer::AUTOFILL_WALLET_METADATA);
}
int AutofillTable::GetKeyValueForModelType(syncer::ModelType model_type) const {
@@ -2777,4 +2813,15 @@ bool AutofillTable::InitModelTypeStateTable() {
return true;
}
+bool AutofillTable::InitPaymentsCustomerDataTable() {
+ if (!db_->DoesTableExist("payments_customer_data")) {
+ if (!db_->Execute("CREATE TABLE payments_customer_data "
+ "(customer_id VARCHAR)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.h b/chromium/components/autofill/core/browser/webdata/autofill_table.h
index bb34d9c4d51..8708a94bf0a 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -33,6 +33,7 @@ class AutofillProfile;
class AutofillTableEncryptor;
class AutofillTableTest;
class CreditCard;
+struct PaymentsCustomerData;
struct FormFieldData;
@@ -263,6 +264,11 @@ struct FormFieldData;
// for one model type, there was an id column with value 1
// for the single entry.
// value The serialized ModelTypeState record.
+//
+// payments_customer_data
+// Contains Google Payments customer data.
+//
+// customer_id A string representing the Google Payments customer id.
class AutofillTable : public WebDatabaseTable,
public syncer::SyncMetadataStore {
@@ -398,6 +404,14 @@ class AutofillTable : public WebDatabaseTable,
bool UpdateServerCardMetadata(const CreditCard& credit_card);
bool UpdateServerAddressMetadata(const AutofillProfile& profile);
+ // Setters and getters related to the Google Payments customer data.
+ // Passing null to the setter will clear the data.
+ void SetPaymentsCustomerData(const PaymentsCustomerData* customer_data);
+ // Getter returns false if it could not execute the database statement, and
+ // may return true but leave |customer_data| untouched if there is no data.
+ bool GetPaymentsCustomerData(
+ std::unique_ptr<PaymentsCustomerData>* customer_data) const;
+
// Deletes all data from the server card and profile tables. Returns true if
// any data was deleted, false if not (so false means "commit not needed"
// rather than "error").
@@ -593,6 +607,7 @@ class AutofillTable : public WebDatabaseTable,
bool InitServerAddressMetadataTable();
bool InitAutofillSyncMetadataTable();
bool InitModelTypeStateTable();
+ bool InitPaymentsCustomerDataTable();
std::unique_ptr<AutofillTableEncryptor> autofill_table_encryptor_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index 283dcc5c327..a12b8bcf152 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -24,6 +24,7 @@
#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/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_constants.h"
@@ -2234,6 +2235,39 @@ TEST_F(AutofillTableTest, DeleteUnmaskedCard) {
outputs.clear();
}
+// Test that we can get what we set.
+TEST_F(AutofillTableTest, SetGetPaymentsCustomerData) {
+ PaymentsCustomerData input{/*customer_id=*/"deadbeef"};
+ table_->SetPaymentsCustomerData(&input);
+
+ std::unique_ptr<PaymentsCustomerData> output;
+ ASSERT_TRUE(table_->GetPaymentsCustomerData(&output));
+ EXPECT_EQ(input, *output);
+}
+
+// We don't set anything in the table. Test that we don't crash.
+TEST_F(AutofillTableTest, GetPaymentsCustomerData_NoData) {
+ std::unique_ptr<PaymentsCustomerData> output;
+ ASSERT_TRUE(table_->GetPaymentsCustomerData(&output));
+ EXPECT_FALSE(output);
+}
+
+// The latest PaymentsCustomerData that was set is returned.
+TEST_F(AutofillTableTest, SetGetPaymentsCustomerData_MultipleSet) {
+ PaymentsCustomerData input{/*customer_id=*/"deadbeef"};
+ table_->SetPaymentsCustomerData(&input);
+
+ PaymentsCustomerData input2{/*customer_id=*/"wallet"};
+ table_->SetPaymentsCustomerData(&input2);
+
+ PaymentsCustomerData input3{/*customer_id=*/"latest"};
+ table_->SetPaymentsCustomerData(&input3);
+
+ std::unique_ptr<PaymentsCustomerData> output;
+ ASSERT_TRUE(table_->GetPaymentsCustomerData(&output));
+ EXPECT_EQ(input3, *output);
+}
+
const size_t kMaxCount = 2;
struct GetFormValuesTestCase {
const char* const field_suggestion[kMaxCount];
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
new file mode 100644
index 00000000000..7f2c27615aa
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc
@@ -0,0 +1,327 @@
+// 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/webdata/autofill_wallet_metadata_sync_bridge.h"
+
+#include <unordered_map>
+#include <utility>
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "base/optional.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.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/autofill_webdata_backend.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.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"
+#include "components/sync/model_impl/sync_metadata_store_change_list.h"
+
+namespace autofill {
+
+namespace {
+
+using sync_pb::WalletMetadataSpecifics;
+using syncer::EntityData;
+using syncer::MetadataChangeList;
+
+// Address to this variable used as the user data key.
+static int kAutofillWalletMetadataSyncBridgeUserDataKey = 0;
+
+std::string GetClientTagForSpecificsId(WalletMetadataSpecifics::Type type,
+ const std::string& specifics_id) {
+ switch (type) {
+ case WalletMetadataSpecifics::ADDRESS:
+ return "address-" + specifics_id;
+ case WalletMetadataSpecifics::CARD:
+ return "card-" + specifics_id;
+ case WalletMetadataSpecifics::UNKNOWN:
+ NOTREACHED();
+ return "";
+ }
+}
+
+// Returns EntityData with common fields set based on |local_data_model|.
+std::unique_ptr<EntityData> CreateEntityDataFromAutofillDataModel(
+ const AutofillDataModel& local_data_model,
+ WalletMetadataSpecifics::Type type,
+ const std::string& specifics_id) {
+ auto entity_data = std::make_unique<EntityData>();
+ entity_data->non_unique_name = GetClientTagForSpecificsId(type, specifics_id);
+
+ WalletMetadataSpecifics* metadata =
+ entity_data->specifics.mutable_wallet_metadata();
+ metadata->set_type(type);
+ metadata->set_id(specifics_id);
+ metadata->set_use_count(local_data_model.use_count());
+ metadata->set_use_date(
+ local_data_model.use_date().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ return entity_data;
+}
+
+// Returns EntityData for wallet_metadata for |local_profile|.
+std::unique_ptr<EntityData> CreateMetadataEntityDataFromAutofillServerProfile(
+ const AutofillProfile& local_profile) {
+ std::unique_ptr<EntityData> entity_data =
+ CreateEntityDataFromAutofillDataModel(
+ local_profile, WalletMetadataSpecifics::ADDRESS,
+ GetSpecificsIdForEntryServerId(local_profile.server_id()));
+
+ WalletMetadataSpecifics* metadata =
+ entity_data->specifics.mutable_wallet_metadata();
+ metadata->set_address_has_converted(local_profile.has_converted());
+ return entity_data;
+}
+
+// Returns EntityData for wallet_metadata for |local_card|.
+std::unique_ptr<EntityData> CreateMetadataEntityDataFromCard(
+ const CreditCard& local_card) {
+ std::unique_ptr<EntityData> entity_data =
+ CreateEntityDataFromAutofillDataModel(
+ local_card, WalletMetadataSpecifics::CARD,
+ GetSpecificsIdForEntryServerId(local_card.server_id()));
+
+ WalletMetadataSpecifics* metadata =
+ entity_data->specifics.mutable_wallet_metadata();
+ // The strings must be in valid UTF-8 to sync.
+ std::string billing_address_id;
+ base::Base64Encode(local_card.billing_address_id(), &billing_address_id);
+ metadata->set_card_billing_address_id(billing_address_id);
+ return entity_data;
+}
+
+} // namespace
+
+// static
+void AutofillWalletMetadataSyncBridge::CreateForWebDataServiceAndBackend(
+ const std::string& app_locale,
+ AutofillWebDataBackend* web_data_backend,
+ AutofillWebDataService* web_data_service) {
+ web_data_service->GetDBUserData()->SetUserData(
+ &kAutofillWalletMetadataSyncBridgeUserDataKey,
+ std::make_unique<AutofillWalletMetadataSyncBridge>(
+ std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+ syncer::AUTOFILL_WALLET_METADATA,
+ /*dump_stack=*/base::RepeatingClosure()),
+ web_data_backend));
+}
+
+// static
+syncer::ModelTypeSyncBridge*
+AutofillWalletMetadataSyncBridge::FromWebDataService(
+ AutofillWebDataService* web_data_service) {
+ return static_cast<AutofillWalletMetadataSyncBridge*>(
+ web_data_service->GetDBUserData()->GetUserData(
+ &kAutofillWalletMetadataSyncBridgeUserDataKey));
+}
+
+AutofillWalletMetadataSyncBridge::AutofillWalletMetadataSyncBridge(
+ std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
+ AutofillWebDataBackend* web_data_backend)
+ : ModelTypeSyncBridge(std::move(change_processor)),
+ web_data_backend_(web_data_backend),
+ scoped_observer_(this) {
+ DCHECK(web_data_backend_);
+
+ scoped_observer_.Add(web_data_backend_);
+
+ LoadDataCacheAndMetadata();
+}
+
+AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() {}
+
+std::unique_ptr<syncer::MetadataChangeList>
+AutofillWalletMetadataSyncBridge::CreateMetadataChangeList() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return std::make_unique<syncer::SyncMetadataStoreChangeList>(
+ GetAutofillTable(), syncer::AUTOFILL_WALLET_METADATA);
+}
+
+base::Optional<syncer::ModelError>
+AutofillWalletMetadataSyncBridge::MergeSyncData(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) {
+ NOTIMPLEMENTED();
+ return base::nullopt;
+}
+
+base::Optional<syncer::ModelError>
+AutofillWalletMetadataSyncBridge::ApplySyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) {
+ NOTIMPLEMENTED();
+ return base::nullopt;
+}
+
+void AutofillWalletMetadataSyncBridge::GetData(StorageKeyList storage_keys,
+ DataCallback callback) {
+ // Build a set out of the list to allow quick lookup.
+ std::unordered_set<std::string> storage_keys_set(storage_keys.begin(),
+ storage_keys.end());
+ GetDataImpl(std::move(storage_keys_set), std::move(callback));
+}
+
+void AutofillWalletMetadataSyncBridge::GetAllDataForDebugging(
+ DataCallback callback) {
+ // Get all data by not providing any |storage_keys| filter.
+ GetDataImpl(/*storage_keys=*/base::nullopt, std::move(callback));
+}
+
+std::string AutofillWalletMetadataSyncBridge::GetClientTag(
+ const syncer::EntityData& entity_data) {
+ const WalletMetadataSpecifics& remote_metadata =
+ entity_data.specifics.wallet_metadata();
+ return GetClientTagForSpecificsId(remote_metadata.type(),
+ remote_metadata.id());
+}
+
+std::string AutofillWalletMetadataSyncBridge::GetStorageKey(
+ const syncer::EntityData& entity_data) {
+ return GetStorageKeyForSpecificsId(
+ 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) {
+ 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));
+}
+
+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());
+ }
+}
+
+AutofillTable* AutofillWalletMetadataSyncBridge::GetAutofillTable() {
+ return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase());
+}
+
+void AutofillWalletMetadataSyncBridge::LoadDataCacheAndMetadata() {
+ if (!web_data_backend_ || !web_data_backend_->GetDatabase() ||
+ !GetAutofillTable()) {
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed to load AutofillWebDatabase."});
+ 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)) {
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed reading autofill data from WebDatabase."});
+ return;
+ }
+ for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
+ cache_[GetStorageKeyForEntryServerId(entry->server_id())] =
+ CreateMetadataEntityDataFromAutofillServerProfile(*entry)
+ ->specifics.wallet_metadata();
+ }
+ for (const std::unique_ptr<CreditCard>& entry : cards) {
+ cache_[GetStorageKeyForEntryServerId(entry->server_id())] =
+ CreateMetadataEntityDataFromCard(*entry)->specifics.wallet_metadata();
+ }
+
+ // Load the metadata and send to the processor.
+ auto batch = std::make_unique<syncer::MetadataBatch>();
+ if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL_WALLET_METADATA,
+ batch.get())) {
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed reading autofill metadata from WebDatabase."});
+ return;
+ }
+
+ change_processor()->ModelReadyToSync(std::move(batch));
+}
+
+void AutofillWalletMetadataSyncBridge::GetDataImpl(
+ base::Optional<std::unordered_set<std::string>> storage_keys_set,
+ 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 = GetStorageKeyForEntryServerId(entry->server_id());
+ if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) {
+ batch->Put(key,
+ CreateMetadataEntityDataFromAutofillServerProfile(*entry));
+ }
+ }
+ for (const std::unique_ptr<CreditCard>& entry : cards) {
+ std::string key = GetStorageKeyForEntryServerId(entry->server_id());
+ if (!storage_keys_set || base::ContainsKey(*storage_keys_set, key)) {
+ batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
+ CreateMetadataEntityDataFromCard(*entry));
+ }
+ }
+
+ std::move(callback).Run(std::move(batch));
+}
+
+} // 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
new file mode 100644
index 00000000000..00479c19c84
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h
@@ -0,0 +1,114 @@
+// 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_WEBDATA_AUTOFILL_WALLET_METADATA_SYNC_BRIDGE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_METADATA_SYNC_BRIDGE_H_
+
+#include <memory>
+#include <string>
+#include <unordered_set>
+
+#include "base/macros.h"
+#include "base/scoped_observer.h"
+#include "base/sequence_checker.h"
+#include "base/supports_user_data.h"
+#include "components/autofill/core/browser/webdata/autofill_change.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
+#include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_error.h"
+#include "components/sync/model/model_type_change_processor.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+
+namespace syncer {
+struct EntityData;
+} // namespace syncer
+
+namespace autofill {
+
+class AutofillTable;
+class AutofillWebDataBackend;
+class AutofillWebDataService;
+
+// Sync bridge responsible for propagating local changes to the processor and
+// applying remote changes to the local database.
+class AutofillWalletMetadataSyncBridge
+ : public base::SupportsUserData::Data,
+ public syncer::ModelTypeSyncBridge,
+ public AutofillWebDataServiceObserverOnDBSequence {
+ public:
+ // Factory method that hides dealing with change_processor and also stores the
+ // created bridge within |web_data_service|. This method should only be
+ // called on |web_data_service|'s DB thread.
+ static void CreateForWebDataServiceAndBackend(
+ const std::string& app_locale,
+ AutofillWebDataBackend* webdata_backend,
+ AutofillWebDataService* web_data_service);
+
+ static syncer::ModelTypeSyncBridge* FromWebDataService(
+ AutofillWebDataService* web_data_service);
+
+ AutofillWalletMetadataSyncBridge(
+ std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
+ AutofillWebDataBackend* web_data_backend);
+ ~AutofillWalletMetadataSyncBridge() override;
+
+ // ModelTypeSyncBridge implementation.
+ std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+ override;
+ base::Optional<syncer::ModelError> MergeSyncData(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) override;
+ base::Optional<syncer::ModelError> ApplySyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_changes) override;
+ void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+ void GetAllDataForDebugging(DataCallback callback) override;
+ std::string GetClientTag(const syncer::EntityData& entity_data) override;
+ std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+
+ // 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.
+ void LoadDataCacheAndMetadata();
+
+ // Reads local wallet metadata from the database and passes them into
+ // |callback|. If |storage_keys_set| is not set, it returns all data entries.
+ // Otherwise, it returns only entries with storage key in |storage_keys_set|.
+ void GetDataImpl(
+ base::Optional<std::unordered_set<std::string>> storage_keys_set,
+ DataCallback callback);
+
+ // AutofillWalletMetadataSyncBridge is owned by |web_data_backend_| through
+ // SupportsUserData, so it's guaranteed to outlive |this|.
+ AutofillWebDataBackend* const web_data_backend_;
+
+ 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_;
+
+ // The bridge should be used on the same sequence where it is constructed.
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillWalletMetadataSyncBridge);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_METADATA_SYNC_BRIDGE_H_
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
new file mode 100644
index 00000000000..435e7950da4
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc
@@ -0,0 +1,500 @@
+// 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/webdata/autofill_wallet_metadata_sync_bridge.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <sstream>
+#include <utility>
+
+#include "base/base64.h"
+#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/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/country_names.h"
+#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_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/sync/base/hash_util.h"
+#include "components/sync/model/data_batch.h"
+#include "components/sync/model/entity_data.h"
+#include "components/sync/model/mock_model_type_change_processor.h"
+#include "components/sync/model_impl/client_tag_based_model_type_processor.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/webdata/common/web_database.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace {
+
+using base::ScopedTempDir;
+using sync_pb::WalletMetadataSpecifics;
+using syncer::DataBatch;
+using syncer::EntityData;
+using syncer::EntityDataPtr;
+using syncer::KeyAndData;
+using syncer::MockModelTypeChangeProcessor;
+using syncer::ModelType;
+using testing::_;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::UnorderedElementsAre;
+
+// Non-UTF8 server IDs.
+const char kAddr1ServerId[] = "addr1\xEF\xBF\xBE";
+const char kAddr2ServerId[] = "addr2\xEF\xBF\xBE";
+const char kCard1ServerId[] = "card1\xEF\xBF\xBE";
+const char kCard2ServerId[] = "card2\xEF\xBF\xBE";
+
+// Base64 encodings of the server IDs, used as ids in WalletMetadataSpecifics
+// (these are suitable for syncing, because they are valid UTF-8).
+const char kAddr1SpecificsId[] = "YWRkcjHvv74=";
+const char kAddr2SpecificsId[] = "YWRkcjLvv74=";
+const char kCard1SpecificsId[] = "Y2FyZDHvv74=";
+const char kCard2SpecificsId[] = "Y2FyZDLvv74=";
+
+// Unique sync tags for the server IDs.
+const char kAddr1SyncTag[] = "address-YWRkcjHvv74=";
+const char kCard1SyncTag[] = "card-Y2FyZDHvv74=";
+
+const char kLocaleString[] = "en-US";
+const base::Time kJune2017 = base::Time::FromDoubleT(1497552271);
+
+class FakeAutofillBackend : public AutofillWebDataBackend {
+ public:
+ FakeAutofillBackend() {}
+ ~FakeAutofillBackend() override {}
+ WebDatabase* GetDatabase() override { return db_; }
+ void AddObserver(
+ autofill::AutofillWebDataServiceObserverOnDBSequence* observer) override {
+ }
+ void RemoveObserver(
+ autofill::AutofillWebDataServiceObserverOnDBSequence* observer) override {
+ }
+ void RemoveExpiredFormElements() override {}
+ void NotifyOfMultipleAutofillChanges() override {}
+ void NotifyThatSyncHasStarted(ModelType model_type) override {}
+ void SetWebDatabase(WebDatabase* db) { db_ = db; }
+
+ private:
+ WebDatabase* db_;
+};
+
+base::Time UseDateFromProtoValue(int64_t use_date_proto_value) {
+ return base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(use_date_proto_value));
+}
+
+int64_t UseDateToProtoValue(base::Time use_date) {
+ return use_date.ToDeltaSinceWindowsEpoch().InMicroseconds();
+}
+
+WalletMetadataSpecifics CreateWalletMetadataSpecificsForAddressWithUseStats(
+ const std::string& specifics_id,
+ size_t use_count,
+ int64_t use_date) {
+ WalletMetadataSpecifics specifics;
+ specifics.set_id(specifics_id);
+ specifics.set_type(WalletMetadataSpecifics::ADDRESS);
+ specifics.set_use_count(use_count);
+ specifics.set_use_date(use_date);
+ // Set the default value according to the constructor of AutofillProfile.
+ specifics.set_address_has_converted(false);
+ return specifics;
+}
+
+WalletMetadataSpecifics CreateWalletMetadataSpecificsForAddress(
+ const std::string& specifics_id) {
+ // Set default values according to the constructor of AutofillProfile (the
+ // clock value is overrided by TestAutofillClock in the test fixture).
+ return CreateWalletMetadataSpecificsForAddressWithUseStats(
+ specifics_id, /*use_count=*/1,
+ /*use_date=*/UseDateToProtoValue(kJune2017));
+}
+
+WalletMetadataSpecifics CreateWalletMetadataSpecificsForCardWithUseStats(
+ const std::string& specifics_id,
+ size_t use_count,
+ int64_t use_date) {
+ WalletMetadataSpecifics specifics;
+ specifics.set_id(specifics_id);
+ specifics.set_type(WalletMetadataSpecifics::CARD);
+ specifics.set_use_count(use_count);
+ specifics.set_use_date(use_date);
+ // Set the default value according to the constructor of AutofillProfile.
+ specifics.set_card_billing_address_id("");
+ return specifics;
+}
+
+WalletMetadataSpecifics CreateWalletMetadataSpecificsForCard(
+ const std::string& specifics_id) {
+ // Set default values according to the constructor of AutofillProfile (the
+ // clock value is overrided by TestAutofillClock in the test fixture).
+ return CreateWalletMetadataSpecificsForCardWithUseStats(
+ specifics_id, /*use_count=*/1,
+ /*use_date=*/UseDateToProtoValue(kJune2017));
+}
+
+AutofillProfile CreateServerProfileWithUseStats(const std::string& server_id,
+ size_t use_count,
+ int64_t use_date) {
+ AutofillProfile profile = CreateServerProfile(server_id);
+ profile.set_use_count(use_count);
+ profile.set_use_date(UseDateFromProtoValue(use_date));
+ return profile;
+}
+
+CreditCard CreateServerCreditCardWithUseStats(const std::string& server_id,
+ size_t use_count,
+ int64_t use_date) {
+ CreditCard card = CreateServerCreditCard(server_id);
+ card.set_use_count(use_count);
+ card.set_use_date(UseDateFromProtoValue(use_date));
+ return card;
+}
+
+void ExtractWalletMetadataSpecificsFromDataBatch(
+ std::unique_ptr<DataBatch> batch,
+ std::vector<WalletMetadataSpecifics>* output) {
+ while (batch->HasNext()) {
+ const KeyAndData& data_pair = batch->Next();
+ output->push_back(data_pair.second->specifics.wallet_metadata());
+ }
+}
+
+std::string WalletMetadataSpecificsAsDebugString(
+ const WalletMetadataSpecifics& specifics) {
+ std::ostringstream output;
+ output << "[id: " << specifics.id()
+ << ", type: " << static_cast<int>(specifics.type())
+ << ", use_count: " << specifics.use_count()
+ << ", use_date: " << UseDateFromProtoValue(specifics.use_date())
+ << ", card_billing_address_id: "
+ << (specifics.has_card_billing_address_id()
+ ? specifics.card_billing_address_id()
+ : "not_set")
+ << ", address_has_converted: "
+ << (specifics.has_address_has_converted()
+ ? (specifics.address_has_converted() ? "true" : "false")
+ : "not_set")
+ << "]";
+ return output.str();
+}
+
+MATCHER_P(EqualsSpecifics, expected, "") {
+ if (arg.SerializeAsString() != expected.SerializeAsString()) {
+ *result_listener << "entry\n"
+ << WalletMetadataSpecificsAsDebugString(arg) << "\n"
+ << "did not match expected\n"
+ << WalletMetadataSpecificsAsDebugString(expected);
+ return false;
+ }
+ return true;
+}
+
+MATCHER_P(HasSpecifics, expected, "") {
+ const WalletMetadataSpecifics& arg_specifics =
+ arg->specifics.wallet_metadata();
+
+ if (arg_specifics.SerializeAsString() != expected.SerializeAsString()) {
+ *result_listener << "entry\n"
+ << WalletMetadataSpecificsAsDebugString(arg_specifics)
+ << "\ndid not match expected\n"
+ << WalletMetadataSpecificsAsDebugString(expected);
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+class AutofillWalletMetadataSyncBridgeTest : public testing::Test {
+ public:
+ AutofillWalletMetadataSyncBridgeTest() {}
+ ~AutofillWalletMetadataSyncBridgeTest() override {}
+
+ void SetUp() override {
+ // Fix a time for implicitly constructed use_dates in AutofillProfile.
+ test_clock_.SetNow(kJune2017);
+ CountryNames::SetLocaleString(kLocaleString);
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ db_.AddTable(&table_);
+ db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase"));
+ backend_.SetWebDatabase(&db_);
+ ResetProcessor();
+ }
+
+ void ResetProcessor() {
+ real_processor_ =
+ std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+ syncer::AUTOFILL_WALLET_METADATA, /*dump_stack=*/base::DoNothing(),
+ /*commit_only=*/false);
+ mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
+ }
+
+ void ResetBridge() {
+ bridge_.reset(new AutofillWalletMetadataSyncBridge(
+ mock_processor_.CreateForwardingProcessor(), &backend_));
+ }
+
+ EntityData SpecificsToEntity(const WalletMetadataSpecifics& specifics) {
+ EntityData data;
+ *data.specifics.mutable_wallet_metadata() = specifics;
+ data.client_tag_hash = syncer::GenerateSyncableHash(
+ syncer::AUTOFILL_WALLET_METADATA, bridge()->GetClientTag(data));
+ return data;
+ }
+
+ std::vector<WalletMetadataSpecifics> GetAllLocalData() {
+ std::vector<WalletMetadataSpecifics> data;
+ // Perform an async call synchronously for testing.
+ base::RunLoop loop;
+ bridge()->GetAllDataForDebugging(base::BindLambdaForTesting(
+ [&loop, &data](std::unique_ptr<DataBatch> batch) {
+ ExtractWalletMetadataSpecificsFromDataBatch(std::move(batch), &data);
+ loop.Quit();
+ }));
+ loop.Run();
+ return data;
+ }
+
+ std::vector<WalletMetadataSpecifics> GetLocalData(
+ AutofillWalletMetadataSyncBridge::StorageKeyList storage_keys) {
+ std::vector<WalletMetadataSpecifics> data;
+ // Perform an async call synchronously for testing.
+ base::RunLoop loop;
+ bridge()->GetData(storage_keys,
+ base::BindLambdaForTesting(
+ [&loop, &data](std::unique_ptr<DataBatch> batch) {
+ ExtractWalletMetadataSpecificsFromDataBatch(
+ std::move(batch), &data);
+ loop.Quit();
+ }));
+ loop.Run();
+ return data;
+ }
+
+ AutofillWalletMetadataSyncBridge* bridge() { return bridge_.get(); }
+
+ syncer::MockModelTypeChangeProcessor& mock_processor() {
+ return mock_processor_;
+ }
+
+ AutofillTable* table() { return &table_; }
+
+ FakeAutofillBackend* backend() { return &backend_; }
+
+ private:
+ autofill::TestAutofillClock test_clock_;
+ ScopedTempDir temp_dir_;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ FakeAutofillBackend backend_;
+ AutofillTable table_;
+ WebDatabase db_;
+ testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
+ std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_;
+ std::unique_ptr<AutofillWalletMetadataSyncBridge> bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillWalletMetadataSyncBridgeTest);
+};
+
+// The following 2 tests make sure client tags stay stable.
+TEST_F(AutofillWalletMetadataSyncBridgeTest, GetClientTagForAddress) {
+ ResetBridge();
+ WalletMetadataSpecifics specifics =
+ CreateWalletMetadataSpecificsForAddress(kAddr1SpecificsId);
+ EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
+ kAddr1SyncTag);
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest, GetClientTagForCard) {
+ ResetBridge();
+ WalletMetadataSpecifics specifics =
+ CreateWalletMetadataSpecificsForCard(kCard1SpecificsId);
+ EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
+ kCard1SyncTag);
+}
+
+// The following 2 tests make sure storage keys stay stable.
+TEST_F(AutofillWalletMetadataSyncBridgeTest, GetStorageKeyForAddress) {
+ ResetBridge();
+ WalletMetadataSpecifics specifics =
+ CreateWalletMetadataSpecificsForAddress(kAddr1SpecificsId);
+ EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics)),
+ kAddr1SpecificsId);
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest, GetStorageKeyForCard) {
+ ResetBridge();
+ WalletMetadataSpecifics specifics =
+ CreateWalletMetadataSpecificsForCard(kCard1SpecificsId);
+ EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics)),
+ kCard1SpecificsId);
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ GetAllDataForDebugging_ShouldReturnAllData) {
+ table()->SetServerProfiles({CreateServerProfile(kAddr1ServerId),
+ CreateServerProfile(kAddr2ServerId)});
+ table()->SetServerCreditCards({CreateServerCreditCard(kCard1ServerId),
+ CreateServerCreditCard(kCard2ServerId)});
+ ResetBridge();
+
+ EXPECT_THAT(
+ GetAllLocalData(),
+ UnorderedElementsAre(
+ EqualsSpecifics(
+ CreateWalletMetadataSpecificsForAddress(kAddr1SpecificsId)),
+ EqualsSpecifics(
+ CreateWalletMetadataSpecificsForAddress(kAddr2SpecificsId)),
+ EqualsSpecifics(
+ CreateWalletMetadataSpecificsForCard(kCard1SpecificsId)),
+ EqualsSpecifics(
+ CreateWalletMetadataSpecificsForCard(kCard2SpecificsId))));
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ GetData_ShouldNotReturnNonexistentData) {
+ ResetBridge();
+ EXPECT_THAT(GetLocalData({kAddr1SpecificsId}), IsEmpty());
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnSelectedData) {
+ table()->SetServerProfiles({CreateServerProfile(kAddr1ServerId),
+ CreateServerProfile(kAddr2ServerId)});
+ table()->SetServerCreditCards({CreateServerCreditCard(kCard1ServerId),
+ CreateServerCreditCard(kCard2ServerId)});
+ ResetBridge();
+
+ EXPECT_THAT(GetLocalData({kAddr1SpecificsId, kCard1SpecificsId}),
+ UnorderedElementsAre(
+ EqualsSpecifics(CreateWalletMetadataSpecificsForAddress(
+ kAddr1SpecificsId)),
+ EqualsSpecifics(CreateWalletMetadataSpecificsForCard(
+ kCard1SpecificsId))));
+}
+
+TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnCompleteData) {
+ AutofillProfile profile = CreateServerProfile(kAddr1ServerId);
+ profile.set_use_count(5);
+ profile.set_use_date(UseDateFromProtoValue(2));
+ profile.set_has_converted(true);
+ table()->SetServerProfiles({profile});
+
+ CreditCard card = CreateServerCreditCard(kCard1ServerId);
+ card.set_use_count(6);
+ card.set_use_date(UseDateFromProtoValue(3));
+ card.set_billing_address_id(kAddr1ServerId);
+ table()->SetServerCreditCards({card});
+ ResetBridge();
+
+ // Expect to retrieve following specifics:
+ WalletMetadataSpecifics profile_specifics =
+ CreateWalletMetadataSpecificsForAddress(kAddr1SpecificsId);
+ profile_specifics.set_use_count(5);
+ profile_specifics.set_use_date(2);
+ profile_specifics.set_address_has_converted(true);
+
+ WalletMetadataSpecifics card_specifics =
+ CreateWalletMetadataSpecificsForCard(kCard1SpecificsId);
+ card_specifics.set_use_count(6);
+ card_specifics.set_use_date(3);
+ card_specifics.set_card_billing_address_id(kAddr1SpecificsId);
+
+ EXPECT_THAT(GetLocalData({kAddr1SpecificsId, kCard1SpecificsId}),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics),
+ EqualsSpecifics(card_specifics)));
+}
+
+// Verify that lower values of metadata are not sent to the sync server when
+// local metadata is updated.
+TEST_F(AutofillWalletMetadataSyncBridgeTest,
+ DontSendLowerValueToServerOnSingleChange) {
+ table()->SetServerProfiles({CreateServerProfileWithUseStats(
+ kAddr1ServerId, /*use_count=*/2, /*use_date=*/5)});
+ table()->SetServerCreditCards({CreateServerCreditCardWithUseStats(
+ kCard1ServerId, /*use_count=*/3, /*use_date=*/6)});
+ ResetBridge();
+
+ AutofillProfile updated_profile = CreateServerProfileWithUseStats(
+ kAddr1ServerId, /*use_count=*/1, /*use_date=*/4);
+ CreditCard updated_card = CreateServerCreditCardWithUseStats(
+ kCard1ServerId, /*use_count=*/2, /*use_date=*/5);
+
+ EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
+
+ bridge()->AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, updated_profile.guid(), &updated_profile));
+ bridge()->CreditCardChanged(CreditCardChange(
+ CreditCardChange::UPDATE, updated_card.guid(), &updated_card));
+}
+
+// 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) {
+ table()->SetServerProfiles({CreateServerProfileWithUseStats(
+ kAddr1ServerId, /*use_count=*/1, /*use_date=*/2)});
+ table()->SetServerCreditCards({CreateServerCreditCardWithUseStats(
+ kCard1ServerId, /*use_count=*/3, /*use_date=*/4)});
+ ResetBridge();
+
+ AutofillProfile new_profile = CreateServerProfileWithUseStats(
+ kAddr2ServerId, /*use_count=*/10, /*use_date=*/20);
+ CreditCard new_card = CreateServerCreditCardWithUseStats(
+ kCard2ServerId, /*use_count=*/30, /*use_date=*/40);
+
+ EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0);
+
+ bridge()->AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, new_profile.guid(), &new_profile));
+ bridge()->CreditCardChanged(
+ CreditCardChange(CreditCardChange::UPDATE, new_card.guid(), &new_card));
+}
+
+// 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)});
+ 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(kAddr1SpecificsId, HasSpecifics(expected_profile_specifics), _));
+ EXPECT_CALL(mock_processor(),
+ Put(kCard1SpecificsId, HasSpecifics(expected_card_specifics), _));
+
+ bridge()->AutofillProfileChanged(AutofillProfileChange(
+ AutofillProfileChange::UPDATE, updated_profile.guid(), &updated_profile));
+ bridge()->CreditCardChanged(CreditCardChange(
+ CreditCardChange::UPDATE, updated_card.guid(), &updated_card));
+}
+
+} // 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 a1720b4f461..1d447d7d198 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
@@ -22,6 +22,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/sync_change.h"
#include "components/sync/model/sync_change_processor.h"
#include "components/sync/model/sync_data.h"
@@ -32,11 +33,7 @@ namespace autofill {
namespace {
-// The length of the GUIDs used for local autofill data. It is different than
-// the length used for server autofill data.
-const int kLocalGuidSize = 36;
-
-void* UserDataKey() {
+void* AutofillWalletMetadataSyncableServiceUserDataKey() {
// Use the address of a static so that COMDAT folding won't ever fold
// with something else.
static int user_data_key = 0;
@@ -499,8 +496,9 @@ void AutofillWalletMetadataSyncableService::CreateForWebDataServiceAndBackend(
AutofillWebDataBackend* web_data_backend,
const std::string& app_locale) {
web_data_service->GetDBUserData()->SetUserData(
- UserDataKey(), base::WrapUnique(new AutofillWalletMetadataSyncableService(
- web_data_backend, app_locale)));
+ AutofillWalletMetadataSyncableServiceUserDataKey(),
+ base::WrapUnique(new AutofillWalletMetadataSyncableService(
+ web_data_backend, app_locale)));
}
// static
@@ -508,7 +506,8 @@ AutofillWalletMetadataSyncableService*
AutofillWalletMetadataSyncableService::FromWebDataService(
AutofillWebDataService* web_data_service) {
return static_cast<AutofillWalletMetadataSyncableService*>(
- web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+ web_data_service->GetDBUserData()->GetUserData(
+ AutofillWalletMetadataSyncableServiceUserDataKey()));
}
AutofillWalletMetadataSyncableService::AutofillWalletMetadataSyncableService(
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
new file mode 100644
index 00000000000..857c76e1c55
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc
@@ -0,0 +1,452 @@
+// 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/webdata/autofill_wallet_sync_bridge.h"
+
+#include <utility>
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_profile_sync_util.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.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/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/sync_merge_result.h"
+#include "components/sync/model_impl/client_tag_based_model_type_processor.h"
+#include "components/sync/model_impl/sync_metadata_store_change_list.h"
+
+using sync_pb::AutofillWalletSpecifics;
+using syncer::EntityData;
+
+namespace autofill {
+namespace {
+
+// Address to this variable used as the user data key.
+static int kAutofillWalletSyncBridgeUserDataKey = 0;
+
+std::string GetSpecificsIdFromAutofillWalletSpecifics(
+ const AutofillWalletSpecifics& specifics) {
+ switch (specifics.type()) {
+ case AutofillWalletSpecifics::MASKED_CREDIT_CARD:
+ return specifics.masked_card().id();
+ case AutofillWalletSpecifics::POSTAL_ADDRESS:
+ return specifics.address().id();
+ case AutofillWalletSpecifics::CUSTOMER_DATA:
+ return specifics.customer_data().id();
+ case AutofillWalletSpecifics::UNKNOWN:
+ NOTREACHED();
+ return std::string();
+ }
+ return std::string();
+}
+
+std::string GetClientTagForWalletDataSpecificsId(
+ const std::string& specifics_id) {
+ // Unlike for the wallet_metadata model type, the wallet_data expects
+ // specifics id directly as client tags.
+ return specifics_id;
+}
+
+} // namespace
+
+// static
+void AutofillWalletSyncBridge::CreateForWebDataServiceAndBackend(
+ const std::string& app_locale,
+ bool has_persistent_storage,
+ AutofillWebDataBackend* web_data_backend,
+ AutofillWebDataService* web_data_service) {
+ web_data_service->GetDBUserData()->SetUserData(
+ &kAutofillWalletSyncBridgeUserDataKey,
+ std::make_unique<AutofillWalletSyncBridge>(
+ std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+ syncer::AUTOFILL_WALLET_DATA,
+ /*dump_stack=*/base::RepeatingClosure()),
+ has_persistent_storage, web_data_backend));
+}
+
+// static
+syncer::ModelTypeSyncBridge* AutofillWalletSyncBridge::FromWebDataService(
+ AutofillWebDataService* web_data_service) {
+ return static_cast<AutofillWalletSyncBridge*>(
+ web_data_service->GetDBUserData()->GetUserData(
+ &kAutofillWalletSyncBridgeUserDataKey));
+}
+
+AutofillWalletSyncBridge::AutofillWalletSyncBridge(
+ std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
+ bool has_persistent_storage,
+ AutofillWebDataBackend* web_data_backend)
+ : ModelTypeSyncBridge(std::move(change_processor)),
+ has_persistent_storage_(has_persistent_storage),
+ initial_sync_done_(false),
+ web_data_backend_(web_data_backend) {
+ DCHECK(web_data_backend_);
+
+ LoadMetadata();
+}
+
+AutofillWalletSyncBridge::~AutofillWalletSyncBridge() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+std::unique_ptr<syncer::MetadataChangeList>
+AutofillWalletSyncBridge::CreateMetadataChangeList() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return std::make_unique<syncer::SyncMetadataStoreChangeList>(
+ GetAutofillTable(), syncer::AUTOFILL_WALLET_DATA);
+}
+
+base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) {
+ SetSyncData(entity_data);
+
+ // After the first sync, we are sure that initial sync is done.
+ initial_sync_done_ = true;
+ return base::nullopt;
+}
+
+base::Optional<syncer::ModelError> AutofillWalletSyncBridge::ApplySyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) {
+ // This bridge does not support incremental updates, so whenever this is
+ // called, the change list should be empty.
+ DCHECK(entity_data.empty()) << "Received an unsupported incremental update.";
+ return base::nullopt;
+}
+
+void AutofillWalletSyncBridge::GetData(StorageKeyList storage_keys,
+ DataCallback callback) {
+ // This data type is never synced "up" so we don't need to implement this.
+ NOTIMPLEMENTED();
+}
+
+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));
+}
+
+std::string AutofillWalletSyncBridge::GetClientTag(
+ const syncer::EntityData& entity_data) {
+ DCHECK(entity_data.specifics.has_autofill_wallet());
+
+ return GetClientTagForWalletDataSpecificsId(
+ GetSpecificsIdFromAutofillWalletSpecifics(
+ entity_data.specifics.autofill_wallet()));
+}
+
+std::string AutofillWalletSyncBridge::GetStorageKey(
+ const syncer::EntityData& entity_data) {
+ DCHECK(entity_data.specifics.has_autofill_wallet());
+ return GetStorageKeyForSpecificsId(GetSpecificsIdFromAutofillWalletSpecifics(
+ entity_data.specifics.autofill_wallet()));
+}
+
+bool AutofillWalletSyncBridge::SupportsIncrementalUpdates() const {
+ // The payments server always returns the full dataset whenever there's any
+ // change to the user's payments data. Therefore, we don't implement full
+ // incremental-update support in this bridge, and clear all data
+ // before inserting new instead.
+ return false;
+}
+
+AutofillWalletSyncBridge::StopSyncResponse
+AutofillWalletSyncBridge::ApplyStopSyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) {
+ // If a metadata change list gets passed in, that means sync is actually
+ // disabled, so we want to delete the payments data.
+ if (delete_metadata_change_list) {
+ SetSyncData(syncer::EntityChangeList());
+ }
+ return StopSyncResponse::kModelStillReadyToSync;
+}
+
+void AutofillWalletSyncBridge::GetAllDataForTesting(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;
+ }
+
+ auto batch = std::make_unique<syncer::MutableDataBatch>();
+ for (const std::unique_ptr<AutofillProfile>& entry : profiles) {
+ batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
+ CreateEntityDataFromAutofillServerProfile(*entry));
+ }
+ for (const std::unique_ptr<CreditCard>& entry : cards) {
+ batch->Put(GetStorageKeyForEntryServerId(entry->server_id()),
+ CreateEntityDataFromCard(*entry));
+ }
+
+ if (customer_data) {
+ batch->Put(GetStorageKeyForEntryServerId(customer_data->customer_id),
+ CreateEntityDataFromPaymentsCustomerData(*customer_data));
+ }
+ std::move(callback).Run(std::move(batch));
+}
+
+void AutofillWalletSyncBridge::SetSyncData(
+ const syncer::EntityChangeList& entity_data) {
+ bool wallet_data_changed = false;
+
+ // Extract the Autofill types from the sync |entity_data|.
+ std::vector<CreditCard> wallet_cards;
+ std::vector<PaymentsCustomerData> customer_data;
+ if (has_persistent_storage_) {
+ // When in persistent storage mode, we update wallet addresses.
+ std::vector<AutofillProfile> wallet_addresses;
+ PopulateWalletTypesFromSyncData(entity_data, &wallet_cards,
+ &wallet_addresses, &customer_data);
+ wallet_data_changed |= SetWalletAddresses(std::move(wallet_addresses));
+ } else {
+ // When in ephemeral storage mode, we ignore wallet addresses.
+ PopulateWalletTypesFromSyncData(entity_data, &wallet_cards, nullptr,
+ &customer_data);
+ }
+
+ // In both cases, we need to update wallet cards and payments customer data.
+ wallet_data_changed |= SetWalletCards(std::move(wallet_cards));
+ wallet_data_changed |= SetPaymentsCustormerData(std::move(customer_data));
+
+ if (web_data_backend_ && wallet_data_changed)
+ web_data_backend_->NotifyOfMultipleAutofillChanges();
+}
+
+bool AutofillWalletSyncBridge::SetWalletCards(
+ std::vector<CreditCard> wallet_cards) {
+ // Users can set billing address of the server credit card locally, but that
+ // information does not propagate to either Chrome Sync or Google Payments
+ // server. To preserve user's preferred billing address and most recent use
+ // stats, copy them from disk into |wallet_cards|.
+ AutofillTable* table = GetAutofillTable();
+ CopyRelevantWalletMetadataFromDisk(*table, &wallet_cards);
+
+ // In the common case, the database won't have changed. Committing an update
+ // to the database will require at least one DB page write and will schedule
+ // a fsync. To avoid this I/O, it should be more efficient to do a read and
+ // only do the writes if something changed.
+ std::vector<std::unique_ptr<CreditCard>> existing_cards;
+ table->GetServerCreditCards(&existing_cards);
+ AutofillWalletDiff diff =
+ ComputeAutofillWalletDiff(existing_cards, wallet_cards);
+
+ // Record only local changes that correspond to changes in the payments
+ // backend and not local changes due to initial sync.
+ if (initial_sync_done_) {
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAdded", diff.items_added);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsRemoved", diff.items_removed);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAddedOrRemoved",
+ diff.items_added + diff.items_removed);
+ }
+
+ if (!diff.IsEmpty()) {
+ table->SetServerCreditCards(wallet_cards);
+ return true;
+ }
+ return false;
+}
+
+bool AutofillWalletSyncBridge::SetWalletAddresses(
+ std::vector<AutofillProfile> wallet_addresses) {
+ // In the common case, the database won't have changed. Committing an update
+ // to the database will require at least one DB page write and will schedule
+ // a fsync. To avoid this I/O, it should be more efficient to do a read and
+ // only do the writes if something changed.
+ AutofillTable* table = GetAutofillTable();
+ std::vector<std::unique_ptr<AutofillProfile>> existing_addresses;
+ table->GetServerProfiles(&existing_addresses);
+ AutofillWalletDiff diff =
+ ComputeAutofillWalletDiff(existing_addresses, wallet_addresses);
+
+ // Record only local changes that correspond to changes in the payments
+ // backend and not local changes due to initial sync.
+ if (initial_sync_done_) {
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesAdded", diff.items_added);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesRemoved",
+ diff.items_removed);
+ UMA_HISTOGRAM_COUNTS_100("Autofill.WalletAddressesAddedOrRemoved",
+ diff.items_added + diff.items_removed);
+ }
+
+ if (!diff.IsEmpty()) {
+ table->SetServerProfiles(wallet_addresses);
+ return true;
+ }
+ return false;
+}
+
+bool AutofillWalletSyncBridge::SetPaymentsCustormerData(
+ std::vector<PaymentsCustomerData> customer_data) {
+ // In the common case, the database won't have changed. Committing an update
+ // to the database will require at least one DB page write and will schedule
+ // a fsync. To avoid this I/O, it should be more efficient to do a read and
+ // only do the writes if something changed.
+ AutofillTable* table = GetAutofillTable();
+ std::unique_ptr<PaymentsCustomerData> existing_entry;
+ table->GetPaymentsCustomerData(&existing_entry);
+
+ // In case there were multiple entries (and there shouldn't!), we take the
+ // pointer to the first entry in the vector.
+ PaymentsCustomerData* new_entry =
+ customer_data.empty() ? nullptr : customer_data.data();
+
+#if DCHECK_IS_ON()
+ if (customer_data.size() > 1) {
+ DLOG(WARNING) << "Sync wallet_data update has " << customer_data.size()
+ << " payments-customer-data entries; expected 0 or 1.";
+ }
+#endif // DCHECK_IS_ON()
+
+ if (!new_entry && existing_entry) {
+ // Clear the existing entry in the DB.
+ GetAutofillTable()->SetPaymentsCustomerData(nullptr);
+ return true;
+ } else if (new_entry && (!existing_entry || *new_entry != *existing_entry)) {
+ // Write the new entry in the DB as it differs from the existing one.
+ GetAutofillTable()->SetPaymentsCustomerData(new_entry);
+ return true;
+ }
+ return false;
+}
+
+// static
+template <class Item>
+AutofillWalletSyncBridge::AutofillWalletDiff
+AutofillWalletSyncBridge::ComputeAutofillWalletDiff(
+ const std::vector<std::unique_ptr<Item>>& old_data,
+ const std::vector<Item>& new_data) {
+ // Build vectors of pointers, so that we can mutate (sort) them.
+ std::vector<const Item*> old_ptrs;
+ old_ptrs.reserve(old_data.size());
+ for (const std::unique_ptr<Item>& old_item : old_data)
+ old_ptrs.push_back(old_item.get());
+ std::vector<const Item*> new_ptrs;
+ new_ptrs.reserve(new_data.size());
+ for (const Item& new_item : new_data)
+ new_ptrs.push_back(&new_item);
+
+ // Sort our vectors.
+ auto compare = [](const Item* lhs, const Item* rhs) {
+ return lhs->Compare(*rhs) < 0;
+ };
+ std::sort(old_ptrs.begin(), old_ptrs.end(), compare);
+ std::sort(new_ptrs.begin(), new_ptrs.end(), compare);
+
+ // Walk over both of them and count added/removed elements.
+ AutofillWalletDiff result;
+ auto old_it = old_ptrs.begin();
+ auto new_it = new_ptrs.begin();
+ while (old_it != old_ptrs.end()) {
+ if (new_it == new_ptrs.end()) {
+ result.items_removed += std::distance(old_it, old_ptrs.end());
+ break;
+ }
+ int cmp = (*old_it)->Compare(**new_it);
+ if (cmp < 0) {
+ ++result.items_removed;
+ ++old_it;
+ } else if (cmp == 0) {
+ ++old_it;
+ ++new_it;
+ } else {
+ ++result.items_added;
+ ++new_it;
+ }
+ }
+ result.items_added += std::distance(new_it, new_ptrs.end());
+
+ DCHECK_EQ(old_data.size() + result.items_added - result.items_removed,
+ new_data.size());
+
+ return result;
+}
+
+AutofillTable* AutofillWalletSyncBridge::GetAutofillTable() {
+ return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase());
+}
+
+void AutofillWalletSyncBridge::LoadMetadata() {
+ if (!web_data_backend_ || !web_data_backend_->GetDatabase() ||
+ !GetAutofillTable()) {
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed to load AutofillWebDatabase."});
+ return;
+ }
+
+ auto batch = std::make_unique<syncer::MetadataBatch>();
+ if (!GetAutofillTable()->GetAllSyncMetadata(syncer::AUTOFILL_WALLET_DATA,
+ batch.get())) {
+ change_processor()->ReportError(
+ {FROM_HERE, "Failed reading autofill metadata from WebDatabase."});
+ return;
+ }
+ initial_sync_done_ = batch->GetModelTypeState().initial_sync_done();
+
+ change_processor()->ModelReadyToSync(std::move(batch));
+}
+
+} // namespace autofill
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
new file mode 100644
index 00000000000..b7a483742b3
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h
@@ -0,0 +1,140 @@
+// 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_WEBDATA_AUTOFILL_WALLET_SYNC_BRIDGE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNC_BRIDGE_H_
+
+#include <memory>
+#include <string>
+#include <unordered_set>
+
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "base/supports_user_data.h"
+#include "components/sync/model/metadata_change_list.h"
+#include "components/sync/model/model_error.h"
+#include "components/sync/model/model_type_change_processor.h"
+#include "components/sync/model/model_type_sync_bridge.h"
+
+namespace autofill {
+
+class AutofillProfile;
+class AutofillTable;
+class AutofillWebDataBackend;
+class AutofillWebDataService;
+class CreditCard;
+struct PaymentsCustomerData;
+
+// Sync bridge responsible for propagating local changes to the processor and
+// applying remote changes to the local database.
+class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
+ public syncer::ModelTypeSyncBridge {
+ public:
+ // Factory method that hides dealing with change_processor and also stores the
+ // created bridge within |web_data_service|. This method should only be
+ // called on |web_data_service|'s DB thread.
+ static void CreateForWebDataServiceAndBackend(
+ const std::string& app_locale,
+ bool has_persistent_storage_,
+ AutofillWebDataBackend* webdata_backend,
+ AutofillWebDataService* web_data_service);
+
+ static syncer::ModelTypeSyncBridge* FromWebDataService(
+ AutofillWebDataService* web_data_service);
+
+ explicit AutofillWalletSyncBridge(
+ std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
+ bool has_persistent_storage_,
+ AutofillWebDataBackend* web_data_backend);
+ ~AutofillWalletSyncBridge() override;
+
+ // ModelTypeSyncBridge implementation.
+ std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+ override;
+ base::Optional<syncer::ModelError> MergeSyncData(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_data) override;
+ base::Optional<syncer::ModelError> ApplySyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+ syncer::EntityChangeList entity_changes) override;
+ void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+ void GetAllDataForDebugging(DataCallback callback) override;
+ std::string GetClientTag(const syncer::EntityData& entity_data) override;
+ std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+ bool SupportsIncrementalUpdates() const override;
+ StopSyncResponse ApplyStopSyncChanges(
+ std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list)
+ override;
+
+ // Sends all Wallet Data to the |callback| and keeps all the strings in their
+ // original format.
+ void GetAllDataForTesting(DataCallback callback);
+
+ private:
+ struct AutofillWalletDiff {
+ int items_added = 0;
+ int items_removed = 0;
+
+ bool IsEmpty() const { return items_added == 0 && items_removed == 0; }
+ };
+
+ // Sets the wallet data from |entity_data| to this client and records metrics
+ // about added/deleted data.
+ void SetSyncData(const syncer::EntityChangeList& entity_data);
+
+ // Sets |wallet_cards| to this client, records metrics about added/deleted
+ // data and returns whether any change has been applied (i.e., whether
+ // |wallet_cards| was different from local data).
+ bool SetWalletCards(std::vector<CreditCard> wallet_cards);
+
+ // Sets |wallet_addresses| to this client, records metrics about added/deleted
+ // data and returns whether any change has been applied (i.e., whether
+ // |wallet_addresses| was different from local data).
+ bool SetWalletAddresses(std::vector<AutofillProfile> wallet_addresses);
+
+ // Sets |customer_data| to this client and returns whether any change has been
+ // applied (i.e., whether |customer_data| was different from local data).
+ bool SetPaymentsCustormerData(
+ std::vector<PaymentsCustomerData> customer_data);
+
+ // Computes a "diff" (items added, items removed) of two vectors of items,
+ // which should be either CreditCard or AutofillProfile. This is used for two
+ // purposes:
+ // 1) Detecting if anything has changed, so that we don't write to disk in the
+ // common case where nothing has changed.
+ // 2) Recording metrics on the number of added/removed items.
+ // This is exposed as a static method so that it can be tested.
+ template <class Item>
+ static AutofillWalletDiff ComputeAutofillWalletDiff(
+ const std::vector<std::unique_ptr<Item>>& old_data,
+ const std::vector<Item>& new_data);
+
+ // Returns the table associated with the |web_data_backend_|.
+ AutofillTable* GetAutofillTable();
+
+ // Synchronously load sync metadata from the autofill table and pass it to the
+ // processor so that it can start tracking changes.
+ void LoadMetadata();
+
+ // Stores whether this bridge is connected to the persistent storage (as part
+ // of the complete sync feature) or to an ephemeral storage (as part of the
+ // content-area-account-based lightweight sync).
+ const bool has_persistent_storage_;
+
+ // Stores whether initial sync has been done.
+ bool initial_sync_done_;
+
+ // AutofillProfileSyncBridge is owned by |web_data_backend_| through
+ // SupportsUserData, so it's guaranteed to outlive |this|.
+ AutofillWebDataBackend* const web_data_backend_;
+
+ // The bridge should be used on the same sequence where it is constructed.
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillWalletSyncBridge);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_WALLET_SYNC_BRIDGE_H_
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
new file mode 100644
index 00000000000..3ff812dedb1
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc
@@ -0,0 +1,738 @@
+// 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/webdata/autofill_wallet_sync_bridge.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <utility>
+
+#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/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/time/time.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"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.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/autofill_webdata_backend.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/sync/base/hash_util.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"
+#include "components/sync/model_impl/client_tag_based_model_type_processor.h"
+#include "components/sync/model_impl/in_memory_metadata_change_list.h"
+#include "components/sync/protocol/autofill_specifics.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/sync/test/test_matchers.h"
+#include "components/webdata/common/web_database.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace {
+
+using base::ScopedTempDir;
+using sync_pb::AutofillWalletSpecifics;
+using sync_pb::EntityMetadata;
+using sync_pb::ModelTypeState;
+using syncer::DataBatch;
+using syncer::EntityChange;
+using syncer::EntityData;
+using syncer::EntityDataPtr;
+using syncer::HasInitialSyncDone;
+using syncer::KeyAndData;
+using syncer::MockModelTypeChangeProcessor;
+using syncer::ModelType;
+using testing::NiceMock;
+using testing::SizeIs;
+using testing::Return;
+using testing::UnorderedElementsAre;
+
+// Base64 encodings of the server IDs, used as ids in WalletMetadataSpecifics
+// (these are suitable for syncing, because they are valid UTF-8).
+const char kAddr1SpecificsId[] = "YWRkcjHvv74=";
+const char kCard1SpecificsId[] = "Y2FyZDHvv74=";
+
+// Represents a Payments customer id.
+const char kCustomerDataId[] = "deadbeef";
+const char kCustomerDataId2[] = "deadcafe";
+
+// Unique sync tags for the server IDs.
+const char kAddr1SyncTag[] = "YWRkcjHvv74=";
+const char kCard1SyncTag[] = "Y2FyZDHvv74=";
+const char kCustomerDataSyncTag[] = "deadbeef";
+
+const char kLocaleString[] = "en-US";
+const base::Time kJune2017 = base::Time::FromDoubleT(1497552271);
+
+// TODO(jkrcal): Extract this class out and reuse it for all autofill bridges.
+class MockAutofillBackend : public AutofillWebDataBackend {
+ public:
+ MockAutofillBackend() {}
+ ~MockAutofillBackend() override {}
+
+ MOCK_METHOD0(GetDatabase, WebDatabase*());
+ MOCK_METHOD1(
+ AddObserver,
+ void(autofill::AutofillWebDataServiceObserverOnDBSequence* observer));
+ MOCK_METHOD1(
+ RemoveObserver,
+ void(autofill::AutofillWebDataServiceObserverOnDBSequence* observer));
+ MOCK_METHOD0(RemoveExpiredFormElements, void());
+ MOCK_METHOD0(NotifyOfMultipleAutofillChanges, void());
+ MOCK_METHOD1(NotifyThatSyncHasStarted, void(ModelType model_type));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockAutofillBackend);
+};
+
+void ExtractAutofillWalletSpecificsFromDataBatch(
+ std::unique_ptr<DataBatch> batch,
+ std::vector<AutofillWalletSpecifics>* output) {
+ while (batch->HasNext()) {
+ const KeyAndData& data_pair = batch->Next();
+ output->push_back(data_pair.second->specifics.autofill_wallet());
+ }
+}
+
+std::string WalletMaskedCreditCardSpecificsAsDebugString(
+ const AutofillWalletSpecifics& specifics) {
+ std::ostringstream output;
+ output << "[id: " << specifics.masked_card().id()
+ << ", type: " << static_cast<int>(specifics.type())
+ << ", name_on_card: " << specifics.masked_card().name_on_card()
+ << ", type: " << specifics.masked_card().type()
+ << ", last_four: " << specifics.masked_card().last_four()
+ << ", exp_month: " << specifics.masked_card().exp_month()
+ << ", exp_year: " << specifics.masked_card().exp_year()
+ << ", billing_address_id: "
+ << specifics.masked_card().billing_address_id()
+ << ", card_class: " << specifics.masked_card().card_class()
+ << ", bank_name: " << specifics.masked_card().bank_name() << "]";
+ return output.str();
+}
+
+std::string WalletPostalAddressSpecificsAsDebugString(
+ const AutofillWalletSpecifics& specifics) {
+ std::ostringstream output;
+ output << "[id: " << specifics.address().id()
+ << ", type: " << static_cast<int>(specifics.type())
+ << ", recipient_name: " << specifics.address().recipient_name()
+ << ", company_name: " << specifics.address().company_name()
+ << ", street_address: "
+ << (specifics.address().street_address_size()
+ ? specifics.address().street_address(0)
+ : "")
+ << ", address_1: " << specifics.address().address_1()
+ << ", address_2: " << specifics.address().address_2()
+ << ", address_3: " << specifics.address().address_3()
+ << ", postal_code: " << specifics.address().postal_code()
+ << ", country_code: " << specifics.address().country_code()
+ << ", phone_number: " << specifics.address().phone_number()
+ << ", sorting_code: " << specifics.address().sorting_code() << "]";
+ return output.str();
+}
+
+std::string AutofillWalletSpecificsAsDebugString(
+ const AutofillWalletSpecifics& specifics) {
+ switch (specifics.type()) {
+ case sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_MASKED_CREDIT_CARD:
+ return WalletMaskedCreditCardSpecificsAsDebugString(specifics);
+ case sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_POSTAL_ADDRESS:
+ return WalletPostalAddressSpecificsAsDebugString(specifics);
+ case sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_CUSTOMER_DATA:
+ return "CustomerData";
+ case sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_UNKNOWN:
+ return "Unknown";
+ }
+}
+
+MATCHER_P(EqualsSpecifics, expected, "") {
+ if (arg.SerializeAsString() != expected.SerializeAsString()) {
+ *result_listener << "entry\n"
+ << AutofillWalletSpecificsAsDebugString(arg) << "\n"
+ << "did not match expected\n"
+ << AutofillWalletSpecificsAsDebugString(expected);
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+class AutofillWalletSyncBridgeTest : public testing::Test {
+ public:
+ AutofillWalletSyncBridgeTest() {}
+ ~AutofillWalletSyncBridgeTest() override {}
+
+ void SetUp() override {
+ // Fix a time for implicitly constructed use_dates in AutofillProfile.
+ test_clock_.SetNow(kJune2017);
+ CountryNames::SetLocaleString(kLocaleString);
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ db_.AddTable(&table_);
+ db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase"));
+ ON_CALL(*backend(), GetDatabase()).WillByDefault(Return(&db_));
+ ResetProcessor();
+ ResetBridge();
+ }
+
+ void ResetProcessor() {
+ real_processor_ =
+ std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+ syncer::AUTOFILL_WALLET_DATA, /*dump_stack=*/base::DoNothing(),
+ /*commit_only=*/false);
+ mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
+ }
+
+ void ResetBridge() {
+ bridge_.reset(new AutofillWalletSyncBridge(
+ mock_processor_.CreateForwardingProcessor(), UseFullSync(), &backend_));
+ }
+
+ void StartSyncing(
+ const std::vector<AutofillWalletSpecifics>& remote_data = {}) {
+ base::RunLoop loop;
+ syncer::DataTypeActivationRequest request;
+ request.error_handler = base::DoNothing();
+ real_processor_->OnSyncStarting(
+ request,
+ base::BindLambdaForTesting(
+ [&loop](std::unique_ptr<syncer::DataTypeActivationResponse>) {
+ loop.Quit();
+ }));
+ loop.Run();
+
+ // Initialize the processor with initial_sync_done.
+ sync_pb::ModelTypeState state;
+ state.set_initial_sync_done(true);
+ state.mutable_progress_marker()
+ ->mutable_gc_directive()
+ ->set_version_watermark(1);
+ syncer::UpdateResponseDataList initial_updates;
+ for (const AutofillWalletSpecifics& specifics : remote_data) {
+ initial_updates.push_back(SpecificsToUpdateResponse(specifics));
+ }
+ real_processor_->OnUpdateReceived(state, initial_updates);
+ }
+
+ EntityData SpecificsToEntity(const AutofillWalletSpecifics& specifics) {
+ EntityData data;
+ *data.specifics.mutable_autofill_wallet() = specifics;
+ data.client_tag_hash = syncer::GenerateSyncableHash(
+ syncer::AUTOFILL_WALLET_DATA, bridge()->GetClientTag(data));
+ return data;
+ }
+
+ std::vector<AutofillWalletSpecifics> GetAllLocalData() {
+ std::vector<AutofillWalletSpecifics> data;
+ // Perform an async call synchronously for testing.
+ base::RunLoop loop;
+ bridge()->GetAllDataForTesting(base::BindLambdaForTesting(
+ [&loop, &data](std::unique_ptr<DataBatch> batch) {
+ ExtractAutofillWalletSpecificsFromDataBatch(std::move(batch), &data);
+ loop.Quit();
+ }));
+ loop.Run();
+ return data;
+ }
+
+ syncer::UpdateResponseData SpecificsToUpdateResponse(
+ const AutofillWalletSpecifics& specifics) {
+ syncer::UpdateResponseData data;
+ data.entity = SpecificsToEntity(specifics).PassToPtr();
+ return data;
+ }
+
+ AutofillWalletSyncBridge* bridge() { return bridge_.get(); }
+
+ syncer::MockModelTypeChangeProcessor& mock_processor() {
+ return mock_processor_;
+ }
+
+ AutofillTable* table() { return &table_; }
+
+ MockAutofillBackend* backend() { return &backend_; }
+
+ virtual bool UseFullSync() { return true; }
+
+ private:
+ autofill::TestAutofillClock test_clock_;
+ ScopedTempDir temp_dir_;
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ NiceMock<MockAutofillBackend> backend_;
+ AutofillTable table_;
+ WebDatabase db_;
+ testing::NiceMock<MockModelTypeChangeProcessor> mock_processor_;
+ std::unique_ptr<syncer::ClientTagBasedModelTypeProcessor> real_processor_;
+ std::unique_ptr<AutofillWalletSyncBridge> bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillWalletSyncBridgeTest);
+};
+
+// The following 3 tests make sure client tags stay stable.
+TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForAddress) {
+ AutofillWalletSpecifics specifics =
+ CreateAutofillWalletSpecificsForAddress(kAddr1SpecificsId);
+ EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
+ kAddr1SyncTag);
+}
+
+TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCard) {
+ AutofillWalletSpecifics specifics =
+ CreateAutofillWalletSpecificsForCard(kCard1SpecificsId);
+ EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
+ kCard1SyncTag);
+}
+
+TEST_F(AutofillWalletSyncBridgeTest, GetClientTagForCustomerData) {
+ AutofillWalletSpecifics specifics =
+ CreateAutofillWalletSpecificsForPaymentsCustomerData(
+ kCustomerDataSyncTag);
+ EXPECT_EQ(bridge()->GetClientTag(SpecificsToEntity(specifics)),
+ kCustomerDataSyncTag);
+}
+
+// The following 3 tests make sure storage keys stay stable.
+TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForAddress) {
+ AutofillWalletSpecifics specifics1 =
+ CreateAutofillWalletSpecificsForAddress(kAddr1SpecificsId);
+ EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics1)),
+ kAddr1SpecificsId);
+}
+
+TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForCard) {
+ AutofillWalletSpecifics specifics2 =
+ CreateAutofillWalletSpecificsForCard(kCard1SpecificsId);
+ EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics2)),
+ kCard1SpecificsId);
+}
+
+TEST_F(AutofillWalletSyncBridgeTest, GetStorageKeyForCustomerData) {
+ AutofillWalletSpecifics specifics3 =
+ CreateAutofillWalletSpecificsForPaymentsCustomerData(kCustomerDataId);
+ EXPECT_EQ(bridge()->GetStorageKey(SpecificsToEntity(specifics3)),
+ kCustomerDataId);
+}
+
+TEST_F(AutofillWalletSyncBridgeTest,
+ GetAllDataForDebugging_ShouldReturnAllData) {
+ AutofillProfile address1 = test::GetServerProfile();
+ AutofillProfile address2 = test::GetServerProfile2();
+ table()->SetServerProfiles({address1, address2});
+ CreditCard card1 = test::GetMaskedServerCard();
+ CreditCard card2 = test::GetMaskedServerCardAmex();
+ table()->SetServerCreditCards({card1, card2});
+ PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
+ table()->SetPaymentsCustomerData(&customer_data);
+
+ AutofillWalletSpecifics profile_specifics1;
+ SetAutofillWalletSpecificsFromServerProfile(address1, &profile_specifics1);
+ AutofillWalletSpecifics profile_specifics2;
+ SetAutofillWalletSpecificsFromServerProfile(address2, &profile_specifics2);
+ AutofillWalletSpecifics card_specifics1;
+ SetAutofillWalletSpecificsFromServerCard(card1, &card_specifics1);
+ AutofillWalletSpecifics card_specifics2;
+ SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2);
+ AutofillWalletSpecifics customer_data_specifics;
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
+ &customer_data_specifics);
+
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics1),
+ EqualsSpecifics(profile_specifics2),
+ EqualsSpecifics(card_specifics1),
+ EqualsSpecifics(card_specifics2),
+ EqualsSpecifics(customer_data_specifics)));
+}
+
+// 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) {
+ // Create one profile and one card on the client.
+ AutofillProfile address1 = test::GetServerProfile();
+ table()->SetServerProfiles({address1});
+ CreditCard card1 = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card1});
+ PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
+ table()->SetPaymentsCustomerData(&customer_data);
+
+ // Create a different profile and a different card on the server.
+ AutofillProfile address2 = test::GetServerProfile2();
+ AutofillWalletSpecifics profile_specifics2;
+ SetAutofillWalletSpecificsFromServerProfile(address2, &profile_specifics2);
+ CreditCard card2 = test::GetMaskedServerCardAmex();
+ AutofillWalletSpecifics card_specifics2;
+ SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2);
+ AutofillWalletSpecifics customer_data_specifics;
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
+ &customer_data_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({profile_specifics2, card_specifics2, customer_data_specifics});
+
+ // Only the server card should be present on the client.
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics2),
+ EqualsSpecifics(card_specifics2),
+ EqualsSpecifics(customer_data_specifics)));
+}
+
+// Test that all field values for a card sent form the server are copied on the
+// card on the client.
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) {
+ // Create one profile, one card and one customer data entry on the client.
+ AutofillProfile address = test::GetServerProfile();
+ table()->SetServerProfiles({address});
+ CreditCard card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card});
+ PaymentsCustomerData customer_data1{/*customer_id=*/kCustomerDataId};
+ table()->SetPaymentsCustomerData(&customer_data1);
+
+ // Create a different customer data entry on the server.
+ AutofillWalletSpecifics profile_specifics;
+ SetAutofillWalletSpecificsFromServerProfile(address, &profile_specifics);
+ AutofillWalletSpecifics card_specifics;
+ SetAutofillWalletSpecificsFromServerCard(card, &card_specifics);
+ PaymentsCustomerData customer_data2{/*customer_id=*/kCustomerDataId2};
+ AutofillWalletSpecifics customer_data_specifics2;
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data2,
+ &customer_data_specifics2);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({profile_specifics, card_specifics, customer_data_specifics2});
+
+ // Only the server card should be present on the client.
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics),
+ EqualsSpecifics(card_specifics),
+ EqualsSpecifics(customer_data_specifics2)));
+}
+
+// Tests that when the server sends no cards or address, the client should
+// delete all it's existing data.
+TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) {
+ // Create one profile and one card on the client.
+ AutofillProfile local_profile = test::GetServerProfile();
+ table()->SetServerProfiles({local_profile});
+ CreditCard local_card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({local_card});
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({});
+
+ EXPECT_TRUE(GetAllLocalData().empty());
+}
+
+// Test that when the server sends the same address and card as the client has,
+// nothing changes on the client.
+TEST_F(AutofillWalletSyncBridgeTest,
+ MergeSyncData_SameWalletAddressAndCardAndCustomerData) {
+ // Create one profile and one card on the client.
+ AutofillProfile profile = test::GetServerProfile();
+ table()->SetServerProfiles({profile});
+ CreditCard card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card});
+ PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
+ table()->SetPaymentsCustomerData(&customer_data);
+
+ // Create the same profile and card on the server.
+ AutofillWalletSpecifics profile_specifics;
+ SetAutofillWalletSpecificsFromServerProfile(profile, &profile_specifics);
+ AutofillWalletSpecifics card_specifics;
+ SetAutofillWalletSpecificsFromServerCard(card, &card_specifics);
+ AutofillWalletSpecifics customer_data_specifics;
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
+ &customer_data_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
+ StartSyncing({profile_specifics, card_specifics, customer_data_specifics});
+
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics),
+ EqualsSpecifics(card_specifics),
+ EqualsSpecifics(customer_data_specifics)));
+}
+
+// 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,
+ MergeSyncData_AddRemoveAndPreserveWalletAddressAndCard) {
+ // Create two profile and one card on the client.
+ AutofillProfile profile = test::GetServerProfile();
+ AutofillProfile profile2 = test::GetServerProfile2();
+ table()->SetServerProfiles({profile, profile2});
+ CreditCard card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card});
+
+ // Create one of the same profiles and a different card on the server.
+ AutofillWalletSpecifics profile_specifics;
+ SetAutofillWalletSpecificsFromServerProfile(profile, &profile_specifics);
+ // The Amex card has different values for the relevant fields.
+ CreditCard card2 = test::GetMaskedServerCardAmex();
+ AutofillWalletSpecifics card_specifics;
+ SetAutofillWalletSpecificsFromServerCard(card, &card_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({profile_specifics, card_specifics});
+
+ // Make sure that the client only has the data from the server.
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics),
+ EqualsSpecifics(card_specifics)));
+}
+
+// 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) {
+ // Create a profile to be synced from the server.
+ AutofillProfile profile = test::GetServerProfile();
+ AutofillWalletSpecifics profile_specifics;
+ SetAutofillWalletSpecificsFromServerProfile(profile, &profile_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({profile_specifics});
+
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(profile_specifics)));
+
+ std::vector<std::unique_ptr<AutofillProfile>> profiles;
+ table()->GetServerProfiles(&profiles);
+ ASSERT_EQ(1U, profiles.size());
+
+ // Make sure that all the data was set properly.
+ EXPECT_EQ(profile.GetRawInfo(NAME_FULL), profiles[0]->GetRawInfo(NAME_FULL));
+ EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME),
+ profiles[0]->GetRawInfo(COMPANY_NAME));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_STATE),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_STATE));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_CITY),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_CITY));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_ZIP),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_ZIP));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_COUNTRY),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER),
+ profiles[0]->GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
+ EXPECT_EQ(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE),
+ profiles[0]->GetRawInfo(ADDRESS_HOME_SORTING_CODE));
+ EXPECT_EQ(profile.language_code(), profiles[0]->language_code());
+
+ // Also make sure that those types are not empty, to exercice all the code
+ // paths.
+ EXPECT_FALSE(profile.GetRawInfo(NAME_FULL).empty());
+ EXPECT_FALSE(profile.GetRawInfo(COMPANY_NAME).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_STATE).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_CITY).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_ZIP).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_COUNTRY).empty());
+ EXPECT_FALSE(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER).empty());
+ EXPECT_FALSE(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE).empty());
+ EXPECT_FALSE(profile.language_code().empty());
+}
+
+// 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) {
+ // 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.
+ card.set_bank_name("The Bank");
+ AutofillWalletSpecifics card_specifics;
+ SetAutofillWalletSpecificsFromServerCard(card, &card_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({card_specifics});
+
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(card_specifics)));
+
+ std::vector<std::unique_ptr<CreditCard>> cards;
+ table()->GetServerCreditCards(&cards);
+ ASSERT_EQ(1U, cards.size());
+
+ // Make sure that all the data was set properly.
+ EXPECT_EQ(card.network(), cards[0]->network());
+ EXPECT_EQ(card.LastFourDigits(), cards[0]->LastFourDigits());
+ EXPECT_EQ(card.expiration_month(), cards[0]->expiration_month());
+ EXPECT_EQ(card.expiration_year(), cards[0]->expiration_year());
+ EXPECT_EQ(card.billing_address_id(), cards[0]->billing_address_id());
+ EXPECT_EQ(card.card_type(), cards[0]->card_type());
+ EXPECT_EQ(card.bank_name(), cards[0]->bank_name());
+
+ // Also make sure that those types are not empty, to exercice all the code
+ // paths.
+ EXPECT_FALSE(card.network().empty());
+ EXPECT_FALSE(card.LastFourDigits().empty());
+ EXPECT_NE(0, card.expiration_month());
+ EXPECT_NE(0, card.expiration_year());
+ 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) {
+ ModelTypeState model_type_state;
+ model_type_state.set_initial_sync_done(true);
+ EXPECT_TRUE(table()->UpdateModelTypeState(syncer::AUTOFILL_WALLET_DATA,
+ model_type_state));
+ EXPECT_TRUE(table()->UpdateSyncMetadata(syncer::AUTOFILL_WALLET_DATA, "key",
+ EntityMetadata()));
+
+ ResetProcessor();
+ EXPECT_CALL(mock_processor(), ModelReadyToSync(MetadataBatchContains(
+ /*state=*/HasInitialSyncDone(),
+ /*entities=*/SizeIs(1))));
+ ResetBridge();
+}
+
+TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
+ // Create one profile and one card on the client.
+ AutofillProfile local_profile = test::GetServerProfile();
+ table()->SetServerProfiles({local_profile});
+ CreditCard local_card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({local_card});
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ // 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>());
+
+ EXPECT_TRUE(GetAllLocalData().empty());
+}
+
+TEST_F(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) {
+ // Create one profile and one card on the client.
+ AutofillProfile local_profile = test::GetServerProfile();
+ table()->SetServerProfiles({local_profile});
+ CreditCard local_card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({local_card});
+
+ // Passing in a non-null metadata change list indicates to the bridge that
+ // sync is stopping but the data type is not disabled.
+ bridge()->ApplyStopSyncChanges(/*delete_metadata_change_list=*/nullptr);
+
+ EXPECT_FALSE(GetAllLocalData().empty());
+}
+
+class AutofillWalletEphemeralSyncBridgeTest
+ : public AutofillWalletSyncBridgeTest {
+ public:
+ AutofillWalletEphemeralSyncBridgeTest() {}
+ ~AutofillWalletEphemeralSyncBridgeTest() override {}
+
+ bool UseFullSync() override { return false; }
+};
+
+// Tests that when the server sends no cards, the client should
+// delete all it's existing data.
+TEST_F(AutofillWalletEphemeralSyncBridgeTest,
+ MergeSyncData_NoWalletAddressOrCard) {
+ // Create one card on the client.
+ CreditCard local_card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({local_card});
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({});
+
+ EXPECT_TRUE(GetAllLocalData().empty());
+}
+
+// Test that when the server sends the same card as the client has, nothing
+// changes on the client.
+TEST_F(AutofillWalletEphemeralSyncBridgeTest, MergeSyncData_SameWalletCard) {
+ // Create one card on the client.
+ CreditCard card = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card});
+
+ // Create the same card on the server.
+ AutofillWalletSpecifics card_specifics;
+ SetAutofillWalletSpecificsFromServerCard(card, &card_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
+ StartSyncing({card_specifics});
+
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(card_specifics)));
+}
+
+// Tests that when a new wallet card is sent by the server, the client only
+// keeps the new data.
+TEST_F(AutofillWalletEphemeralSyncBridgeTest, MergeSyncData_NewWalletCard) {
+ // Create one card on the client.
+ CreditCard card1 = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card1});
+ PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
+ table()->SetPaymentsCustomerData(&customer_data);
+
+ // Create a different card on the server.
+ CreditCard card2 = test::GetMaskedServerCardAmex();
+ AutofillWalletSpecifics card_specifics2;
+ SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2);
+ AutofillWalletSpecifics customer_data_specifics;
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
+ &customer_data_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({card_specifics2, customer_data_specifics});
+
+ // Only the server card should be present on the client.
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(card_specifics2),
+ EqualsSpecifics(customer_data_specifics)));
+}
+
+// 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(AutofillWalletEphemeralSyncBridgeTest,
+ MergeSyncData_AddressesAreDropped) {
+ // Create one card on the client.
+ CreditCard card1 = test::GetMaskedServerCard();
+ table()->SetServerCreditCards({card1});
+ PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
+ table()->SetPaymentsCustomerData(&customer_data);
+
+ // Create a new profile and a different card on the server.
+ AutofillProfile address = test::GetServerProfile();
+ AutofillWalletSpecifics profile_specifics;
+ SetAutofillWalletSpecificsFromServerProfile(address, &profile_specifics);
+ CreditCard card2 = test::GetMaskedServerCardAmex();
+ AutofillWalletSpecifics card_specifics2;
+ SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2);
+ AutofillWalletSpecifics customer_data_specifics;
+ SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data,
+ &customer_data_specifics);
+
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
+ StartSyncing({profile_specifics, card_specifics2, customer_data_specifics});
+
+ // Only the server card should be present on the client; the server profile is
+ // ignored.
+ EXPECT_THAT(GetAllLocalData(),
+ UnorderedElementsAre(EqualsSpecifics(card_specifics2),
+ EqualsSpecifics(customer_data_specifics)));
+}
+
+} // 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 10f35b38615..f13179aaf79 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
@@ -18,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/sync_error_factory.h"
#include "components/sync/protocol/sync.pb.h"
@@ -25,18 +26,14 @@ namespace autofill {
namespace {
-// The length of the GUIDs used for local autofill data. It is different than
-// the length used for server autofill data.
-const int kLocalGuidSize = 36;
-
-void* UserDataKey() {
+void* AutofillWalletSyncableServiceUserDataKey() {
// Use the address of a static so that COMDAT folding won't ever fold
// with something else.
static int user_data_key = 0;
return reinterpret_cast<void*>(&user_data_key);
}
-const char* CardNetworkFromWalletCardType(
+const char* CardNetworkFromAutofillWalletCardType(
sync_pb::WalletMaskedCreditCard::WalletCardType type) {
switch (type) {
case sync_pb::WalletMaskedCreditCard::AMEX:
@@ -61,7 +58,7 @@ const char* CardNetworkFromWalletCardType(
}
}
-CreditCard::CardType CardTypeFromWalletCardClass(
+CreditCard::CardType CardTypeFromAutofillWalletCardClass(
sync_pb::WalletMaskedCreditCard::WalletCardClass card_class) {
switch (card_class) {
case sync_pb::WalletMaskedCreditCard::CREDIT:
@@ -75,7 +72,7 @@ CreditCard::CardType CardTypeFromWalletCardClass(
}
}
-CreditCard::ServerStatus ServerToLocalStatus(
+CreditCard::ServerStatus ServerToLocalWalletCardStatus(
sync_pb::WalletMaskedCreditCard::WalletCardStatus status) {
switch (status) {
case sync_pb::WalletMaskedCreditCard::VALID:
@@ -87,12 +84,14 @@ CreditCard::ServerStatus ServerToLocalStatus(
}
}
-CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
+CreditCard CardFromWalletCardSpecifics(
+ 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.SetServerStatus(ServerToLocalWalletCardStatus(card.status()));
+ result.SetNetworkForMaskedCard(
+ CardNetworkFromAutofillWalletCardType(card.type()));
+ result.set_card_type(CardTypeFromAutofillWalletCardClass(card.card_class()));
result.SetRawInfo(CREDIT_CARD_NAME_FULL,
base::UTF8ToUTF16(card.name_on_card()));
result.SetExpirationMonth(card.exp_month());
@@ -102,7 +101,7 @@ CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
return result;
}
-AutofillProfile ProfileFromSpecifics(
+AutofillProfile ProfileFromWalletCardSpecifics(
const sync_pb::WalletPostalAddress& address) {
AutofillProfile profile(AutofillProfile::SERVER_PROFILE, std::string());
@@ -140,6 +139,11 @@ AutofillProfile ProfileFromSpecifics(
return profile;
}
+PaymentsCustomerData CustomerDataFromSyncSpecifics(
+ const sync_pb::PaymentsCustomerData& customer_data) {
+ return PaymentsCustomerData{/*customer_id=*/customer_data.id()};
+}
+
} // namespace
// static
@@ -245,8 +249,9 @@ void AutofillWalletSyncableService::CreateForWebDataServiceAndBackend(
AutofillWebDataBackend* webdata_backend,
const std::string& app_locale) {
web_data_service->GetDBUserData()->SetUserData(
- UserDataKey(), base::WrapUnique(new AutofillWalletSyncableService(
- webdata_backend, app_locale)));
+ AutofillWalletSyncableServiceUserDataKey(),
+ base::WrapUnique(
+ new AutofillWalletSyncableService(webdata_backend, app_locale)));
}
// static
@@ -254,7 +259,8 @@ AutofillWalletSyncableService*
AutofillWalletSyncableService::FromWebDataService(
AutofillWebDataService* web_data_service) {
return static_cast<AutofillWalletSyncableService*>(
- web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+ web_data_service->GetDBUserData()->GetUserData(
+ AutofillWalletSyncableServiceUserDataKey()));
}
void AutofillWalletSyncableService::InjectStartSyncFlare(
@@ -263,10 +269,11 @@ void AutofillWalletSyncableService::InjectStartSyncFlare(
}
// static
-void AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
+void AutofillWalletSyncableService::PopulateWalletTypesFromSyncData(
const syncer::SyncDataList& data_list,
std::vector<CreditCard>* wallet_cards,
- std::vector<AutofillProfile>* wallet_addresses) {
+ std::vector<AutofillProfile>* wallet_addresses,
+ std::vector<PaymentsCustomerData>* customer_data) {
std::map<std::string, std::string> ids;
for (const syncer::SyncData& data : data_list) {
@@ -276,16 +283,20 @@ void AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
switch (autofill_specifics.type()) {
case sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD:
wallet_cards->push_back(
- CardFromSpecifics(autofill_specifics.masked_card()));
+ CardFromWalletCardSpecifics(autofill_specifics.masked_card()));
break;
case sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS:
wallet_addresses->push_back(
- ProfileFromSpecifics(autofill_specifics.address()));
+ ProfileFromWalletCardSpecifics(autofill_specifics.address()));
// Map the sync billing address id to the profile's id.
ids[autofill_specifics.address().id()] =
wallet_addresses->back().server_id();
break;
+ case sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA:
+ customer_data->push_back(
+ CustomerDataFromSyncSpecifics(autofill_specifics.customer_data()));
+ break;
case sync_pb::AutofillWalletSpecifics::UNKNOWN:
// Just ignore new entry types that the client doesn't know about.
break;
@@ -333,7 +344,9 @@ syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
bool is_initial_data) {
std::vector<CreditCard> wallet_cards;
std::vector<AutofillProfile> wallet_addresses;
- PopulateWalletCardsAndAddresses(data_list, &wallet_cards, &wallet_addresses);
+ std::vector<PaymentsCustomerData> customer_data;
+ PopulateWalletTypesFromSyncData(data_list, &wallet_cards, &wallet_addresses,
+ &customer_data);
// Users can set billing address of the server credit card locally, but that
// information does not propagate to either Chrome Sync or Google Payments
@@ -365,6 +378,16 @@ syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
merge_result.set_num_items_after_association(
static_cast<int>(wallet_cards.size() + wallet_addresses.size()));
+ if (customer_data.empty()) {
+ // Clears the data only.
+ table->SetPaymentsCustomerData(nullptr);
+ } else {
+ // In case there were multiple entries (and there shouldn't!), we take the
+ // first entry in the vector.
+ DCHECK_EQ(1u, customer_data.size());
+ table->SetPaymentsCustomerData(&customer_data.front());
+ }
+
if (!is_initial_data) {
UMA_HISTOGRAM_COUNTS_100("Autofill.WalletCardsAdded",
cards_diff.items_added);
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 c27626c36fd..bcaa296bdd2 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
@@ -14,6 +14,7 @@
#include "base/threading/thread_checker.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/sync/model/syncable_service.h"
namespace autofill {
@@ -72,11 +73,13 @@ class AutofillWalletSyncableService
CopyRelevantMetadataFromDisk_OverwriteOtherAddresses);
FRIEND_TEST_ALL_PREFIXES(
AutofillWalletSyncableServiceTest,
- PopulateWalletCardsAndAddresses_BillingAddressIdTransfer);
+ PopulateWalletTypesFromSyncData_BillingAddressIdTransfer);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
CopyRelevantMetadataFromDisk_KeepUseStats);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, NewWalletCard);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, EmptyNameOnCard);
+ FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
+ PaymentsCustomerData);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, ComputeCardsDiff);
FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
ComputeAddressesDiff);
@@ -102,12 +105,13 @@ class AutofillWalletSyncableService
syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list,
bool is_initial_data);
- // Populates the wallet cards and addresses from the sync data and uses the
- // sync data to link the card to its billing address.
- static void PopulateWalletCardsAndAddresses(
+ // Populates the wallet datatypes from the sync data and uses the sync data to
+ // link the card to its billing address.
+ static void PopulateWalletTypesFromSyncData(
const syncer::SyncDataList& data_list,
std::vector<CreditCard>* wallet_cards,
- std::vector<AutofillProfile>* wallet_addresses);
+ std::vector<AutofillProfile>* wallet_addresses,
+ std::vector<PaymentsCustomerData>* customer_data);
// Finds the copies of the same credit card from the server and on disk and
// overwrites the server version with the use stats saved on disk, and the
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
index c31ea73a9d5..2530bfcf151 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
@@ -10,6 +10,7 @@
#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/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/sync/protocol/autofill_specifics.pb.h"
@@ -52,6 +53,21 @@ syncer::SyncData CreateSyncDataForWalletAddress(const std::string& id) {
return syncer::SyncData::CreateLocalData(id, id, specifics);
}
+syncer::SyncData CreateSyncDataForPaymentsCustomerData(const std::string& id) {
+ sync_pb::EntitySpecifics specifics;
+
+ sync_pb::AutofillWalletSpecifics* wallet_specifics =
+ specifics.mutable_autofill_wallet();
+ wallet_specifics->set_type(
+ sync_pb::AutofillWalletSpecifics_WalletInfoType::
+ AutofillWalletSpecifics_WalletInfoType_CUSTOMER_DATA);
+
+ sync_pb::PaymentsCustomerData* customer_data_specifics =
+ wallet_specifics->mutable_customer_data();
+ customer_data_specifics->set_id(id);
+ return syncer::SyncData::CreateLocalData(id, id, specifics);
+}
+
class TestAutofillTable : public AutofillTable {
public:
explicit TestAutofillTable(std::vector<CreditCard> cards_on_disk)
@@ -77,9 +93,10 @@ class TestAutofillTable : public AutofillTable {
// Verify that the link between a card and its billing address from sync is
// present in the generated Autofill objects.
TEST(AutofillWalletSyncableServiceTest,
- PopulateWalletCardsAndAddresses_BillingAddressIdTransfer) {
+ PopulateWalletTypesFromSyncData_BillingAddressIdTransfer) {
std::vector<CreditCard> wallet_cards;
std::vector<AutofillProfile> wallet_addresses;
+ std::vector<PaymentsCustomerData> customer_data;
syncer::SyncDataList data_list;
// Create a Sync data for a card and its billing address.
@@ -87,8 +104,8 @@ TEST(AutofillWalletSyncableServiceTest,
data_list.push_back(CreateSyncDataForWalletCreditCard(
"card1" /* id */, "1" /* billing_address_id */));
- AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
- data_list, &wallet_cards, &wallet_addresses);
+ AutofillWalletSyncableService::PopulateWalletTypesFromSyncData(
+ data_list, &wallet_cards, &wallet_addresses, &customer_data);
ASSERT_EQ(1U, wallet_cards.size());
ASSERT_EQ(1U, wallet_addresses.size());
@@ -206,6 +223,7 @@ TEST(AutofillWalletSyncableServiceTest, NewWalletCard) {
std::vector<AutofillProfile> wallet_addresses;
std::vector<CreditCard> wallet_cards;
+ std::vector<PaymentsCustomerData> customer_data;
syncer::SyncDataList data_list;
// Create a Sync data for a card and its billing address.
@@ -213,8 +231,8 @@ TEST(AutofillWalletSyncableServiceTest, NewWalletCard) {
data_list.push_back(CreateSyncDataForWalletCreditCard(
"card1" /* id */, "1" /* billing_address_id */));
- AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
- data_list, &wallet_cards, &wallet_addresses);
+ AutofillWalletSyncableService::PopulateWalletTypesFromSyncData(
+ data_list, &wallet_cards, &wallet_addresses, &customer_data);
ASSERT_EQ(1U, wallet_cards.size());
@@ -227,14 +245,15 @@ TEST(AutofillWalletSyncableServiceTest, NewWalletCard) {
TEST(AutofillWalletSyncableServiceTest, EmptyNameOnCard) {
std::vector<CreditCard> wallet_cards;
std::vector<AutofillProfile> wallet_addresses;
+ std::vector<PaymentsCustomerData> customer_data;
syncer::SyncDataList data_list;
// Create a Sync data for a card and its billing address.
data_list.push_back(CreateSyncDataForWalletCreditCard(
"card1" /* id */, "1" /* billing_address_id */));
- AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
- data_list, &wallet_cards, &wallet_addresses);
+ AutofillWalletSyncableService::PopulateWalletTypesFromSyncData(
+ data_list, &wallet_cards, &wallet_addresses, &customer_data);
ASSERT_EQ(1U, wallet_cards.size());
@@ -247,6 +266,23 @@ TEST(AutofillWalletSyncableServiceTest, EmptyNameOnCard) {
wallet_cards.back().GetRawInfo(autofill::CREDIT_CARD_NAME_LAST).empty());
}
+TEST(AutofillWalletSyncableServiceTest, PaymentsCustomerData) {
+ std::vector<CreditCard> wallet_cards;
+ std::vector<AutofillProfile> wallet_addresses;
+ std::vector<PaymentsCustomerData> customer_data;
+ syncer::SyncDataList data_list;
+
+ // Create Sync data for Payments Customer data.
+ data_list.push_back(
+ CreateSyncDataForPaymentsCustomerData("deadbeef" /* id */));
+
+ AutofillWalletSyncableService::PopulateWalletTypesFromSyncData(
+ data_list, &wallet_cards, &wallet_addresses, &customer_data);
+
+ // Make sure the Payments customer id is there.
+ EXPECT_EQ("deadbeef", customer_data.back().customer_id);
+}
+
TEST(AutofillWalletSyncableServiceTest, ComputeCardsDiff) {
// Some arbitrary cards for testing.
CreditCard card0(CreditCard::MASKED_SERVER_CARD, "a");
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata.h
index fc715a0aa31..3ae94e14cae 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata.h
@@ -112,6 +112,13 @@ class AutofillWebData {
const base::string16& full_number) = 0;
virtual void MaskServerCreditCard(const std::string& id) = 0;
+ // Initiates the request for Payments customer data. The method
+ // OnWebDataServiceRequestDone of |consumer| gets called when the request is
+ // finished, with the customer data included in the argument |result|. The
+ // consumer owns the data.
+ virtual WebDataServiceBase::Handle GetPaymentsCustomerData(
+ WebDataServiceConsumer* consumer) = 0;
+
// Updates the metadata for a server card (masked or not).
virtual void UpdateServerCardMetadata(const CreditCard& credit_card) = 0;
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 d57b01c6b04..1a038008a9c 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
@@ -11,6 +11,7 @@
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
+#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/browser/webdata/autofill_table.h"
@@ -82,8 +83,8 @@ void AutofillWebDataBackendImpl::NotifyThatSyncHasStarted(
return;
// UI sequence notification.
- ui_task_runner_->PostTask(FROM_HERE,
- base::Bind(on_sync_started_callback_, model_type));
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(on_sync_started_callback_, model_type));
}
base::SupportsUserData* AutofillWebDataBackendImpl::GetDBUserData() {
@@ -419,6 +420,15 @@ WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressMetadata(
return WebDatabase::COMMIT_NEEDED;
}
+std::unique_ptr<WDTypedResult>
+AutofillWebDataBackendImpl::GetPaymentsCustomerData(WebDatabase* db) {
+ DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
+ std::unique_ptr<PaymentsCustomerData> customer_data;
+ AutofillTable::FromWebDatabase(db)->GetPaymentsCustomerData(&customer_data);
+ return std::make_unique<WDResult<std::unique_ptr<PaymentsCustomerData>>>(
+ AUTOFILL_CUSTOMERDATA_RESULT, std::move(customer_data));
+}
+
WebDatabase::State AutofillWebDataBackendImpl::ClearAllServerData(
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
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 91c379f30d2..070287977d2 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
@@ -163,6 +163,9 @@ class AutofillWebDataBackendImpl
WebDatabase::State UpdateServerAddressMetadata(const AutofillProfile& profile,
WebDatabase* db);
+ // Returns the PaymentsCustomerData from the database.
+ std::unique_ptr<WDTypedResult> GetPaymentsCustomerData(WebDatabase* db);
+
WebDatabase::State ClearAllServerData(WebDatabase* db);
WebDatabase::State ClearAllLocalData(WebDatabase* db);
@@ -214,7 +217,7 @@ class AutofillWebDataBackendImpl
WebDatabase::State RemoveExpiredFormElementsImpl(WebDatabase* db);
- base::ObserverList<AutofillWebDataServiceObserverOnDBSequence>
+ base::ObserverList<AutofillWebDataServiceObserverOnDBSequence>::Unchecked
db_observer_list_;
// WebDatabaseBackend allows direct access to DB.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 4d9db9dd58b..dd40364ed89 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -67,7 +67,7 @@ void AutofillWebDataService::ShutdownOnUISequence() {
weak_ptr_factory_.InvalidateWeakPtrs();
db_task_runner_->PostTask(
FROM_HERE,
- Bind(&AutofillWebDataBackendImpl::ResetUserData, autofill_backend_));
+ BindOnce(&AutofillWebDataBackendImpl::ResetUserData, autofill_backend_));
WebDataServiceBase::ShutdownOnUISequence();
}
@@ -213,6 +213,15 @@ void AutofillWebDataService::MaskServerCreditCard(const std::string& id) {
autofill_backend_, id));
}
+WebDataServiceBase::Handle AutofillWebDataService::GetPaymentsCustomerData(
+ WebDataServiceConsumer* consumer) {
+ return wdbs_->ScheduleDBTaskWithResult(
+ FROM_HERE,
+ Bind(&AutofillWebDataBackendImpl::GetPaymentsCustomerData,
+ autofill_backend_),
+ consumer);
+}
+
void AutofillWebDataService::ClearAllServerData() {
wdbs_->ScheduleDBTask(
FROM_HERE,
@@ -298,7 +307,8 @@ base::SupportsUserData* AutofillWebDataService::GetDBUserData() {
void AutofillWebDataService::GetAutofillBackend(
const base::Callback<void(AutofillWebDataBackend*)>& callback) {
db_task_runner_->PostTask(
- FROM_HERE, base::Bind(callback, base::RetainedRef(autofill_backend_)));
+ FROM_HERE,
+ base::BindOnce(callback, base::RetainedRef(autofill_backend_)));
}
base::SingleThreadTaskRunner* AutofillWebDataService::GetDBTaskRunner() {
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 8b26dc1c8ad..a1db37c055a 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -98,6 +98,10 @@ class AutofillWebDataService : public AutofillWebData,
const base::string16& full_number) override;
void MaskServerCreditCard(const std::string& id) override;
+ // PaymentsCustomerData.
+ WebDataServiceBase::Handle GetPaymentsCustomerData(
+ WebDataServiceConsumer* consumer) override;
+
void ClearAllServerData();
void ClearAllLocalData();
@@ -145,7 +149,7 @@ class AutofillWebDataService : public AutofillWebData,
}
private:
- base::ObserverList<AutofillWebDataServiceObserverOnUISequence>
+ base::ObserverList<AutofillWebDataServiceObserverOnUISequence>::Unchecked
ui_observer_list_;
// The task runner that this class uses for UI tasks.
diff --git a/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc b/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc
deleted file mode 100644
index d21981e122e..00000000000
--- a/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/webdata/web_data_model_type_controller.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-
-using syncer::ModelType;
-using syncer::ModelTypeController;
-using syncer::SyncClient;
-
-namespace autofill {
-
-WebDataModelTypeController::WebDataModelTypeController(
- ModelType type,
- SyncClient* sync_client,
- const scoped_refptr<base::SingleThreadTaskRunner>& model_thread,
- const scoped_refptr<AutofillWebDataService>& web_data_service,
- const DelegateFromWebData& delegate_from_web_data)
- : ModelTypeController(type, sync_client, model_thread),
- web_data_service_(web_data_service),
- delegate_from_web_data_(delegate_from_web_data) {}
-
-WebDataModelTypeController::~WebDataModelTypeController() {}
-
-ModelTypeController::DelegateProvider
-WebDataModelTypeController::GetDelegateProvider() {
- // As opposed to the default implementation, get the delegate on demand, the
- // web data service requires us to be on the model thread.
- return base::Bind(delegate_from_web_data_,
- base::RetainedRef(web_data_service_));
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h b/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h
deleted file mode 100644
index 1a80c1e7be1..00000000000
--- a/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_WEB_DATA_MODEL_TYPE_CONTROLLER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_WEB_DATA_MODEL_TYPE_CONTROLLER_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
-#include "components/sync/driver/model_type_controller.h"
-
-namespace syncer {
-class ModelTypeControllerDelegate;
-} // namespace syncer
-
-namespace autofill {
-
-class WebDataModelTypeController : public syncer::ModelTypeController {
- public:
- using DelegateFromWebData =
- base::Callback<base::WeakPtr<syncer::ModelTypeControllerDelegate>(
- AutofillWebDataService*)>;
-
- WebDataModelTypeController(
- syncer::ModelType type,
- syncer::SyncClient* sync_client,
- const scoped_refptr<base::SingleThreadTaskRunner>& model_thread,
- const scoped_refptr<AutofillWebDataService>& web_data_service,
- const DelegateFromWebData& delegate_from_web_data);
-
- ~WebDataModelTypeController() override;
-
- private:
- // syncer::ModelTypeController implementation.
- syncer::ModelTypeController::DelegateProvider GetDelegateProvider() override;
-
- // A reference to the AutofillWebDataService for this controller.
- scoped_refptr<AutofillWebDataService> web_data_service_;
-
- // How to grab the correct delegate from a web data.
- DelegateFromWebData delegate_from_web_data_;
-
- DISALLOW_COPY_AND_ASSIGN(WebDataModelTypeController);
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_WEB_DATA_MODEL_TYPE_CONTROLLER_H_
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 9058c7eeccc..97f8650618b 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
@@ -16,8 +16,8 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
+#include "base/task/post_task.h"
+#include "base/task/task_scheduler/task_scheduler.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -151,7 +151,7 @@ class WebDataServiceAutofillTest : public WebDataServiceTest {
AutofillWebDataServiceObserverOnDBSequence*) =
&AutofillWebDataService::AddObserver;
wds_->GetDBTaskRunner()->PostTask(
- FROM_HERE, base::Bind(add_observer_func, wds_, &observer_));
+ FROM_HERE, base::BindOnce(add_observer_func, wds_, &observer_));
base::TaskScheduler::GetInstance()->FlushForTesting();
}
@@ -160,7 +160,7 @@ class WebDataServiceAutofillTest : public WebDataServiceTest {
AutofillWebDataServiceObserverOnDBSequence*) =
&AutofillWebDataService::RemoveObserver;
wds_->GetDBTaskRunner()->PostTask(
- FROM_HERE, base::Bind(remove_observer_func, wds_, &observer_));
+ FROM_HERE, base::BindOnce(remove_observer_func, wds_, &observer_));
WebDataServiceTest::TearDown();
}
diff --git a/chromium/components/autofill/core/common/BUILD.gn b/chromium/components/autofill/core/common/BUILD.gn
index 32aa82cca98..2fc6a1f2c95 100644
--- a/chromium/components/autofill/core/common/BUILD.gn
+++ b/chromium/components/autofill/core/common/BUILD.gn
@@ -1,8 +1,9 @@
# Copyright 2014 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.
+import("//build/config/jumbo.gni")
-static_library("common") {
+jumbo_static_library("common") {
sources = [
"autofill_clock.cc",
"autofill_clock.h",
@@ -14,8 +15,8 @@ static_library("common") {
"autofill_features.h",
"autofill_l10n_util.cc",
"autofill_l10n_util.h",
- "autofill_pref_names.cc",
- "autofill_pref_names.h",
+ "autofill_prefs.cc",
+ "autofill_prefs.h",
"autofill_regex_constants.cc",
"autofill_regex_constants.h",
"autofill_regexes.cc",
@@ -52,16 +53,14 @@ static_library("common") {
deps = [
"//base",
"//base:i18n",
+ "//components/pref_registry",
+ "//components/prefs",
"//components/variations",
"//ui/base",
"//ui/gfx/geometry",
"//url",
]
- if (is_android) {
- # deps += [ 'autofill_jni_headers' ] TODO(GYP)
- }
-
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
@@ -69,6 +68,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"autofill_l10n_util_unittest.cc",
+ "autofill_prefs_unittest.cc",
"autofill_regexes_unittest.cc",
"autofill_util_unittest.cc",
"form_data_unittest.cc",
@@ -82,6 +82,9 @@ source_set("unit_tests") {
"//base",
"//base:i18n",
"//base/test:test_support",
+ "//components/pref_registry",
+ "//components/prefs",
+ "//components/prefs:test_support",
"//testing/gmock",
"//testing/gtest",
"//url",
diff --git a/chromium/components/autofill/core/common/autofill_features.cc b/chromium/components/autofill/core/common/autofill_features.cc
index 7534892decf..e61fee0bb26 100644
--- a/chromium/components/autofill/core/common/autofill_features.cc
+++ b/chromium/components/autofill/core/common/autofill_features.cc
@@ -4,6 +4,20 @@
#include "components/autofill/core/common/autofill_features.h"
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#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 {
@@ -12,11 +26,32 @@ namespace features {
const base::Feature kAutofillAddressNormalizer{
"AutofillAddressNormalizer", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillAlwaysFillAddresses{
+ "AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
+
// Controls the use of GET (instead of POST) to fetch cacheable autofill query
// responses.
const base::Feature kAutofillCacheQueryResponses{
"AutofillCacheQueryResponses", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillCreateDataForTest{
+ "AutofillCreateDataForTest", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillCreditCardAblationExperiment{
+ "AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillCreditCardAssist{
+ "AutofillCreditCardAssist", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillCreditCardLocalCardMigration{
+ "AutofillCreditCardLocalCardMigration", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillDeleteDisusedAddresses{
+ "AutofillDeleteDisusedAddresses", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillDeleteDisusedCreditCards{
+ "AutofillDeleteDisusedCreditCards", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether the credit card downstream keyboard accessory shows
// the Google Pay logo animation on iOS.
const base::Feature kAutofillDownstreamUseGooglePayBrandingOniOS{
@@ -32,28 +67,19 @@ const base::Feature kAutofillDynamicForms{"AutofillDynamicForms",
const base::Feature kAutofillEnableAccountWalletStorage{
"AutofillEnableAccountWalletStorage", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillEnableCompanyName{
+ "AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT};
+
// Controls whether the server credit cards are offered to be filled and
// uploaded to Google Pay if the sync service is in auth error.
const base::Feature kAutofillEnablePaymentsInteractionsOnAuthError{
"AutofillDontOfferServerCardsOnAuthError",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls whether Autofill should fill fields previously filled by the
-// website.
-const base::Feature kAutofillPrefilledFields{"AutofillPrefilledFields",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Controls whether autofill suggestions are filtered by field values previously
-// filled by website.
-const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms{
- "AutofillShowAllSuggestionsOnPrefilledForms",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Controls whether Autofill should rationalize repeated server type
-// predictions.
-const base::Feature kAutofillRationalizeRepeatedServerPredictions{
- "kAutofillRationalizeRepeatedServerPredictions",
- base::FEATURE_ENABLED_BY_DEFAULT};
+// When enabled, no local copy of server card will be saved when upload
+// succeeds.
+const base::Feature kAutofillNoLocalSaveOnUploadSuccess{
+ "AutofillNoLocalSaveOnUploadSuccess", base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether or not a minimum number of fields is required before
// heuristic field type prediction is run for a form.
@@ -73,10 +99,43 @@ const base::Feature kAutofillEnforceMinRequiredFieldsForUpload{
"AutofillEnforceMinRequiredFieldsForUpload",
base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillExpandedPopupViews{
+ "AutofillExpandedPopupViews", 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, the local card migration dialog will show the progress
+// and result of the migration after starting the migration. When disabled,
+// there is no feedback for the migration.
+const base::Feature kAutofillLocalCardMigrationShowFeedback{
+ "AutofillLocalCardMigrationShowFeedback",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether the manual fill fallback will be present.
const base::Feature kAutofillManualFallback{"AutofillManualFallback",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillPreferServerNamePredictions{
+ "AutofillPreferServerNamePredictions", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls whether Autofill should fill fields previously filled by the
+// website.
+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{
+ "kAutofillRationalizeRepeatedServerPredictions",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Controls whether Full Server credit cards should be reset when the sync
// service is in an auth error state.
const base::Feature kAutofillResetFullServerCardsOnAuthError{
@@ -90,6 +149,18 @@ const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout{
"AutofillRestrictUnownedFieldsToFormlessCheckout",
base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate{
+ "AutofillSaveCardDialogUnlabeledExpirationDate",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// 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};
+
+const base::Feature kAutofillScanCardholderName{
+ "AutofillScanCardholderName", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether experiment ids should be sent through
// Google Payments RPCs or not.
const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs{
@@ -103,11 +174,26 @@ const base::Feature kAutofillSendOnlyCountryInGetUploadDetails{
"AutofillSendOnlyCountryInGetUploadDetails",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables or Disables (mostly for hermetic testing) autofill server
+// communication. The URL of the autofill server can further be controlled via
+// the autofill-server-url param. The given URL should specify the complete
+// autofill server API url up to the parent "directory" of the "query" and
+// "upload" resources.
+// i.e., https://other.autofill.server:port/tbproxy/af/
+const base::Feature kAutofillServerCommunication{
+ "kAutofillServerCommunication", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Controls whether autofill suggestions are filtered by field values previously
+// filled by website.
+const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms{
+ "AutofillShowAllSuggestionsOnPrefilledForms",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether we show warnings in the Dev console for misused autocomplete
// types.
const base::Feature kAutofillShowAutocompleteConsoleWarnings{
"AutofillShowAutocompleteConsoleWarnings",
- base::FEATURE_ENABLED_BY_DEFAULT};
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Controls attaching the autofill type predictions to their respective
// element in the DOM.
@@ -119,6 +205,29 @@ const base::Feature kAutofillShowTypePredictions{
const base::Feature kAutofillSkipComparingInferredLabels{
"AutofillSkipComparingInferredLabels", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillSuggestInvalidProfileData{
+ "AutofillSuggestInvalidProfileData", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kAutofillSuppressDisusedAddresses{
+ "AutofillSuppressDisusedAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kAutofillSuppressDisusedCreditCards{
+ "AutofillSuppressDisusedCreditCards", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kAutofillUpstream{"AutofillUpstream",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillUpstreamAllowAllEmailDomains{
+ "AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillUpstreamAlwaysRequestCardholderName{
+ "AutofillUpstreamAlwaysRequestCardholderName",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillUpstreamBlankCardholderNameField{
+ "AutofillUpstreamBlankCardholderNameField",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls whether ELO cards should be uploaded to Google Payments.
const base::Feature kAutofillUpstreamDisallowElo{
"AutofillUpstreamDisallowElo", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -127,20 +236,137 @@ const base::Feature kAutofillUpstreamDisallowElo{
const base::Feature kAutofillUpstreamDisallowJcb{
"AutofillUpstreamDisallowJcb", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillUpstreamEditableCardholderName{
+ "AutofillUpstreamEditableCardholderName",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillUpstreamSendPanFirstSix{
+ "AutofillUpstreamSendPanFirstSix", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillUpstreamUpdatePromptExplanation{
+ "AutofillUpstreamUpdatePromptExplanation",
+ base::FEATURE_ENABLED_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 the PaymentsCustomerData is used to make requests to
+// Google Payments.
+const base::Feature kAutofillUsePaymentsCustomerData{
+ "AutofillUsePaymentsCustomerData", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAutofillVoteUsingInvalidProfileData{
+ "AutofillVoteUsingInvalidProfileData", base::FEATURE_ENABLED_BY_DEFAULT};
+
// Controls whether password generation is offered automatically on fields
-// percieved as eligible for generation.
+// perceived as eligible for generation.
+#if defined(OS_ANDROID)
const base::Feature kAutomaticPasswordGeneration = {
"AutomaticPasswordGeneration", base::FEATURE_DISABLED_BY_DEFAULT};
+#else
+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 kAutofillLocalCardMigrationCloseButtonDelay[] =
+ "show_close_migration_dialog_button_delay";
+
+const char kAutofillCreditCardLocalCardMigrationParameterName[] = "variant";
+
+const char kAutofillCreditCardLocalCardMigrationParameterWithoutSettingsPage[] =
+ "without-settings-page";
+
+const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
+
+#if defined(OS_MACOSX)
+const base::Feature kMacViewsAutofillPopup{"MacViewsAutofillPopup",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+#endif // defined(OS_MACOSX)
+
+bool IsAutofillCreditCardAssistEnabled() {
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ return false;
+#else
+ return base::FeatureList::IsEnabled(kAutofillCreditCardAssist);
+#endif
+}
+
+LocalCardMigrationExperimentalFlag GetLocalCardMigrationExperimentalFlag() {
+ if (!base::FeatureList::IsEnabled(kAutofillCreditCardLocalCardMigration))
+ return LocalCardMigrationExperimentalFlag::kMigrationDisabled;
+
+ std::string param = base::GetFieldTrialParamValueByFeature(
+ kAutofillCreditCardLocalCardMigration,
+ kAutofillCreditCardLocalCardMigrationParameterName);
+
+ if (param ==
+ kAutofillCreditCardLocalCardMigrationParameterWithoutSettingsPage) {
+ return LocalCardMigrationExperimentalFlag::kMigrationWithoutSettingsPage;
+ }
+ return LocalCardMigrationExperimentalFlag::kMigrationIncludeSettingsPage;
+}
+
+base::TimeDelta GetTimeoutForMigrationPromptFeedbackCloseButton() {
+ constexpr int show_close_button_timeout_in_seconds = 5;
+ return base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
+ kAutofillCreditCardLocalCardMigration,
+ kAutofillLocalCardMigrationCloseButtonDelay,
+ show_close_button_timeout_in_seconds));
+}
+
+bool IsAutofillUpstreamAlwaysRequestCardholderNameExperimentEnabled() {
+ return base::FeatureList::IsEnabled(
+ features::kAutofillUpstreamAlwaysRequestCardholderName);
+}
+
+bool IsAutofillUpstreamBlankCardholderNameFieldExperimentEnabled() {
+ return base::FeatureList::IsEnabled(
+ features::kAutofillUpstreamBlankCardholderNameField);
+}
+
+bool IsAutofillUpstreamEditableCardholderNameExperimentEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillUpstreamEditableCardholderName);
+}
+
+bool IsAutofillUpstreamSendPanFirstSixExperimentEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillUpstreamSendPanFirstSix);
+}
+
+bool IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillUpstreamUpdatePromptExplanation);
+}
+
+#if defined(OS_MACOSX)
+bool IsMacViewsAutofillPopupExperimentEnabled() {
+#if BUILDFLAG(MAC_VIEWS_BROWSER)
+ if (!::features::IsViewsBrowserCocoa())
+ return true;
+#endif
+
+ return base::FeatureList::IsEnabled(kMacViewsAutofillPopup);
+}
+#endif // defined(OS_MACOSX)
+
+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);
+}
+
} // namespace features
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_features.h b/chromium/components/autofill/core/common/autofill_features.h
index 7da46eb4253..c708629722a 100644
--- a/chromium/components/autofill/core/common/autofill_features.h
+++ b/chromium/components/autofill/core/common/autofill_features.h
@@ -5,38 +5,158 @@
#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_FEATURES_H_
#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_FEATURES_H_
+#include <string>
+
#include "base/feature_list.h"
+#include "base/strings/string16.h"
+#include "build/build_config.h"
+
+class PrefService;
+
+namespace base {
+struct Feature;
+}
namespace autofill {
namespace features {
// All features in alphabetical order.
extern const base::Feature kAutofillAddressNormalizer;
+extern const base::Feature kAutofillAlwaysFillAddresses;
extern const base::Feature kAutofillCacheQueryResponses;
+extern const base::Feature kAutofillCreateDataForTest;
+extern const base::Feature kAutofillCreditCardAblationExperiment;
+extern const base::Feature kAutofillCreditCardAssist;
+extern const base::Feature kAutofillCreditCardLocalCardMigration;
+extern const base::Feature kAutofillDeleteDisusedAddresses;
+extern const base::Feature kAutofillDeleteDisusedCreditCards;
extern const base::Feature kAutofillDownstreamUseGooglePayBrandingOniOS;
extern const base::Feature kAutofillDynamicForms;
extern const base::Feature kAutofillEnableAccountWalletStorage;
+extern const base::Feature kAutofillEnableCompanyName;
extern const base::Feature kAutofillEnablePaymentsInteractionsOnAuthError;
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 kAutofillLocalCardMigrationShowFeedback;
extern const base::Feature kAutofillManualFallback;
+extern const base::Feature kAutofillPreferServerNamePredictions;
+extern const base::Feature kAutofillNoLocalSaveOnUploadSuccess;
extern const base::Feature kAutofillPrefilledFields;
+extern const base::Feature kAutofillRationalizeFieldTypePredictions;
+extern const base::Feature kAutofillRationalizeRepeatedServerPredictions;
extern const base::Feature kAutofillResetFullServerCardsOnAuthError;
extern const base::Feature kAutofillRestrictUnownedFieldsToFormlessCheckout;
+extern const base::Feature kAutofillSaveCardDialogUnlabeledExpirationDate;
+extern const base::Feature kAutofillSaveCardSignInAfterLocalSave;
+extern const base::Feature kAutofillScanCardholderName;
extern const base::Feature kAutofillSendExperimentIdsInPaymentsRPCs;
extern const base::Feature kAutofillSendOnlyCountryInGetUploadDetails;
+extern const base::Feature kAutofillServerCommunication;
extern const base::Feature kAutofillShowAllSuggestionsOnPrefilledForms;
extern const base::Feature kAutofillShowAutocompleteConsoleWarnings;
extern const base::Feature kAutofillShowTypePredictions;
extern const base::Feature kAutofillSkipComparingInferredLabels;
+extern const base::Feature kAutofillSuggestInvalidProfileData;
+extern const base::Feature kAutofillSuppressDisusedAddresses;
+extern const base::Feature kAutofillSuppressDisusedCreditCards;
+extern const base::Feature kAutofillUpstream;
+extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
+extern const base::Feature kAutofillUpstreamAlwaysRequestCardholderName;
+extern const base::Feature kAutofillUpstreamBlankCardholderNameField;
extern const base::Feature kAutofillUpstreamDisallowElo;
extern const base::Feature kAutofillUpstreamDisallowJcb;
+extern const base::Feature kAutofillUpstreamEditableCardholderName;
+extern const base::Feature kAutofillUpstreamSendPanFirstSix;
+extern const base::Feature kAutofillUpstreamUpdatePromptExplanation;
extern const base::Feature kAutofillUpstreamUseGooglePayBrandingOnMobile;
+extern const base::Feature kAutofillUsePaymentsCustomerData;
+extern const base::Feature kAutofillVoteUsingInvalidProfileData;
extern const base::Feature kAutomaticPasswordGeneration;
extern const base::Feature kSingleClickAutofill;
-extern const base::Feature kAutofillPrefilledFields;
-extern const base::Feature kAutofillRationalizeRepeatedServerPredictions;
+extern const base::Feature kAutofillCreditCardLocalCardMigration;
+extern const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[];
+extern const char kAutofillLocalCardMigrationCloseButtonDelay[];
+extern const char kAutofillCreditCardLocalCardMigrationParameterName[];
+extern const char kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey[];
+extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
+extern const char
+ kAutofillCreditCardLocalCardMigrationParameterWithoutSettingsPage[];
+
+#if defined(OS_MACOSX)
+extern const base::Feature kMacViewsAutofillPopup;
+#endif // defined(OS_MACOSX)
+
+// Returns whether the Autofill credit card assist infobar should be shown.
+bool IsAutofillCreditCardAssistEnabled();
+
+// Enum for local card migration experimental flag states.
+enum class LocalCardMigrationExperimentalFlag {
+ // Local card migration disabled.
+ kMigrationDisabled,
+ // Only migrate local cards when user submits form.
+ kMigrationWithoutSettingsPage,
+ // Migrate both on submitted form and from settings page.
+ kMigrationIncludeSettingsPage,
+};
+
+// Returns kMigrationDisabled if no experimental behavior is enabled for
+// kAutofillCreditCardLocalCardMigration; Return kMigrationIncludeSettingsPage
+// if user enables the local card migration and does not exclude the settings
+// page. Return kMigrationWithoutSettingsPage if user chooses to exclude the
+// settings page migration.
+LocalCardMigrationExperimentalFlag GetLocalCardMigrationExperimentalFlag();
+
+// Returns the time delay for the local card migration dialog to show the close
+// button.
+base::TimeDelta GetTimeoutForMigrationPromptFeedbackCloseButton();
+
+// For testing purposes; not to be launched. When enabled, Chrome Upstream
+// always requests that the user enters/confirms cardholder name in the
+// offer-to-save dialog, regardless of if it was present or if the user is a
+// Google Payments customer. Note that this will override the detected
+// cardholder name, if one was found.
+bool IsAutofillUpstreamAlwaysRequestCardholderNameExperimentEnabled();
+
+// For experimental purposes; not to be made available in chrome://flags. When
+// enabled and Chrome Upstream requests the cardholder name in the offer-to-save
+// dialog, the field will be blank instead of being prefilled with the name from
+// the user's Google Account.
+bool IsAutofillUpstreamBlankCardholderNameFieldExperimentEnabled();
+
+// Returns whether the experiment is enabled where Chrome Upstream can request
+// the user to enter/confirm cardholder name in the offer-to-save bubble if it
+// was not detected or was conflicting during the checkout flow and the user is
+// NOT a Google Payments customer.
+bool IsAutofillUpstreamEditableCardholderNameExperimentEnabled();
+
+// Returns whether the experiment is enabled where Chrome Upstream sends the
+// first six digits of the card PAN to Google Payments to help determine whether
+// card upload is possible.
+bool IsAutofillUpstreamSendPanFirstSixExperimentEnabled();
+
+// Returns whether the experiment is enbabled where upstream sends updated
+// prompt explanation which changes 'save this card' to 'save your card and
+// billing address.'
+bool IsAutofillUpstreamUpdatePromptExplanationExperimentEnabled();
+
+#if defined(OS_MACOSX)
+// Returns true if whether the views autofill popup feature is enabled or the
+// we're using the views browser.
+bool IsMacViewsAutofillPopupExperimentEnabled();
+#endif // defined(OS_MACOSX)
+
+// 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();
+
} // namespace features
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_pref_names.cc b/chromium/components/autofill/core/common/autofill_pref_names.cc
deleted file mode 100644
index 5cd3354a4c0..00000000000
--- a/chromium/components/autofill/core/common/autofill_pref_names.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/common/autofill_pref_names.h"
-
-namespace autofill {
-namespace prefs {
-
-// Integer that is set to the last choice user made when prompted for saving a
-// credit card. The prompt is for user's consent in saving the card in the
-// server for signed in users and saving the card locally for non signed-in
-// users.
-const char kAutofillAcceptSaveCreditCardPromptState[] =
- "autofill.accept_save_credit_card_prompt_state";
-
-// Integer that is set to the billing customer number fetched from priority
-// preference.
-const char kAutofillBillingCustomerNumber[] = "billing_customer_number";
-
-// Boolean that is true if Autofill is enabled and allowed to save credit card
-// data.
-const char kAutofillCreditCardEnabled[] = "autofill.credit_card_enabled";
-
-// Number of times the credit card signin promo has been shown.
-const char kAutofillCreditCardSigninPromoImpressionCount[] =
- "autofill.credit_card_signin_promo_impression_count";
-
-// Boolean that is true if Autofill is enabled and allowed to save profile data.
-const char kAutofillProfileEnabled[] = "autofill.profile_enabled";
-
-// Boolean that is true if Autofill is enabled and allowed to save data.
-const char kAutofillEnabled[] = "autofill.enabled";
-
-// Integer that is set to the last version where the profile deduping routine
-// was run. This routine will be run once per version.
-const char kAutofillLastVersionDeduped[] = "autofill.last_version_deduped";
-
-// Integer that is set to the last version where disused addresses were
-// deleted. This deletion will be run once per version.
-const char kAutofillLastVersionDisusedAddressesDeleted[] =
- "autofill.last_version_disused_addresses_deleted";
-
-// Integer that is set to the last version where disused credit cards were
-// deleted. This deletion will be run once per version.
-const char kAutofillLastVersionDisusedCreditCardsDeleted[] =
- "autofill.last_version_disused_credit_cards_deleted";
-
-// Boolean that is true if the orphan rows in the autofill table were removed.
-const char kAutofillOrphanRowsRemoved[] = "autofill.orphan_rows_removed";
-
-// Boolean that's true when Wallet card and address import is enabled by the
-// user.
-const char kAutofillWalletImportEnabled[] = "autofill.wallet_import_enabled";
-
-// Boolean that is set to the last choice user made when prompted for saving an
-// unmasked server card locally.
-const char kAutofillWalletImportStorageCheckboxState[] =
- "autofill.wallet_import_storage_checkbox_state";
-
-} // namespace prefs
-} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_pref_names.h b/chromium/components/autofill/core/common/autofill_pref_names.h
deleted file mode 100644
index ee224e8aa8c..00000000000
--- a/chromium/components/autofill/core/common/autofill_pref_names.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PREF_NAMES_H_
-#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PREF_NAMES_H_
-
-namespace autofill {
-namespace prefs {
-
-// Alphabetical list of preference names specific to the Autofill
-// component. Keep alphabetized, and document each in the .cc file.
-
-extern const char kAutofillAcceptSaveCreditCardPromptState[];
-extern const char kAutofillBillingCustomerNumber[];
-extern const char kAutofillCreditCardEnabled[];
-extern const char kAutofillCreditCardSigninPromoImpressionCount[];
-extern const char kAutofillProfileEnabled[];
-extern const char kAutofillEnabled[];
-extern const char kAutofillLastVersionDeduped[];
-extern const char kAutofillLastVersionDisusedAddressesDeleted[];
-extern const char kAutofillLastVersionDisusedCreditCardsDeleted[];
-extern const char kAutofillOrphanRowsRemoved[];
-extern const char kAutofillWalletImportEnabled[];
-extern const char kAutofillWalletImportStorageCheckboxState[];
-
-// Possible values for previous user decision when we displayed a save credit
-// card prompt.
-enum PreviousSaveCreditCardPromptUserDecision {
- PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE,
- PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED,
- PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED,
- NUM_PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISIONS
-};
-
-} // namespace prefs
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PREF_NAMES_H_
diff --git a/chromium/components/autofill/core/common/autofill_prefs.cc b/chromium/components/autofill/core/common/autofill_prefs.cc
new file mode 100644
index 00000000000..5b9c0dcf69d
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_prefs.cc
@@ -0,0 +1,195 @@
+// 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/common/autofill_prefs.h"
+
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+
+namespace autofill {
+namespace prefs {
+
+// Integer that is set to the last choice user made when prompted for saving a
+// credit card. The prompt is for user's consent in saving the card in the
+// server for signed in users and saving the card locally for non signed-in
+// users.
+const char kAutofillAcceptSaveCreditCardPromptState[] =
+ "autofill.accept_save_credit_card_prompt_state";
+
+// Integer that is set to the billing customer number fetched from priority
+// preference.
+const char kAutofillBillingCustomerNumber[] = "billing_customer_number";
+
+// The field type, validity state map of all profiles.
+const char kAutofillProfileValidity[] = "autofill.profile_validity";
+
+// Boolean that is true if Autofill is enabled and allowed to save credit card
+// data.
+const char kAutofillCreditCardEnabled[] = "autofill.credit_card_enabled";
+
+// Number of times the credit card signin promo has been shown.
+const char kAutofillCreditCardSigninPromoImpressionCount[] =
+ "autofill.credit_card_signin_promo_impression_count";
+
+// Boolean that is true if Autofill is enabled and allowed to save data.
+const char kAutofillEnabledDeprecated[] = "autofill.enabled";
+
+// Boolean that is true if Japan address city field has been migrated to be a
+// part of the street field.
+const char kAutofillJapanCityFieldMigrated[] =
+ "autofill.japan_city_field_migrated_to_street_address";
+
+// Integer that is set to the last version where the profile deduping routine
+// was run. This routine will be run once per version.
+const char kAutofillLastVersionDeduped[] = "autofill.last_version_deduped";
+
+// Integer that is set to the last version where disused addresses were
+// deleted. This deletion will be run once per version.
+const char kAutofillLastVersionDisusedAddressesDeleted[] =
+ "autofill.last_version_disused_addresses_deleted";
+
+// Integer that is set to the last version where disused credit cards were
+// deleted. This deletion will be run once per version.
+const char kAutofillLastVersionDisusedCreditCardsDeleted[] =
+ "autofill.last_version_disused_credit_cards_deleted";
+
+// Boolean that is true if the orphan rows in the autofill table were removed.
+const char kAutofillOrphanRowsRemoved[] = "autofill.orphan_rows_removed";
+
+// Boolean that is true if Autofill is enabled and allowed to save profile data.
+const char kAutofillProfileEnabled[] = "autofill.profile_enabled";
+
+// Boolean that's true when Wallet card and address import is enabled by the
+// user.
+const char kAutofillWalletImportEnabled[] = "autofill.wallet_import_enabled";
+
+// Boolean that is set to the last choice user made when prompted for saving an
+// unmasked server card locally.
+const char kAutofillWalletImportStorageCheckboxState[] =
+ "autofill.wallet_import_storage_checkbox_state";
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+ // Synced prefs. Used for cross-device choices, e.g., credit card Autofill.
+ registry->RegisterDoublePref(
+ prefs::kAutofillBillingCustomerNumber, 0.0,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+ registry->RegisterBooleanPref(
+ prefs::kAutofillEnabledDeprecated, true,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterBooleanPref(
+ prefs::kAutofillProfileEnabled, true,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterIntegerPref(
+ prefs::kAutofillLastVersionDeduped, 0,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterIntegerPref(
+ prefs::kAutofillLastVersionDisusedAddressesDeleted, 0,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterBooleanPref(
+ prefs::kAutofillCreditCardEnabled, true,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterStringPref(
+ prefs::kAutofillProfileValidity, "",
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF);
+
+ // Non-synced prefs. Used for per-device choices, e.g., signin promo.
+ registry->RegisterIntegerPref(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount, 0);
+ registry->RegisterBooleanPref(prefs::kAutofillJapanCityFieldMigrated, false);
+ registry->RegisterBooleanPref(prefs::kAutofillWalletImportEnabled, true);
+ registry->RegisterBooleanPref(
+ prefs::kAutofillWalletImportStorageCheckboxState, true);
+ registry->RegisterIntegerPref(
+ prefs::kAutofillAcceptSaveCreditCardPromptState,
+ prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE);
+ registry->RegisterIntegerPref(
+ prefs::kAutofillLastVersionDisusedCreditCardsDeleted, 0);
+ registry->RegisterBooleanPref(prefs::kAutofillOrphanRowsRemoved, false);
+}
+
+void MigrateDeprecatedAutofillPrefs(PrefService* prefs) {
+ // If kAutofillCreditCardEnabled and kAutofillProfileEnabled prefs are
+ // currently using their default value and kAutofillEnabledDeprecated has a
+ // non-default value, override the valuAues of the new prefs. The following
+ // blocks should execute only once and are needed for those users who had
+ // Autofill disabled before introduction of the fine-grained prefs.
+ // TODO(crbug.com/870328): Remove these once M70- users are sufficiently low.
+ const PrefService::Preference* deprecated_autofill_pref =
+ prefs->FindPreference(prefs::kAutofillEnabledDeprecated);
+ DCHECK(deprecated_autofill_pref);
+
+ const PrefService::Preference* autofill_credit_card_pref =
+ prefs->FindPreference(prefs::kAutofillCreditCardEnabled);
+ DCHECK(autofill_credit_card_pref);
+ if (autofill_credit_card_pref->IsDefaultValue() &&
+ !deprecated_autofill_pref->IsDefaultValue()) {
+ prefs->SetBoolean(kAutofillCreditCardEnabled,
+ prefs->GetBoolean(kAutofillEnabledDeprecated));
+ }
+
+ const PrefService::Preference* autofill_profile_pref =
+ prefs->FindPreference(prefs::kAutofillProfileEnabled);
+ DCHECK(autofill_profile_pref);
+ if (autofill_profile_pref->IsDefaultValue() &&
+ !deprecated_autofill_pref->IsDefaultValue()) {
+ prefs->SetBoolean(kAutofillProfileEnabled,
+ prefs->GetBoolean(kAutofillEnabledDeprecated));
+ }
+}
+
+bool IsAutocompleteEnabled(const PrefService* prefs) {
+ return IsProfileAutofillEnabled(prefs);
+}
+
+bool IsAutofillEnabled(const PrefService* prefs) {
+ return IsProfileAutofillEnabled(prefs) || IsCreditCardAutofillEnabled(prefs);
+}
+
+void SetAutofillEnabled(PrefService* prefs, bool enabled) {
+ SetProfileAutofillEnabled(prefs, enabled);
+ SetCreditCardAutofillEnabled(prefs, enabled);
+}
+
+bool IsAutofillManaged(const PrefService* prefs) {
+ return prefs->IsManagedPreference(kAutofillEnabledDeprecated);
+}
+
+bool IsProfileAutofillManaged(const PrefService* prefs) {
+ return prefs->IsManagedPreference(kAutofillProfileEnabled);
+}
+
+bool IsCreditCardAutofillManaged(const PrefService* prefs) {
+ return prefs->IsManagedPreference(kAutofillCreditCardEnabled);
+}
+
+bool IsProfileAutofillEnabled(const PrefService* prefs) {
+ return prefs->GetBoolean(kAutofillProfileEnabled);
+}
+
+void SetProfileAutofillEnabled(PrefService* prefs, bool enabled) {
+ prefs->SetBoolean(kAutofillProfileEnabled, enabled);
+}
+
+bool IsCreditCardAutofillEnabled(const PrefService* prefs) {
+ return prefs->GetBoolean(kAutofillCreditCardEnabled);
+}
+
+void SetCreditCardAutofillEnabled(PrefService* prefs, bool enabled) {
+ prefs->SetBoolean(kAutofillCreditCardEnabled, enabled);
+}
+
+bool IsPaymentsIntegrationEnabled(const PrefService* prefs) {
+ return prefs->GetBoolean(kAutofillWalletImportEnabled);
+}
+
+void SetPaymentsIntegrationEnabled(PrefService* prefs, bool enabled) {
+ prefs->SetBoolean(kAutofillWalletImportEnabled, enabled);
+}
+
+std::string GetAllProfilesValidityMapsEncodedString(const PrefService* prefs) {
+ return prefs->GetString(kAutofillProfileValidity);
+}
+
+} // namespace prefs
+} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_prefs.h b/chromium/components/autofill/core/common/autofill_prefs.h
new file mode 100644
index 00000000000..4dc9d14ee74
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_prefs.h
@@ -0,0 +1,83 @@
+// 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_COMMON_AUTOFILL_PREFS_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PREFS_H_
+
+#include <string>
+
+class PrefService;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+} // namespace user_prefs
+
+namespace autofill {
+namespace prefs {
+
+// Alphabetical list of preference names specific to the Autofill
+// component. Keep alphabetized, and document each in the .cc file.
+extern const char kAutofillAcceptSaveCreditCardPromptState[];
+extern const char kAutofillBillingCustomerNumber[];
+// Do not get/set the value of this pref directly. Use provided getter/setter.
+extern const char kAutofillCreditCardEnabled[];
+extern const char kAutofillCreditCardSigninPromoImpressionCount[];
+// Please use kAutofillCreditCardEnabled and kAutofillProfileEnabled instead.
+extern const char kAutofillEnabledDeprecated[];
+extern const char kAutofillJapanCityFieldMigrated[];
+extern const char kAutofillLastVersionDeduped[];
+extern const char kAutofillLastVersionDisusedAddressesDeleted[];
+extern const char kAutofillLastVersionDisusedCreditCardsDeleted[];
+extern const char kAutofillOrphanRowsRemoved[];
+// Do not get/set the value of this pref directly. Use provided getter/setter.
+extern const char kAutofillProfileEnabled[];
+extern const char kAutofillWalletImportEnabled[];
+extern const char kAutofillWalletImportStorageCheckboxState[];
+extern const char kAutofillProfileValidity[];
+
+// Possible values for previous user decision when we displayed a save credit
+// card prompt.
+enum PreviousSaveCreditCardPromptUserDecision {
+ PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE,
+ PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED,
+ PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED,
+ NUM_PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISIONS
+};
+
+// Registers Autofill prefs.
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+// Migrates deprecated Autofill prefs values.
+void MigrateDeprecatedAutofillPrefs(PrefService* prefs);
+
+bool IsAutocompleteEnabled(const PrefService* prefs);
+
+bool IsAutofillEnabled(const PrefService* prefs);
+
+void SetAutofillEnabled(PrefService* prefs, bool enabled);
+
+bool IsAutofillManaged(const PrefService* prefs);
+
+bool IsProfileAutofillManaged(const PrefService* prefs);
+
+bool IsCreditCardAutofillManaged(const PrefService* prefs);
+
+bool IsProfileAutofillEnabled(const PrefService* prefs);
+
+void SetProfileAutofillEnabled(PrefService* prefs, bool enabled);
+
+bool IsCreditCardAutofillEnabled(const PrefService* prefs);
+
+void SetCreditCardAutofillEnabled(PrefService* prefs, bool enabled);
+
+bool IsPaymentsIntegrationEnabled(const PrefService* prefs);
+
+void SetPaymentsIntegrationEnabled(PrefService* prefs, bool enabled);
+
+std::string GetAllProfilesValidityMapsEncodedString(const PrefService* prefs);
+
+} // namespace prefs
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PREFS_H_
diff --git a/chromium/components/autofill/core/common/autofill_prefs_unittest.cc b/chromium/components/autofill/core/common/autofill_prefs_unittest.cc
new file mode 100644
index 00000000000..af9d814f3e9
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_prefs_unittest.cc
@@ -0,0 +1,77 @@
+// 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/common/autofill_prefs.h"
+
+#include <memory>
+
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_service_factory.h"
+#include "components/prefs/testing_pref_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+namespace prefs {
+
+class AutofillPrefsTest : public testing::Test {
+ protected:
+ AutofillPrefsTest() {}
+ ~AutofillPrefsTest() override {}
+
+ void SetUp() override { pref_service_ = CreatePrefServiceAndRegisterPrefs(); }
+
+ // Creates a PrefService and registers Autofill prefs.
+ std::unique_ptr<PrefService> CreatePrefServiceAndRegisterPrefs() {
+ scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
+ new user_prefs::PrefRegistrySyncable());
+ RegisterProfilePrefs(registry.get());
+ PrefServiceFactory factory;
+ factory.set_user_prefs(base::MakeRefCounted<TestingPrefStore>());
+ return factory.Create(registry);
+ }
+
+ PrefService* pref_service() { return pref_service_.get(); }
+
+ private:
+ std::unique_ptr<PrefService> pref_service_;
+};
+
+// Tests migrating the value of the deprecated Autofill master pref to the new
+// prefs and that this operation takes place only once.
+TEST_F(AutofillPrefsTest, MigrateDeprecatedAutofillPrefs) {
+ // All prefs should be enabled by default.
+ ASSERT_TRUE(pref_service()->GetBoolean(kAutofillEnabledDeprecated));
+ ASSERT_TRUE(pref_service()->GetBoolean(kAutofillProfileEnabled));
+ ASSERT_TRUE(pref_service()->GetBoolean(kAutofillCreditCardEnabled));
+
+ // Disable the deprecated master pref and make sure the new fine-grained prefs
+ // are not affected by that.
+ pref_service()->SetBoolean(kAutofillEnabledDeprecated, false);
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillEnabledDeprecated));
+ EXPECT_TRUE(pref_service()->GetBoolean(kAutofillProfileEnabled));
+ EXPECT_TRUE(pref_service()->GetBoolean(kAutofillCreditCardEnabled));
+
+ // Migrate the deprecated master pref's value to the new fine-grained prefs.
+ // Their values should become the same as the deprecated master pref's value.
+ MigrateDeprecatedAutofillPrefs(pref_service());
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillProfileEnabled));
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillCreditCardEnabled));
+
+ // Enable the deprecated master pref and make sure the new fine-grained prefs
+ // are not affected by that.
+ pref_service()->SetBoolean(kAutofillEnabledDeprecated, true);
+ EXPECT_TRUE(pref_service()->GetBoolean(kAutofillEnabledDeprecated));
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillProfileEnabled));
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillCreditCardEnabled));
+
+ // Migrate the deprecated master pref's value to the new fine-grained prefs.
+ // Their values should not be affected when migration happens a second time.
+ MigrateDeprecatedAutofillPrefs(pref_service());
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillProfileEnabled));
+ EXPECT_FALSE(pref_service()->GetBoolean(kAutofillCreditCardEnabled));
+}
+
+} // namespace prefs
+} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/common/autofill_regex_constants.cc b/chromium/components/autofill/core/common/autofill_regex_constants.cc
index fe72126c7a2..d861aa9ea87 100644
--- a/chromium/components/autofill/core/common/autofill_regex_constants.cc
+++ b/chromium/components/autofill/core/common/autofill_regex_constants.cc
@@ -28,6 +28,7 @@ const char kCompanyRe[] =
"|会社" // ja-JP
"|название.?компании" // ru
"|单位|公司" // zh-CN
+ "|شرکت" // fa
"|회사|직장"; // ko-KR
const char kAddressLine1Re[] =
"^address$|address[_-]?line(one)?|address1|addr1|street"
@@ -78,10 +79,11 @@ const char kAddressLinesExtraRe[] =
const char kAddressLookupRe[] = "lookup";
const char kCountryRe[] =
"country|countries"
- "|país|pais" // es
- "|国" // ja-JP
- "|国家" // zh-CN
- "|국가|나라"; // ko-KR
+ "|país|pais" // es
+ "|国" // ja-JP
+ "|国家" // zh-CN
+ "|국가|나라" // ko-KR
+ "|کشور"; // fa
const char kCountryLocationRe[] = "location";
const char kZipCodeRe[] =
"zip|postal|post.*code|pcode"
@@ -111,6 +113,7 @@ const char kCityRe[] =
"|Город" // ru
"|市" // zh-CN
"|分區" // zh-TW
+ "|شهر" // fa
"|^시[^도·・]|시[·・]?군[·・]?구"; // ko-KR
const char kStateRe[] =
"(?<!(united|hist|history).?)state|county|region|province"
@@ -121,6 +124,7 @@ const char kStateRe[] =
"|область" // ru
"|省" // zh-CN
"|地區" // zh-TW
+ "|استان" // fa
"|^시[·・]?도"; // ko-KR
/////////////////////////////////////////////////////////////////////////////
@@ -156,14 +160,14 @@ const char kNameOnCardRe[] =
const char kNameOnCardContextualRe[] = "name";
const char kCardNumberRe[] =
"(add)?(?:card|cc|acct).?(?:number|#|no|num|field)"
- "|(?<!telefon|haus)nummer" // de-DE
- "|credito|numero|número" // es
- "|numéro" // fr-FR
- "|カード番号" // ja-JP
- "|Номер.*карты" // ru
- "|信用卡号|信用卡号码" // zh-CN
- "|信用卡卡號" // zh-TW
- "|카드"; // ko-KR
+ "|(?<!telefon|haus)nummer" // de-DE
+ "|カード番号" // ja-JP
+ "|Номер.*карты" // ru
+ "|信用卡号|信用卡号码" // zh-CN
+ "|信用卡卡號" // zh-TW
+ "|카드" // ko-KR
+ "|(numero|número|numéro)(?!.*(document|fono|phone))"; // es/pt/fr
+
const char kCardCvcRe[] =
"verification|card.?identification|security.?code|card.?code"
"|security.?value"
@@ -243,6 +247,7 @@ const char kEmailRe[] =
"|Электронной.?Почты" // ru
"|邮件|邮箱" // zh-CN
"|電郵地址" // zh-TW
+ "|ایمیل|پست.*الکترونیک" // fa
"|(?:이메일|전자.?우편|[Ee]-?mail)(.?주소)?"; // ko-KR
/////////////////////////////////////////////////////////////////////////////
@@ -260,6 +265,7 @@ const char kNameRe[] =
"|^nom" // fr-FR
"|お名前|氏名" // ja-JP
"|^nome" // pt-BR, pt-PT
+ "|نام.*نام.*خانوادگی" // fa
"|姓名" // zh-CN
"|성명"; // ko-KR
const char kNameSpecificRe[] =
@@ -274,6 +280,7 @@ const char kFirstNameRe[] =
"|名" // ja-JP
"|nome" // pt-BR, pt-PT
"|Имя" // ru
+ "|نام" // fa
"|이름"; // ko-KR
const char kMiddleInitialRe[] = "middle.*initial|m\\.i\\.|mi$|\\bmi\\b";
const char kMiddleNameRe[] =
@@ -288,6 +295,7 @@ const char kLastNameRe[] =
"|姓" // ja-JP
"|morada|apelidos|surename|sobrenome" // pt-BR, pt-PT
"|Фамилия" // ru
+ "|نام.*خانوادگی" // fa
"|\\b성(?:[^명]|\\b)"; // ko-KR
/////////////////////////////////////////////////////////////////////////////
@@ -303,7 +311,8 @@ const char kPhoneRe[] =
"|телефон" // ru
"|电话" // zh-CN
"|(?:전화|핸드폰|휴대폰|휴대전화)(?:.?번호)?"; // ko-KR
-const char kCountryCodeRe[] = "country.*code|ccode|_cc";
+const char kCountryCodeRe[] =
+ "country.*code|ccode|_cc|phone.*code|user.*phone.*code";
const char kAreaCodeNotextRe[] = "^\\($";
const char kAreaCodeRe[] =
"area.*code|acode|area"
diff --git a/chromium/components/autofill/core/common/autofill_util.h b/chromium/components/autofill/core/common/autofill_util.h
index 92ddb896a0e..3f8f74f6d70 100644
--- a/chromium/components/autofill/core/common/autofill_util.h
+++ b/chromium/components/autofill/core/common/autofill_util.h
@@ -24,6 +24,10 @@ extern const char kAutofillKeyboardAccessoryAnimationDurationKey[];
extern const char kAutofillKeyboardAccessoryLimitLabelWidthKey[];
extern const char kAutofillKeyboardAccessoryHintKey[];
+// The length of the GUIDs used for local autofill data. It is different than
+// the length used for server autofill data.
+constexpr int kLocalGuidSize = 36;
+
// Returns true when command line switch |kEnableSuggestionsWithSubstringMatch|
// is on.
bool IsFeatureSubstringMatchEnabled();
diff --git a/chromium/components/autofill/core/common/form_data.cc b/chromium/components/autofill/core/common/form_data.cc
index 0bf0ff8ad6f..50bc6173b7e 100644
--- a/chromium/components/autofill/core/common/form_data.cc
+++ b/chromium/components/autofill/core/common/form_data.cc
@@ -17,7 +17,7 @@ namespace autofill {
namespace {
-const int kPickleVersion = 6;
+const int kFormDataPickleVersion = 6;
bool ReadGURL(base::PickleIterator* iter, GURL* url) {
std::string spec;
@@ -152,7 +152,7 @@ std::ostream& operator<<(std::ostream& os, const FormData& form) {
}
void SerializeFormData(const FormData& form_data, base::Pickle* pickle) {
- pickle->WriteInt(kPickleVersion);
+ pickle->WriteInt(kFormDataPickleVersion);
pickle->WriteString16(form_data.name);
pickle->WriteString(form_data.origin.spec());
pickle->WriteString(form_data.action.spec());
@@ -179,7 +179,7 @@ bool DeserializeFormData(base::PickleIterator* iter, FormData* form_data) {
return false;
}
- if (version < 1 || version > kPickleVersion) {
+ if (version < 1 || version > kFormDataPickleVersion) {
DVLOG(1) << "Unknown FormData pickle version " << version;
return false;
}
diff --git a/chromium/components/autofill/core/common/form_field_data.cc b/chromium/components/autofill/core/common/form_field_data.cc
index 69f2f3e416e..9aa08333f6b 100644
--- a/chromium/components/autofill/core/common/form_field_data.cc
+++ b/chromium/components/autofill/core/common/form_field_data.cc
@@ -15,8 +15,8 @@ namespace autofill {
namespace {
// Increment this anytime pickle format is modified as well as provide
-// deserialization routine from previous kPickleVersion format.
-const int kPickleVersion = 7;
+// deserialization routine from previous kFormFieldDataPickleVersion format.
+const int kFormFieldDataPickleVersion = 7;
void AddVectorToPickle(std::vector<base::string16> strings,
base::Pickle* pickle) {
@@ -147,7 +147,6 @@ FormFieldData::FormFieldData()
properties_mask(0),
is_enabled(false),
is_readonly(false),
- is_default(false),
label_source(LabelSource::UNKNOWN) {}
FormFieldData::FormFieldData(const FormFieldData& other) = default;
@@ -281,7 +280,7 @@ bool FormFieldData::operator<(const FormFieldData& field) const {
void SerializeFormFieldData(const FormFieldData& field_data,
base::Pickle* pickle) {
- pickle->WriteInt(kPickleVersion);
+ pickle->WriteInt(kFormFieldDataPickleVersion);
pickle->WriteString16(field_data.label);
pickle->WriteString16(field_data.name);
pickle->WriteString16(field_data.value);
@@ -455,7 +454,6 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field) {
<< "text_direction=" << field.text_direction << " "
<< "is_enabled=" << field.is_enabled << " "
<< "is_readonly=" << field.is_readonly << " "
- << "is_default=" << field.is_default << " "
<< "typed_value=" << field.typed_value << " "
<< "properties_mask=" << field.properties_mask << " "
<< "label_source=" << field.label_source;
diff --git a/chromium/components/autofill/core/common/form_field_data.h b/chromium/components/autofill/core/common/form_field_data.h
index 8f9e3cd942d..aedef09f757 100644
--- a/chromium/components/autofill/core/common/form_field_data.h
+++ b/chromium/components/autofill/core/common/form_field_data.h
@@ -155,7 +155,6 @@ struct FormFieldData {
// serialised for storage.
bool is_enabled;
bool is_readonly;
- bool is_default;
base::string16 typed_value;
// For the HTML snippet |<option value="US">United States</option>|, the
diff --git a/chromium/components/autofill/core/common/password_form.cc b/chromium/components/autofill/core/common/password_form.cc
index 9fc16b198a2..6e6a16ad9ce 100644
--- a/chromium/components/autofill/core/common/password_form.cc
+++ b/chromium/components/autofill/core/common/password_form.cc
@@ -36,14 +36,10 @@ void PasswordFormToJSON(const PasswordForm& form,
target->SetString("username_value", form.username_value);
target->SetString("password_elem", form.password_element);
target->SetString("password_value", form.password_value);
- target->SetBoolean("password_value_is_default",
- form.password_value_is_default);
target->SetString("new_password_element", form.new_password_element);
target->SetInteger("password_element_renderer_id",
form.password_element_renderer_id);
target->SetString("new_password_value", form.new_password_value);
- target->SetBoolean("new_password_value_is_default",
- form.new_password_value_is_default);
target->SetBoolean("new_password_marked_by_site",
form.new_password_marked_by_site);
target->SetString("other_possible_usernames",
@@ -86,8 +82,6 @@ PasswordForm::PasswordForm()
: scheme(SCHEME_HTML),
username_marked_by_site(false),
form_has_autofilled_value(false),
- password_value_is_default(false),
- new_password_value_is_default(false),
new_password_marked_by_site(false),
preferred(false),
blacklisted_by_user(false),
diff --git a/chromium/components/autofill/core/common/password_form.h b/chromium/components/autofill/core/common/password_form.h
index cc168863b0f..06c316d8a4f 100644
--- a/chromium/components/autofill/core/common/password_form.h
+++ b/chromium/components/autofill/core/common/password_form.h
@@ -226,10 +226,6 @@ struct PasswordForm {
// When parsing an HTML form, this is typically empty.
base::string16 password_value;
- // Whether the password value is the same as specified in the "value"
- // attribute of the input element. Only used in the renderer.
- bool password_value_is_default;
-
// If the form was a sign-up or a change password form, the name of the input
// element corresponding to the new password. Optional, and not persisted.
base::string16 new_password_element;
@@ -241,10 +237,6 @@ struct PasswordForm {
// The new password. Optional, and not persisted.
base::string16 new_password_value;
- // Whether the password value is the same as specified in the "value"
- // attribute of the input element. Only used in the renderer.
- bool new_password_value_is_default;
-
// Whether the |new_password_element| has an autocomplete=new-password
// attribute. This is only used in parsed HTML forms.
bool new_password_marked_by_site;
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 bcc0766b2b2..6dcaa7b85f5 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.cc
+++ b/chromium/components/autofill/core/common/password_form_fill_data.cc
@@ -11,18 +11,7 @@
namespace autofill {
-UsernamesCollectionKey::UsernamesCollectionKey() {}
-
-UsernamesCollectionKey::~UsernamesCollectionKey() {}
-
-bool UsernamesCollectionKey::operator<(
- const UsernamesCollectionKey& other) const {
- return std::tie(username, password, realm) <
- std::tie(other.username, other.password, other.realm);
-}
-
-PasswordFormFillData::PasswordFormFillData()
- : wait_for_username(false), is_possible_change_password_form(false) {}
+PasswordFormFillData::PasswordFormFillData() : wait_for_username(false) {}
PasswordFormFillData::PasswordFormFillData(const PasswordFormFillData& other) =
default;
@@ -58,8 +47,6 @@ void InitPasswordFormFillData(
result->username_field = username_field;
result->password_field = password_field;
result->wait_for_username = wait_for_username_before_autofill;
- result->is_possible_change_password_form =
- form_on_page.IsPossibleChangePasswordForm();
result->has_renderer_ids = form_on_page.has_renderer_ids;
if (preferred_match->is_public_suffix_match ||
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 cc90089ee7e..5db0c17b244 100644
--- a/chromium/components/autofill/core/common/password_form_fill_data.h
+++ b/chromium/components/autofill/core/common/password_form_fill_data.h
@@ -12,19 +12,6 @@
namespace autofill {
-// Helper struct for PasswordFormFillData
-struct UsernamesCollectionKey {
- UsernamesCollectionKey();
- ~UsernamesCollectionKey();
-
- // Defined so that this struct can be used as a key in a std::map.
- bool operator<(const UsernamesCollectionKey& other) const;
-
- base::string16 username;
- base::string16 password;
- std::string realm;
-};
-
struct PasswordAndRealm {
base::string16 password;
std::string realm;
@@ -35,8 +22,6 @@ struct PasswordAndRealm {
// form that we are filling.
struct PasswordFormFillData {
typedef std::map<base::string16, PasswordAndRealm> LoginCollection;
- typedef std::map<UsernamesCollectionKey,
- std::vector<base::string16> > UsernamesCollection;
// If |has_renderer_ids| == true then |form_renderer_id| contains the unique
// renderer form id. No special values for |has_renderer_ids| == false case
@@ -81,9 +66,6 @@ struct PasswordFormFillData {
// and our saved representation don't match up.
bool wait_for_username;
- // True if this form is a change password form.
- bool is_possible_change_password_form;
-
// True if renderer ids for form, username and password fields are present.
// TODO(https://crbug.com/831123): Remove this field when old parsing is
// removed and filling by renderer ids is by default.
diff --git a/chromium/components/autofill/core/common/password_generation_util.cc b/chromium/components/autofill/core/common/password_generation_util.cc
index c040a3ea40a..b96f81de574 100644
--- a/chromium/components/autofill/core/common/password_generation_util.cc
+++ b/chromium/components/autofill/core/common/password_generation_util.cc
@@ -58,6 +58,10 @@ void LogPasswordGenerationEvent(PasswordGenerationEvent event) {
event, EVENT_ENUM_COUNT);
}
+void LogPasswordGenerationUserEvent(PasswordGenerationUserEvent event) {
+ UMA_HISTOGRAM_ENUMERATION("PasswordGeneration.UserEvent", event);
+}
+
bool IsPasswordGenerationEnabled() {
if (base::FeatureList::IsEnabled(
autofill::features::kAutomaticPasswordGeneration))
diff --git a/chromium/components/autofill/core/common/password_generation_util.h b/chromium/components/autofill/core/common/password_generation_util.h
index 5543655fef3..40cefd89ce0 100644
--- a/chromium/components/autofill/core/common/password_generation_util.h
+++ b/chromium/components/autofill/core/common/password_generation_util.h
@@ -75,6 +75,25 @@ enum PasswordGenerationEvent {
EVENT_ENUM_COUNT
};
+// These values are used for metrics. Entries should not be renumbered and
+// numeric values should never be reused.
+// Metric: PasswordGeneration.UserEvent
+enum class PasswordGenerationUserEvent {
+ // The generated password was accepted by the user.
+ kPasswordAccepted = 0,
+ // The generated password was edited by the user in the field in which
+ // it was filled after being accepted.
+ kPasswordEdited = 1,
+ // The generated password was deleted by the user from the field
+ // in which it was filled after being accepted.
+ kPasswordDeleted = 2,
+ // The generated password was rejected by the user from the modal
+ // dialog, either by pressing "Cancel" in the dialog or by dismissing it.
+ // Only used on Android.
+ kPasswordRejectedInDialog = 3,
+ kMaxValue = kPasswordRejectedInDialog
+};
+
// Wrapper to store the user interactions with the password generation bubble.
struct PasswordGenerationActions {
// Whether the user has clicked on the learn more link.
@@ -124,6 +143,8 @@ void LogUserActions(PasswordGenerationActions actions);
void LogPasswordGenerationEvent(PasswordGenerationEvent event);
+void LogPasswordGenerationUserEvent(PasswordGenerationUserEvent event);
+
// Enumerates user actions after password generation bubble is shown.
// These are visible for testing purposes.
enum UserAction {
diff --git a/chromium/components/autofill/ios/browser/BUILD.gn b/chromium/components/autofill/ios/browser/BUILD.gn
index ab38995664f..3a3c11ebb98 100644
--- a/chromium/components/autofill/ios/browser/BUILD.gn
+++ b/chromium/components/autofill/ios/browser/BUILD.gn
@@ -49,16 +49,21 @@ source_set("test_support") {
testonly = true
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
+ "credit_card_save_manager_test_observer_bridge.h",
+ "credit_card_save_manager_test_observer_bridge.mm",
"fake_autofill_agent.h",
"fake_autofill_agent.mm",
"fake_js_autofill_manager.h",
"fake_js_autofill_manager.mm",
+ "ios_test_event_waiter.h",
]
public_deps = [
":browser",
]
deps = [
"//base",
+ "//base/test:test_support",
+ "//components/autofill/core/browser",
"//ios/web/public",
]
}
@@ -89,3 +94,14 @@ source_set("unit_tests") {
"//third_party/ocmock",
]
}
+
+bundle_data("autofill_test_bundle_data") {
+ testonly = true
+ sources = [
+ "//components/test/data/autofill/credit_card_upload_form_address_and_cc.html",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/" +
+ "{{source_root_relative_dir}}/{{source_file_part}}",
+ ]
+}
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.mm b/chromium/components/autofill/ios/browser/autofill_agent.mm
index 1073e8642c5..8c5255c4acc 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent.mm
@@ -27,7 +27,7 @@
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
@@ -212,7 +212,9 @@ void GetFormAndField(autofill::FormData* form,
prefObserverBridge_ = std::make_unique<PrefObserverBridge>(self);
prefChangeRegistrar_.Init(prefService);
prefObserverBridge_->ObserveChangesForPreference(
- autofill::prefs::kAutofillEnabled, &prefChangeRegistrar_);
+ autofill::prefs::kAutofillCreditCardEnabled, &prefChangeRegistrar_);
+ prefObserverBridge_->ObserveChangesForPreference(
+ autofill::prefs::kAutofillProfileEnabled, &prefChangeRegistrar_);
jsAutofillManager_ = [[JsAutofillManager alloc]
initWithReceiver:webState_->GetJSInjectionReceiver()];
@@ -689,9 +691,6 @@ void GetFormAndField(autofill::FormData* form,
#pragma mark - PrefObserverDelegate
- (void)onPreferenceChanged:(const std::string&)preferenceName {
- if (preferenceName != autofill::prefs::kAutofillEnabled)
- return;
-
// Processing the page can be needed here if Autofill is enabled in settings
// when the page is already loaded.
if ([self isAutofillEnabled])
@@ -701,7 +700,7 @@ void GetFormAndField(autofill::FormData* form,
#pragma mark - Private methods.
- (BOOL)isAutofillEnabled {
- if (!prefService_->GetBoolean(autofill::prefs::kAutofillEnabled))
+ if (!autofill::prefs::IsAutofillEnabled(prefService_))
return NO;
web::URLVerificationTrustLevel trustLevel;
diff --git a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
index 5f8c2b44a20..ca73deea805 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -8,7 +8,7 @@
#import "base/test/ios/wait_util.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/popup_item_ids.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/form_data.h"
#import "components/autofill/ios/browser/js_autofill_manager.h"
#include "components/prefs/pref_service.h"
@@ -46,7 +46,7 @@ class AutofillAgentTests : public PlatformTest {
test_web_state_.SetCurrentURL(GURL("https://example.com"));
prefs_ = autofill::test::PrefServiceForTesting();
- prefs_->SetBoolean(autofill::prefs::kAutofillEnabled, true);
+ autofill::prefs::SetAutofillEnabled(prefs_.get(), true);
autofill_agent_ =
[[AutofillAgent alloc] initWithPrefService:prefs_.get()
webState:&test_web_state_];
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
new file mode 100644
index 00000000000..85b804d80b7
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h
@@ -0,0 +1,53 @@
+// 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_IOS_BROWSER_CREDIT_CARD_SAVE_MANAGER_TEST_OBSERVER_BRIDGE_H_
+#define COMPONENTS_AUTOFILL_IOS_BROWSER_CREDIT_CARD_SAVE_MANAGER_TEST_OBSERVER_BRIDGE_H_
+
+#import <Foundation/Foundation.h>
+
+#include "base/macros.h"
+#include "components/autofill/core/browser/credit_card_save_manager.h"
+
+// A protocol to be adopted by EarlGrey tests to get notified of actions that
+// occur in autofill::CreditCardSaveManager.
+@protocol CreditCardSaveManagerTestObserver<NSObject>
+
+- (void)offeredLocalSave;
+
+- (void)decidedToRequestUploadSave;
+
+- (void)receivedGetUploadDetailsResponse;
+
+- (void)sentUploadCardRequest;
+
+@end
+
+namespace autofill {
+
+// Forwards actions from autofill::CreditCardSaveManager to the Objective-C
+// observer, CreditCardSaveManagerTestObserver.
+class CreditCardSaveManagerTestObserverBridge
+ : public CreditCardSaveManager::ObserverForTest {
+ public:
+ explicit CreditCardSaveManagerTestObserverBridge(
+ CreditCardSaveManager* credit_card_save_manager,
+ id<CreditCardSaveManagerTestObserver> observer);
+ virtual ~CreditCardSaveManagerTestObserverBridge() = default;
+
+ // CreditCardSaveManager::ObserverForTest:
+ void OnOfferLocalSave() override;
+ void OnDecideToRequestUploadSave() override;
+ void OnReceivedGetUploadDetailsResponse() override;
+ void OnSentUploadCardRequest() override;
+
+ private:
+ __weak id<CreditCardSaveManagerTestObserver> observer_ = nil;
+
+ DISALLOW_COPY_AND_ASSIGN(CreditCardSaveManagerTestObserverBridge);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_CREDIT_CARD_SAVE_MANAGER_TEST_OBSERVER_BRIDGE_H_
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
new file mode 100644
index 00000000000..c85b844d426
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm
@@ -0,0 +1,42 @@
+// 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.
+
+#import "components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h"
+
+#include "base/logging.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace autofill {
+
+CreditCardSaveManagerTestObserverBridge::
+ CreditCardSaveManagerTestObserverBridge(
+ CreditCardSaveManager* credit_card_save_manager,
+ id<CreditCardSaveManagerTestObserver> observer)
+ : observer_(observer) {
+ DCHECK(observer_);
+ DCHECK(credit_card_save_manager);
+ credit_card_save_manager->SetEventObserverForTesting(this);
+}
+
+void CreditCardSaveManagerTestObserverBridge::OnOfferLocalSave() {
+ [observer_ offeredLocalSave];
+}
+
+void CreditCardSaveManagerTestObserverBridge::OnDecideToRequestUploadSave() {
+ [observer_ decidedToRequestUploadSave];
+}
+
+void CreditCardSaveManagerTestObserverBridge::
+ OnReceivedGetUploadDetailsResponse() {
+ [observer_ receivedGetUploadDetailsResponse];
+}
+
+void CreditCardSaveManagerTestObserverBridge::OnSentUploadCardRequest() {
+ [observer_ sentUploadCardRequest];
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/ios/browser/ios_test_event_waiter.h b/chromium/components/autofill/ios/browser/ios_test_event_waiter.h
new file mode 100644
index 00000000000..0cd8eff237a
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/ios_test_event_waiter.h
@@ -0,0 +1,85 @@
+// 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_IOS_BROWSER_IOS_TEST_EVENT_WAITER_H_
+#define COMPONENTS_AUTOFILL_IOS_BROWSER_IOS_TEST_EVENT_WAITER_H_
+
+#include <list>
+
+#import "base/test/ios/wait_util.h"
+
+namespace autofill {
+
+// IOSTestEventWaiter is used to wait on given events that may have occurred
+// before call to Wait(), or after, in which case a |timeout| should be provided
+// to wait for those events to occur until |timeout| expires.
+//
+// Usage:
+// waiter_ = std::make_unique<IOSTestEventWaiter>({ ... });
+//
+// Do stuff, which (a)synchronously calls waiter_->OnEvent(...).
+//
+// waiter_->Wait();
+template <typename Event>
+class IOSTestEventWaiter {
+ public:
+ explicit IOSTestEventWaiter(std::list<Event> expected_events,
+ double timeout = 0);
+ ~IOSTestEventWaiter() = default;
+
+ // Either returns true right away if all events were observed between this
+ // object's construction and this call to Wait(); or returns true if that
+ // condition is met before |timeout|; Otherwise returns false. If |timeout| is
+ // zero, a reasonable default is used. Returns false if the current NSRunLoop
+ // is already running.
+ bool Wait();
+
+ // Observes an event. Returns false if the event is unexpected and true
+ // Otherwise.
+ bool OnEvent(Event event);
+
+ private:
+ std::list<Event> expected_events_;
+ bool runloop_running_;
+ double timeout_;
+
+ DISALLOW_COPY_AND_ASSIGN(IOSTestEventWaiter);
+};
+
+template <typename Event>
+IOSTestEventWaiter<Event>::IOSTestEventWaiter(std::list<Event> expected_events,
+ double timeout)
+ : expected_events_(std::move(expected_events)),
+ runloop_running_(false),
+ timeout_(timeout) {}
+
+template <typename Event>
+bool IOSTestEventWaiter<Event>::Wait() {
+ if (expected_events_.empty())
+ return true;
+
+ if (runloop_running_)
+ return false;
+
+ runloop_running_ = true;
+ bool result = base::test::ios::WaitUntilConditionOrTimeout(timeout_, ^{
+ return expected_events_.empty();
+ });
+ runloop_running_ = false;
+
+ return result;
+}
+
+template <typename Event>
+bool IOSTestEventWaiter<Event>::OnEvent(Event event) {
+ if (expected_events_.empty() || expected_events_.front() != event)
+ return false;
+
+ expected_events_.pop_front();
+ return true;
+}
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_IOS_TEST_EVENT_WAITER_H_
diff --git a/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.h b/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.h
index d3c7cf1c1b0..1f996b6839f 100644
--- a/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.h
+++ b/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.h
@@ -10,10 +10,10 @@
#include "base/macros.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
-// PersonalDataManagerObserverBridgeDelegate is used by PersonalDataManager to
-// informs its client implemented in Objective-C when it has finished loading
-// personal data from the web database.
-@protocol PersonalDataManagerObserverBridgeDelegate<NSObject>
+// PersonalDataManagerObserver is used by PersonalDataManager to informs its
+// client implemented in Objective-C when it has finished loading personal data
+// from the web database.
+@protocol PersonalDataManagerObserver<NSObject>
// Called when the PersonalDataManager changed in some way.
- (void)onPersonalDataChanged;
@@ -32,7 +32,7 @@ namespace autofill {
class PersonalDataManagerObserverBridge : public PersonalDataManagerObserver {
public:
explicit PersonalDataManagerObserverBridge(
- id<PersonalDataManagerObserverBridgeDelegate> delegate);
+ id<PersonalDataManagerObserver> delegate);
~PersonalDataManagerObserverBridge() override;
// PersonalDataManagerObserver implementation.
@@ -40,7 +40,7 @@ class PersonalDataManagerObserverBridge : public PersonalDataManagerObserver {
void OnInsufficientFormData() override;
private:
- __unsafe_unretained id<PersonalDataManagerObserverBridgeDelegate> delegate_;
+ __weak id<PersonalDataManagerObserver> delegate_;
DISALLOW_COPY_AND_ASSIGN(PersonalDataManagerObserverBridge);
};
diff --git a/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.mm b/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.mm
index bb3c48f63da..ed247acd3c5 100644
--- a/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.mm
+++ b/chromium/components/autofill/ios/browser/personal_data_manager_observer_bridge.mm
@@ -13,7 +13,7 @@
namespace autofill {
PersonalDataManagerObserverBridge::PersonalDataManagerObserverBridge(
- id<PersonalDataManagerObserverBridgeDelegate> delegate)
+ id<PersonalDataManagerObserver> delegate)
: delegate_(delegate) {
DCHECK(delegate_);
}
diff --git a/chromium/components/autofill/ios/form_util/BUILD.gn b/chromium/components/autofill/ios/form_util/BUILD.gn
index 3b0c7ee87ba..30daeef241f 100644
--- a/chromium/components/autofill/ios/form_util/BUILD.gn
+++ b/chromium/components/autofill/ios/form_util/BUILD.gn
@@ -56,7 +56,6 @@ source_set("unit_tests") {
"//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/tabs:tabs_internal",
"//ios/chrome/browser/web:test_support",
- "//ios/testing:ios_test_support",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
"//ios/web/web_state/js",
diff --git a/chromium/components/autofill/ios/form_util/DEPS b/chromium/components/autofill/ios/form_util/DEPS
deleted file mode 100644
index 4c30da6e895..00000000000
--- a/chromium/components/autofill/ios/form_util/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-specific_include_rules = {
- # Unittests using form.js need page_script_util to inject the script.
- "form_unittest\.mm": [
- "+ios/web/web_state/js/page_script_util.h",
- ],
-}
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
index ef98869b5d8..631770bce6d 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper.h
@@ -64,7 +64,7 @@ class FormActivityTabHelper
web::WebState* web_state_ = nullptr;
// The observers.
- base::ObserverList<FormActivityObserver> observers_;
+ base::ObserverList<FormActivityObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(FormActivityTabHelper);
};
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm b/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
index 27731e1b829..38e9f605e9a 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
@@ -10,17 +10,26 @@
#import "ios/web/public/test/fakes/test_web_client.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#import "ios/web/public/test/fakes/test_web_state_observer_util.h"
+#import "ios/web/public/test/js_test_util.h"
#import "ios/web/public/test/web_js_test.h"
#import "ios/web/public/test/web_test_with_web_state.h"
#include "testing/platform_test.h"
+class FormTestClient : public web::TestWebClient {
+ public:
+ NSString* GetDocumentStartScriptForAllFrames(
+ web::BrowserState* browser_state) const override {
+ return web::test::GetPageScript(@"form");
+ }
+};
+
// Test fixture for autofill::FormActivityTabHelper class.
class FormActivityTabHelperTest
: public web::WebJsTest<web::WebTestWithWebState> {
public:
FormActivityTabHelperTest()
: web::WebJsTest<web::WebTestWithWebState>(
- @[ @"chrome_bundle_all_frames" ]) {}
+ std::make_unique<FormTestClient>()) {}
void SetUp() override {
web::WebJsTest<web::WebTestWithWebState>::SetUp();
diff --git a/chromium/components/autofill/ios/form_util/form_unittest.mm b/chromium/components/autofill/ios/form_util/form_unittest.mm
index 6ff183c2143..6f535c37f0b 100644
--- a/chromium/components/autofill/ios/form_util/form_unittest.mm
+++ b/chromium/components/autofill/ios/form_util/form_unittest.mm
@@ -7,9 +7,9 @@
#import "ios/web/public/browser_state.h"
#import "ios/web/public/test/fakes/test_web_client.h"
#include "ios/web/public/test/fakes/test_web_state_observer.h"
+#import "ios/web/public/test/js_test_util.h"
#import "ios/web/public/test/web_js_test.h"
#import "ios/web/public/test/web_test_with_web_state.h"
-#import "ios/web/web_state/js/page_script_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -20,7 +20,7 @@ class FormTestClient : public web::TestWebClient {
public:
NSString* GetDocumentStartScriptForAllFrames(
web::BrowserState* browser_state) const override {
- return web::GetPageScript(@"form");
+ return web::test::GetPageScript(@"form");
}
};
diff --git a/chromium/components/autofill/ios/form_util/resources/form.js b/chromium/components/autofill/ios/form_util/resources/form.js
index efb0aaf6a59..7c3fa23c232 100644
--- a/chromium/components/autofill/ios/form_util/resources/form.js
+++ b/chromium/components/autofill/ios/form_util/resources/form.js
@@ -73,7 +73,7 @@ __gCrWeb.form.lastFocusedElement = null;
* programmatically.
* If the map is null, the source of changed is not track.
*/
- __gCrWeb.form.wasEditedByUser = null;
+__gCrWeb.form.wasEditedByUser = null;
/**
* Based on Element::isFormControlElement() (WebKit)
@@ -310,7 +310,8 @@ __gCrWeb.form.getFormElementFromIdentifier = function(name) {
* If called multiple times on the same runloop, only the last message is really
* sent.
*/
-var sendMessageOnNextLoop_ = function(mesg) {
+var sendMessageOnNextLoop_ =
+ function(mesg) {
if (!__gCrWeb.form.messageToSend) {
setTimeout(function() {
__gCrWeb.message.invokeOnHost(__gCrWeb.form.messageToSend);
@@ -343,7 +344,8 @@ var formActivity_ = function(evt) {
if (evt.type != 'blur') {
__gCrWeb.form.lastFocusedElement = document.activeElement;
}
- if (['change', 'input'].includes(evt.type)) {
+ if (['change', 'input'].includes(evt.type) &&
+ __gCrWeb.form.wasEditedByUser !== null) {
__gCrWeb.form.wasEditedByUser.set(target, evt.isTrusted);
}
if (target != __gCrWeb.form.lastFocusedElement) return;
@@ -397,8 +399,7 @@ var getFullyQualifiedUrl_ = function(originalURL) {
* to this function are ignored.
*/
var sendFormMutationMessageAfterDelay_ = function(msg, delay) {
- if (__gCrWeb.form.formMutationMessageToSend)
- return;
+ if (__gCrWeb.form.formMutationMessageToSend) return;
__gCrWeb.form.formMutationMessageToSend = msg;
setTimeout(function() {
@@ -419,12 +420,12 @@ var attachListeners_ = function() {
document.addEventListener('change', formActivity_, true);
document.addEventListener('input', formActivity_, true);
- /**
- * Other events are watched at the bubbling phase as this seems adequate in
- * practice and it is less obtrusive to page scripts than capture phase.
- */
+ /**
+ * Other events are watched at the bubbling phase as this seems adequate in
+ * practice and it is less obtrusive to page scripts than capture phase.
+ */
document.addEventListener('keyup', formActivity_, false);
- document.addEventListener('submit',submitHandler_, false);
+ document.addEventListener('submit', submitHandler_, false);
};
// Attach the listeners immediatly to try to catch early actions of the user.
@@ -447,22 +448,19 @@ __gCrWeb.form['trackFormMutations'] = function(delay) {
__gCrWeb.form.formMutationObserver = null;
}
- if (!delay)
- return;
+ if (!delay) return;
__gCrWeb.form.formMutationObserver =
new MutationObserver(function(mutations) {
for (var i = 0; i < mutations.length; i++) {
var mutation = mutations[i];
// Only process mutations to the tree of nodes.
- if (mutation.type != 'childList')
- continue;
+ if (mutation.type != 'childList') continue;
var addedElements = [];
for (var j = 0; j < mutation.addedNodes.length; j++) {
var node = mutation.addedNodes[j];
// Ignore non-element nodes.
- if (node.nodeType != Node.ELEMENT_NODE)
- continue;
+ if (node.nodeType != Node.ELEMENT_NODE) continue;
addedElements.push(node);
[].push.apply(
addedElements, [].slice.call(node.getElementsByTagName('*')));
@@ -492,7 +490,8 @@ __gCrWeb.form['trackFormMutations'] = function(delay) {
/**
* Enables or disables the tracking of input event sources.
*/
-__gCrWeb.form['toggleTrackingUserEditedFields'] = function(track) {
+__gCrWeb.form['toggleTrackingUserEditedFields'] =
+ function(track) {
if (track) {
__gCrWeb.form.wasEditedByUser =
__gCrWeb.form.wasEditedByUser || new WeakMap();
@@ -501,11 +500,12 @@ __gCrWeb.form['toggleTrackingUserEditedFields'] = function(track) {
}
}
-/**
- * Returns whether the last |input| or |change| event on |element| was triggered
- * by a user action (was "trusted").
- */
-__gCrWeb.form['fieldWasEditedByUser'] = function(element) {
+ /**
+ * Returns whether the last |input| or |change| event on |element| was
+ * triggered by a user action (was "trusted").
+ */
+ __gCrWeb.form['fieldWasEditedByUser'] =
+ function(element) {
if (__gCrWeb.form.wasEditedByUser === null) {
// Input event sources is not tracked.
// Return true to preserve previous behavior.