diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-16 09:59:13 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-20 10:28:53 +0000 |
commit | 6c11fb357ec39bf087b8b632e2b1e375aef1b38b (patch) | |
tree | c8315530db18a8ee566521c39ab8a6af4f72bc03 /chromium/components/autofill/core/browser | |
parent | 3ffaed019d0772e59d6cdb2d0d32fe4834c31f72 (diff) | |
download | qtwebengine-chromium-6c11fb357ec39bf087b8b632e2b1e375aef1b38b.tar.gz |
BASELINE: Update Chromium to 74.0.3729.159
Change-Id: I8d2497da544c275415aedd94dd25328d555de811
Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/autofill/core/browser')
175 files changed, 8823 insertions, 4006 deletions
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn index 9cf6e445d70..fea04db6961 100644 --- a/chromium/components/autofill/core/browser/BUILD.gn +++ b/chromium/components/autofill/core/browser/BUILD.gn @@ -18,6 +18,8 @@ jumbo_static_library("browser") { "address_combobox_model.h", "address_field.cc", "address_field.h", + "address_form_label_formatter.cc", + "address_form_label_formatter.h", "address_i18n.cc", "address_i18n.h", "address_normalization_manager.cc", @@ -92,6 +94,8 @@ jumbo_static_library("browser") { "autofill_wallet_model_type_controller.h", "card_unmask_delegate.cc", "card_unmask_delegate.h", + "contact_form_label_formatter.cc", + "contact_form_label_formatter.h", "contact_info.cc", "contact_info.h", "country_combobox_model.cc", @@ -125,6 +129,10 @@ jumbo_static_library("browser") { "form_structure.h", "form_types.cc", "form_types.h", + "label_formatter.cc", + "label_formatter.h", + "label_formatter_utils.cc", + "label_formatter_utils.h", "legacy_strike_database.cc", "legacy_strike_database.h", "legal_message_line.cc", @@ -133,6 +141,13 @@ jumbo_static_library("browser") { "local_card_migration_manager.h", "local_card_migration_strike_database.cc", "local_card_migration_strike_database.h", + "metrics/address_form_event_logger.cc", + "metrics/address_form_event_logger.h", + "metrics/credit_card_form_event_logger.cc", + "metrics/credit_card_form_event_logger.h", + "metrics/form_event_logger_base.cc", + "metrics/form_event_logger_base.h", + "metrics/form_events.h", "name_field.cc", "name_field.h", "password_requirements_spec_fetcher.h", @@ -161,6 +176,8 @@ jumbo_static_library("browser") { "phone_number_i18n.h", "popup_item_ids.h", "popup_types.h", + "price_field.cc", + "price_field.h", "randomized_encoder.cc", "randomized_encoder.h", "rationalization_util.cc", @@ -179,6 +196,8 @@ jumbo_static_library("browser") { "strike_database.h", "strike_database_integrator_base.cc", "strike_database_integrator_base.h", + "strike_database_integrator_test_strike_database.cc", + "strike_database_integrator_test_strike_database.h", "subkey_requester.cc", "subkey_requester.h", "suggestion.cc", @@ -188,6 +207,8 @@ jumbo_static_library("browser") { "sync_utils.h", "test_data_creator.cc", "test_data_creator.h", + "travel_field.cc", + "travel_field.h", "ui/card_unmask_prompt_controller.h", "ui/card_unmask_prompt_controller_impl.cc", "ui/card_unmask_prompt_controller_impl.h", @@ -252,6 +273,8 @@ jumbo_static_library("browser") { "autofill_save_card_infobar_delegate_mobile.cc", "autofill_save_card_infobar_delegate_mobile.h", "autofill_save_card_infobar_mobile.h", + "ui/card_expiration_date_fix_flow_view_delegate_mobile.cc", + "ui/card_expiration_date_fix_flow_view_delegate_mobile.h", "ui/card_name_fix_flow_view_delegate_mobile.cc", "ui/card_name_fix_flow_view_delegate_mobile.h", ] @@ -295,6 +318,7 @@ jumbo_static_library("browser") { "//base", "//base:i18n", "//components/data_use_measurement/core", + "//components/google/core/common", "//components/history/core/browser", "//components/infobars/core", "//components/keyed_service/core", @@ -375,6 +399,8 @@ jumbo_static_library("test_support") { "test_autofill_manager.h", "test_autofill_profile_validator.cc", "test_autofill_profile_validator.h", + "test_autofill_profile_validator_delayed.cc", + "test_autofill_profile_validator_delayed.h", "test_autofill_provider.cc", "test_autofill_provider.h", "test_credit_card_save_manager.cc", @@ -390,8 +416,6 @@ jumbo_static_library("test_support") { "test_legacy_strike_database.h", "test_local_card_migration_manager.cc", "test_local_card_migration_manager.h", - "test_local_card_migration_strike_database.cc", - "test_local_card_migration_strike_database.h", "test_personal_data_manager.cc", "test_personal_data_manager.h", "test_region_data_loader.cc", @@ -517,17 +541,16 @@ source_set("unit_tests") { "country_names_unittest.cc", "credit_card_field_unittest.cc", "credit_card_save_manager_unittest.cc", - "credit_card_save_strike_database_unittest.cc", "credit_card_unittest.cc", "field_candidates_unittest.cc", "field_filler_unittest.cc", "form_data_importer_unittest.cc", "form_field_unittest.cc", "form_structure_unittest.cc", + "label_formatter_utils_unittest.cc", "legacy_strike_database_unittest.cc", "legal_message_line_unittest.cc", "local_card_migration_manager_unittest.cc", - "local_card_migration_strike_database_unittest.cc", "name_field_unittest.cc", "password_generator_fips181_unittest.cc", "password_generator_unittest.cc", @@ -540,11 +563,13 @@ source_set("unit_tests") { "phone_field_unittest.cc", "phone_number_i18n_unittest.cc", "phone_number_unittest.cc", + "price_field_unittest.cc", "proto/legacy_proto_bridge_unittest.cc", "randomized_encoder_unittest.cc", "rationalization_util_unittest.cc", "region_combobox_model_unittest.cc", "search_field_unittest.cc", + "strike_database_integrator_test_strike_database_unittest.cc", "strike_database_unittest.cc", "subkey_requester_unittest.cc", "suggestion_selection_unittest.cc", @@ -600,6 +625,7 @@ source_set("unit_tests") { "//components/ukm:test_support", "//components/variations", "//components/variations:test_support", + "//components/variations/net", "//components/version_info:version_info", "//components/webdata/common", "//components/webdata_services:test_support", diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS index 35cb68b74d4..3536f9f5ce0 100644 --- a/chromium/components/autofill/core/browser/DEPS +++ b/chromium/components/autofill/core/browser/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+components/data_use_measurement/core", + "+components/google/core/common/google_util.h", "+components/grit/components_scaled_resources.h", "+components/history/core/browser", "+components/infobars/core", diff --git a/chromium/components/autofill/core/browser/OWNERS b/chromium/components/autofill/core/browser/OWNERS new file mode 100644 index 00000000000..013fa313149 --- /dev/null +++ b/chromium/components/autofill/core/browser/OWNERS @@ -0,0 +1 @@ +parastoog@google.com diff --git a/chromium/components/autofill/core/browser/accessory_sheet_data.cc b/chromium/components/autofill/core/browser/accessory_sheet_data.cc index dc0eb25bd7d..75cce7ffa5b 100644 --- a/chromium/components/autofill/core/browser/accessory_sheet_data.cc +++ b/chromium/components/autofill/core/browser/accessory_sheet_data.cc @@ -67,8 +67,9 @@ bool FooterCommand::operator==(const FooterCommand& fc) const { return display_text_ == fc.display_text_; } -AccessorySheetData::AccessorySheetData(const base::string16& title) - : title_(title) {} +AccessorySheetData::AccessorySheetData(FallbackSheetType sheet_type, + const base::string16& title) + : sheet_type_(sheet_type), title_(title) {} AccessorySheetData::AccessorySheetData(const AccessorySheetData& data) = default; diff --git a/chromium/components/autofill/core/browser/accessory_sheet_data.h b/chromium/components/autofill/core/browser/accessory_sheet_data.h index 5e439d787c1..384079b895e 100644 --- a/chromium/components/autofill/core/browser/accessory_sheet_data.h +++ b/chromium/components/autofill/core/browser/accessory_sheet_data.h @@ -87,14 +87,20 @@ class FooterCommand { base::string16 display_text_; }; +// GENERATED_JAVA_ENUM_PACKAGE: ( +// org.chromium.chrome.browser.autofill.keyboard_accessory) +enum class FallbackSheetType { + // Indicates the data type to which an AccessorySheetData object corresponds. + PASSWORD, + CREDIT_CARD +}; + // Represents the contents of a bottom sheet tab below the keyboard accessory, // which can correspond to passwords, credit cards, or profiles data. -// -// TODO(crbug.com/902425): Add a field to indicate if this corresponds to -// password, profile, or credit card data. class AccessorySheetData { public: - explicit AccessorySheetData(const base::string16& title); + explicit AccessorySheetData(FallbackSheetType sheet_type, + const base::string16& title); AccessorySheetData(const AccessorySheetData& data); AccessorySheetData(AccessorySheetData&& data); @@ -104,6 +110,7 @@ class AccessorySheetData { AccessorySheetData& operator=(AccessorySheetData&& data); const base::string16& title() const { return title_; } + FallbackSheetType get_sheet_type() const { return sheet_type_; } void add_user_info(UserInfo user_info) { user_info_list_.emplace_back(std::move(user_info)); @@ -126,6 +133,7 @@ class AccessorySheetData { bool operator==(const AccessorySheetData& data) const; private: + FallbackSheetType sheet_type_; base::string16 title_; std::vector<UserInfo> user_info_list_; std::vector<FooterCommand> footer_commands_; diff --git a/chromium/components/autofill/core/browser/account_info_getter.h b/chromium/components/autofill/core/browser/account_info_getter.h index 7d71b5fae99..44fa238ebec 100644 --- a/chromium/components/autofill/core/browser/account_info_getter.h +++ b/chromium/components/autofill/core/browser/account_info_getter.h @@ -17,7 +17,7 @@ class AccountInfoGetter { // 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; + virtual CoreAccountInfo 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 diff --git a/chromium/components/autofill/core/browser/address_form_label_formatter.cc b/chromium/components/autofill/core/browser/address_form_label_formatter.cc new file mode 100644 index 00000000000..604dd7882da --- /dev/null +++ b/chromium/components/autofill/core/browser/address_form_label_formatter.cc @@ -0,0 +1,31 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/address_form_label_formatter.h" + +namespace autofill { + +AddressFormLabelFormatter::AddressFormLabelFormatter( + const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types) + : LabelFormatter(app_locale, focused_field_type, field_types) { + for (const ServerFieldType& type : field_types) { + if (type != focused_field_type && type != ADDRESS_HOME_COUNTRY && + type != ADDRESS_BILLING_COUNTRY) { + field_types_for_labels_.push_back(type); + } + } +} + +AddressFormLabelFormatter::~AddressFormLabelFormatter() {} + +std::vector<base::string16> AddressFormLabelFormatter::GetLabels( + const std::vector<AutofillProfile*>& profiles) const { + // TODO(crbug.com/936168): Implement GetLabels(). + std::vector<base::string16> labels; + return labels; +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/address_form_label_formatter.h b/chromium/components/autofill/core/browser/address_form_label_formatter.h new file mode 100644 index 00000000000..1f0c4850a3d --- /dev/null +++ b/chromium/components/autofill/core/browser/address_form_label_formatter.h @@ -0,0 +1,39 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_FORM_LABEL_FORMATTER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_FORM_LABEL_FORMATTER_H_ + +#include <string> +#include <vector> + +#include "base/strings/string16.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/label_formatter.h" + +namespace autofill { + +// A LabelFormatter that creates Suggestions' disambiguating labels for forms +// with name and address fields and without email or phone fields. +class AddressFormLabelFormatter : public LabelFormatter { + public: + AddressFormLabelFormatter(const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types); + + ~AddressFormLabelFormatter() override; + + std::vector<base::string16> GetLabels( + const std::vector<AutofillProfile*>& profiles) const override; + + private: + // A collection of field types that can be used to make labels. This + // collection excludes the focused_field_type_ and address countries. + std::vector<ServerFieldType> field_types_for_labels_; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_FORM_LABEL_FORMATTER_H_ diff --git a/chromium/components/autofill/core/browser/address_i18n_unittest.cc b/chromium/components/autofill/core/browser/address_i18n_unittest.cc index 2647d888fe2..0f96565a4b7 100644 --- a/chromium/components/autofill/core/browser/address_i18n_unittest.cc +++ b/chromium/components/autofill/core/browser/address_i18n_unittest.cc @@ -55,7 +55,7 @@ TEST_P(FieldTypeMirrorConversionsTest, FieldTypeMirrorConversions) { EXPECT_EQ(test_data.server_field, server_field); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AddressI18nTest, FieldTypeMirrorConversionsTest, testing::Values( @@ -108,17 +108,17 @@ TEST_P(FieldTypeUnidirectionalConversionsTest, EXPECT_EQ(test_data.expected_address_field, actual_address_field); } -INSTANTIATE_TEST_CASE_P(AddressI18nTest, - FieldTypeUnidirectionalConversionsTest, - testing::Values( - FieldTypeUnidirectionalConversionsTestCase{ - ADDRESS_BILLING_LINE1, STREET_ADDRESS}, - FieldTypeUnidirectionalConversionsTestCase{ - ADDRESS_BILLING_LINE2, STREET_ADDRESS}, - FieldTypeUnidirectionalConversionsTestCase{ - ADDRESS_HOME_LINE1, STREET_ADDRESS}, - FieldTypeUnidirectionalConversionsTestCase{ - ADDRESS_HOME_LINE2, STREET_ADDRESS})); +INSTANTIATE_TEST_SUITE_P(AddressI18nTest, + FieldTypeUnidirectionalConversionsTest, + testing::Values( + FieldTypeUnidirectionalConversionsTestCase{ + ADDRESS_BILLING_LINE1, STREET_ADDRESS}, + FieldTypeUnidirectionalConversionsTestCase{ + ADDRESS_BILLING_LINE2, STREET_ADDRESS}, + FieldTypeUnidirectionalConversionsTestCase{ + ADDRESS_HOME_LINE1, STREET_ADDRESS}, + FieldTypeUnidirectionalConversionsTestCase{ + ADDRESS_HOME_LINE2, STREET_ADDRESS})); TEST(AddressI18nTest, UnconvertableServerFields) { EXPECT_FALSE(FieldForType(PHONE_HOME_NUMBER, nullptr)); diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc index d15eb19251a..8eae19020de 100644 --- a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc +++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "base/strings/string16.h" diff --git a/chromium/components/autofill/core/browser/autofill_assistant.cc b/chromium/components/autofill/core/browser/autofill_assistant.cc index d72104c0909..5cbbd241c0b 100644 --- a/chromium/components/autofill/core/browser/autofill_assistant.cc +++ b/chromium/components/autofill/core/browser/autofill_assistant.cc @@ -4,6 +4,7 @@ #include "components/autofill/core/browser/autofill_assistant.h" +#include "base/bind.h" #include "base/containers/adapters.h" #include "base/strings/string16.h" #include "components/autofill/core/browser/autofill_manager.h" diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h index cb53a600e65..0341ce2c565 100644 --- a/chromium/components/autofill/core/browser/autofill_client.h +++ b/chromium/components/autofill/core/browser/autofill_client.h @@ -123,6 +123,35 @@ class AutofillClient : public RiskDataLoader { base::string16 expiration_date_year; }; + // Used for options of upload prompt. + struct SaveCreditCardOptions { + SaveCreditCardOptions& with_has_non_focusable_field(bool b) { + has_non_focusable_field = b; + return *this; + } + + SaveCreditCardOptions& with_should_request_name_from_user(bool b) { + should_request_name_from_user = b; + return *this; + } + + SaveCreditCardOptions& with_should_request_expiration_date_from_user( + bool b) { + should_request_expiration_date_from_user = b; + return *this; + } + + SaveCreditCardOptions& with_show_prompt(bool b = true) { + show_prompt = b; + return *this; + } + + bool has_non_focusable_field = false; + bool should_request_name_from_user = false; + bool should_request_expiration_date_from_user = false; + bool show_prompt = false; + }; + // Callback to run after local credit card save is offered. Sends whether the // prompt was accepted, declined, or ignored in |user_decision|. typedef base::OnceCallback<void(SaveCardOfferUserDecision user_decision)> @@ -247,35 +276,43 @@ class AutofillClient : public RiskDataLoader { // Runs |callback| once the user makes a decision with respect to the // offer-to-save prompt. On desktop, shows the offer-to-save bubble if - // |show_prompt| is true; otherwise only shows the omnibox icon. On mobile, - // shows the offer-to-save infobar if |show_prompt| is true; otherwise does - // not offer to save at all. + // |options.show_prompt| is true; otherwise only shows the + // omnibox icon. On mobile, shows the offer-to-save infobar if + // |options.show_prompt| is true; otherwise does not offer to + // save at all. virtual void ConfirmSaveCreditCardLocally( const CreditCard& card, - bool show_prompt, + AutofillClient::SaveCreditCardOptions options, LocalSaveCardPromptCallback callback) = 0; #if defined(OS_ANDROID) - // Run |callback| if the card should be uploaded to payments with updated - // name from the user. + // Display the cardholder name fix flow prompt and run the |callback| if + // the card should be uploaded to payments with updated name from the user. virtual void ConfirmAccountNameFixFlow( base::OnceCallback<void(const base::string16&)> callback) = 0; + // Display the expiration date fix flow prompt with the |card| details + // and run the |callback| if the card should be uploaded to payments with + // updated expiration date from the user. + virtual void ConfirmExpirationDateFixFlow( + const CreditCard& card, + base::OnceCallback<void(const base::string16&, const base::string16&)> + callback) = 0; #endif // defined(OS_ANDROID) // Runs |callback| once the user makes a decision with respect to the // offer-to-save prompt. Displays the contents of |legal_message| to the user. // Displays a cardholder name textfield in the bubble if - // |should_request_name_from_user| is true. Displays a pair of expiration date - // dropdowns in the bubble if |should_request_expiration_date_from_user| is - // true. On desktop, shows the offer-to-save bubble if |show_prompt| is true; + // |options.should_request_name_from_user| is true. Displays + // a pair of expiration date dropdowns in the bubble if + // |should_request_expiration_date_from_user| is true. On desktop, shows the + // offer-to-save bubble if |options.show_prompt| is true; // otherwise only shows the omnibox icon. On mobile, shows the offer-to-save - // infobar if |show_prompt| is true; otherwise does not offer to save at all. + // infobar if |options.show_prompt| is true; otherwise does + // not offer to save at all. virtual void ConfirmSaveCreditCardToCloud( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, - bool should_request_name_from_user, - bool should_request_expiration_date_from_user, - bool show_prompt, + SaveCreditCardOptions options, UploadSaveCardPromptCallback callback) = 0; // Will show an infobar to get user consent for Credit Card assistive filling. diff --git a/chromium/components/autofill/core/browser/autofill_data_model.cc b/chromium/components/autofill/core/browser/autofill_data_model.cc index 913bfe22e69..59f83e57b3e 100644 --- a/chromium/components/autofill/core/browser/autofill_data_model.cc +++ b/chromium/components/autofill/core/browser/autofill_data_model.cc @@ -37,8 +37,9 @@ bool AutofillDataModel::UseDateEqualsInSeconds( return !((other->use_date() - use_date()).InSeconds()); } -bool AutofillDataModel::CompareFrecency(const AutofillDataModel* other, - base::Time comparison_time) const { +bool AutofillDataModel::HasGreaterFrecencyThan( + const AutofillDataModel* other, + base::Time comparison_time) const { double score = GetFrecencyScore(comparison_time); double other_score = other->GetFrecencyScore(comparison_time); @@ -79,4 +80,15 @@ bool AutofillDataModel::IsDeletable() const { return use_date_ < AutofillClock::Now() - kDisusedDataModelDeletionTimeDelta; } +AutofillDataModel::ValidityState AutofillDataModel::GetValidityState( + ServerFieldType type, + AutofillDataModel::ValidationSource source) const { + return AutofillDataModel::UNSUPPORTED; +} + +bool AutofillDataModel::ShouldSkipFillingOrSuggesting( + ServerFieldType type) const { + return false; +} + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_data_model.h b/chromium/components/autofill/core/browser/autofill_data_model.h index 719df504e04..07fd92b828d 100644 --- a/chromium/components/autofill/core/browser/autofill_data_model.h +++ b/chromium/components/autofill/core/browser/autofill_data_model.h @@ -22,6 +22,26 @@ struct AutofillMetadata; // PersonalDataManager. class AutofillDataModel : public FormGroup { public: + enum ValidityState { + // The field has not been validated. + UNVALIDATED = 0, + // The field is empty. + EMPTY = 1, + // The field is valid. + VALID = 2, + // The field is invalid. + INVALID = 3, + // The validation for the field is unsupported. + UNSUPPORTED = 4, + }; + + enum ValidationSource { + // The validity state is according to the client validation. + CLIENT = 0, + // The validity state is according to the server validation. + SERVER = 1, + }; + AutofillDataModel(const std::string& guid, const std::string& origin); ~AutofillDataModel() override; @@ -56,8 +76,8 @@ class AutofillDataModel : public FormGroup { // a combination of frequency and recency to determine the relevance of the // profile. |comparison_time_| allows consistent sorting throughout the // comparisons. - bool CompareFrecency(const AutofillDataModel* other, - base::Time comparison_time) const; + bool HasGreaterFrecencyThan(const AutofillDataModel* other, + base::Time comparison_time) const; // Gets the metadata associated with this autofill data model. virtual AutofillMetadata GetMetadata() const; @@ -70,6 +90,14 @@ class AutofillDataModel : public FormGroup { // longer than |kDisusedCreditCardDeletionTimeDelta|. virtual bool IsDeletable() const; + // Returns the validity state of the specified autofill type. + virtual ValidityState GetValidityState(ServerFieldType type, + ValidationSource source) const; + + // Check for the validity of the data. Leave the field empty if the data is + // invalid and the relevant feature is enabled. + virtual bool ShouldSkipFillingOrSuggesting(ServerFieldType type) const; + protected: // Called to update |use_count_| and |use_date_| when this data model is // the subject of user interaction (usually, when it's used to fill a form). diff --git a/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc b/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc index 670e50ce8d1..f719d9b7ac7 100644 --- a/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_data_model_unittest.cc @@ -110,7 +110,7 @@ TEST(AutofillDataModelTest, IsDeletable) { } enum Expectation { GREATER, LESS }; -struct CompareFrecencyTestCase { +struct HasGreaterFrecencyThanTestCase { const std::string guid_a; const int use_count_a; const base::Time use_date_a; @@ -122,10 +122,10 @@ struct CompareFrecencyTestCase { base::Time now = base::Time::Now(); -class CompareFrecencyTest - : public testing::TestWithParam<CompareFrecencyTestCase> {}; +class HasGreaterFrecencyThanTest + : public testing::TestWithParam<HasGreaterFrecencyThanTestCase> {}; -TEST_P(CompareFrecencyTest, CompareFrecency) { +TEST_P(HasGreaterFrecencyThanTest, HasGreaterFrecencyThan) { auto test_case = GetParam(); TestAutofillDataModel model_a(test_case.guid_a, test_case.use_count_a, test_case.use_date_a); @@ -133,39 +133,44 @@ TEST_P(CompareFrecencyTest, CompareFrecency) { test_case.use_date_b); EXPECT_EQ(test_case.expectation == GREATER, - model_a.CompareFrecency(&model_b, now)); + model_a.HasGreaterFrecencyThan(&model_b, now)); EXPECT_NE(test_case.expectation == GREATER, - model_b.CompareFrecency(&model_a, now)); + model_b.HasGreaterFrecencyThan(&model_a, now)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillDataModelTest, - CompareFrecencyTest, + HasGreaterFrecencyThanTest, testing::Values( // Same frecency, model_a has a smaller GUID (tie breaker). - CompareFrecencyTestCase{"guid_a", 8, now, "guid_b", 8, now, LESS}, + HasGreaterFrecencyThanTestCase{"guid_a", 8, now, "guid_b", 8, now, + LESS}, // Same recency, model_a has a bigger frequency. - CompareFrecencyTestCase{"guid_a", 10, now, "guid_b", 8, now, GREATER}, + HasGreaterFrecencyThanTestCase{"guid_a", 10, now, "guid_b", 8, now, + GREATER}, // Same recency, model_a has a smaller frequency. - CompareFrecencyTestCase{"guid_a", 8, now, "guid_b", 10, now, LESS}, + HasGreaterFrecencyThanTestCase{"guid_a", 8, now, "guid_b", 10, now, + LESS}, // Same frequency, model_a is more recent. - CompareFrecencyTestCase{"guid_a", 8, now, "guid_b", 8, - now - base::TimeDelta::FromDays(1), GREATER}, + HasGreaterFrecencyThanTestCase{"guid_a", 8, now, "guid_b", 8, + now - base::TimeDelta::FromDays(1), + GREATER}, // Same frequency, model_a is less recent. - CompareFrecencyTestCase{"guid_a", 8, now - base::TimeDelta::FromDays(1), - "guid_b", 8, now, LESS}, + HasGreaterFrecencyThanTestCase{"guid_a", 8, + now - base::TimeDelta::FromDays(1), + "guid_b", 8, now, LESS}, // Special case: occasional profiles. A profile with relatively low // usage and used recently (model_b) should not rank higher than a more // used profile that has been unused for a short amount of time // (model_a). - CompareFrecencyTestCase{ + HasGreaterFrecencyThanTestCase{ "guid_a", 300, now - base::TimeDelta::FromDays(5), "guid_b", 10, now - base::TimeDelta::FromDays(1), GREATER}, // Special case: moving. A new profile used frequently (model_b) should // rank higher than a profile with more usage that has not been used for // a while (model_a). - CompareFrecencyTestCase{"guid_a", 300, - now - base::TimeDelta::FromDays(15), "guid_b", - 10, now - base::TimeDelta::FromDays(1), LESS})); + HasGreaterFrecencyThanTestCase{ + "guid_a", 300, now - base::TimeDelta::FromDays(15), "guid_b", 10, + now - base::TimeDelta::FromDays(1), LESS})); } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc b/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc index d2de5151ec8..57c7748b217 100644 --- a/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc @@ -25,7 +25,7 @@ TEST_P(IsCJKNameTest, IsCJKName) { << "Failed for: " << test_case.full_name; } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillDataUtilTest, IsCJKNameTest, testing::Values( @@ -73,7 +73,7 @@ TEST_P(SplitNameTest, SplitName) { EXPECT_EQ(base::UTF8ToUTF16(test_case.family_name), name_parts.family); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillDataUtil, SplitNameTest, testing::Values( @@ -150,7 +150,7 @@ TEST_P(JoinNamePartsTest, JoinNameParts) { EXPECT_EQ(base::UTF8ToUTF16(test_case.full_name), joined); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillDataUtil, JoinNamePartsTest, testing::Values( @@ -213,7 +213,7 @@ TEST_P(ValidCountryCodeTest, ValidCountryCode) { IsValidCountryCode(test_case.country_code)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillDataUtil, ValidCountryCodeTest, testing::Values( diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc index adeb0145dd7..1b9a0429dd4 100644 --- a/chromium/components/autofill/core/browser/autofill_download_manager.cc +++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc @@ -4,6 +4,7 @@ #include "components/autofill/core/browser/autofill_download_manager.h" +#include <algorithm> #include <tuple> #include <utility> @@ -34,6 +35,7 @@ #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/submission_source.h" #include "components/data_use_measurement/core/data_use_user_data.h" +#include "components/google/core/common/google_util.h" #include "components/history/core/browser/history_service.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" @@ -52,6 +54,12 @@ namespace autofill { namespace { +// The reserved identifier ranges for autofill server experiments. +constexpr std::pair<int, int> kAutofillExperimentRanges[] = { + {3312923, 3312930}, {3314208, 3314209}, {3314711, 3314712}, + {3314445, 3314448}, {3314854, 3314883}, +}; + const size_t kMaxQueryGetSize = 1400; // 1.25KB const size_t kAutofillDownloadManagerMaxFormCacheSize = 16; const size_t kMaxFieldsPerQueryRequest = 100; @@ -85,6 +93,13 @@ const net::BackoffEntry::Policy kAutofillBackoffPolicy = { const char kDefaultAutofillServerURL[] = "https://clients1.google.com/tbproxy/af/"; +// The default number of days after which to reset the registry of autofill +// events for which an upload has been sent. +constexpr base::FeatureParam<int> kAutofillUploadThrottlingPeriodInDays( + &features::kAutofillUploadThrottling, + switches::kAutofillUploadThrottlingPeriodInDays, + 28); + // Header for API key. constexpr char kGoogApiKey[] = "X-Goog-Api-Key"; // Header to get base64 encoded serialized proto from API for safety. @@ -93,6 +108,12 @@ constexpr char kGoogEncodeResponseIfExecutable[] = constexpr char kDefaultAPIKey[] = ""; +// The maximum number of attempts for a given autofill request. +constexpr base::FeatureParam<int> kAutofillMaxServerAttempts( + &features::kAutofillServerCommunication, + "max-attempts", + 5); + // Returns the base URL for the autofill server. GURL GetAutofillServerURL() { // If a valid autofill server URL is specified on the command line, then the @@ -136,6 +157,20 @@ GURL GetAutofillServerURL() { return autofill_server_url; } +base::TimeDelta GetThrottleResetPeriod() { + return base::TimeDelta::FromDays( + std::max(1, kAutofillUploadThrottlingPeriodInDays.Get())); +} + +// Returns true if |id| is within |kAutofillExperimentRanges|. +bool IsAutofillExperimentId(int id) { + for (const auto& range : kAutofillExperimentRanges) { + if (range.first <= id && id <= range.second) + return true; + } + return false; +} + // Helper to log the HTTP |response_code| and other data received for // |request_type| to UMA. void LogHttpResponseData(AutofillDownloadManager::RequestType request_type, @@ -343,21 +378,24 @@ std::ostream& operator<<(std::ostream& out, return out; } -// Check for and returns true if |upload_event| is allowed to trigger an upload -// for |form|. If true, updates |prefs| to track that |upload_event| has been -// recorded for |form|. -bool IsUploadAllowed(const FormStructure& form, PrefService* pref_service) { - if (!pref_service || - !base::FeatureList::IsEnabled(features::kAutofillUploadThrottling)) { - return true; - } +// Returns true if an upload of |form| triggered by |form.submission_source()| +// can be throttled/suppressed. This is true if |prefs| indicates that this +// upload has already happened within the last update window. Updates |prefs| +// account for the upload for |form|. +bool CanThrottleUpload(const FormStructure& form, + base::TimeDelta throttle_reset_period, + PrefService* pref_service) { + // PasswordManager uploads are triggered via specific first occurrences and + // do not participate in the pref-service tracked throttling mechanism. Return + // false for these uploads. + if (!pref_service) + return false; // If the upload event pref needs to be reset, clear it now. - static constexpr base::TimeDelta kResetPeriod = base::TimeDelta::FromDays(28); base::Time now = AutofillClock::Now(); base::Time last_reset = pref_service->GetTime(prefs::kAutofillUploadEventsLastResetTimestamp); - if ((now - last_reset) > kResetPeriod) { + if ((now - last_reset) > throttle_reset_period) { AutofillDownloadManager::ClearUploadHistory(pref_service); } @@ -376,17 +414,15 @@ bool IsUploadAllowed(const FormStructure& form, PrefService* pref_service) { DCHECK_LT(bit, 32); const int mask = (1 << bit); - // Check if the upload should be allowed and, if so, update the upload event - // pref to set the appropriate bit. - bool allow_upload = ((value & mask) == 0); - if (allow_upload) { + // Check if this is the first upload for this event. If so, update the upload + // event pref to set the appropriate bit. + bool is_first_upload_for_event = ((value & mask) == 0); + if (is_first_upload_for_event) { DictionaryPrefUpdate update(pref_service, prefs::kAutofillUploadEvents); update->SetKey(std::move(key), base::Value(value | mask)); } - // Capture metrics and return. - AutofillMetrics::LogUploadEvent(form.submission_source(), allow_upload); - return allow_upload; + return !is_first_upload_for_event; } // Determines whether to use the API instead of the legacy server. @@ -441,8 +477,20 @@ struct AutofillDownloadManager::FormRequestData { std::vector<std::string> form_signatures; RequestType request_type; std::string payload; + int num_attempts = 0; }; +ScopedActiveAutofillExperiments::ScopedActiveAutofillExperiments() { + AutofillDownloadManager::ResetActiveExperiments(); +} + +ScopedActiveAutofillExperiments::~ScopedActiveAutofillExperiments() { + AutofillDownloadManager::ResetActiveExperiments(); +} + +std::vector<variations::VariationID>* + AutofillDownloadManager::active_experiments_ = nullptr; + AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver, Observer* observer, const std::string& api_key) @@ -450,6 +498,7 @@ AutofillDownloadManager::AutofillDownloadManager(AutofillDriver* driver, observer_(observer), api_key_(api_key), autofill_server_url_(GetAutofillServerURL()), + throttle_reset_period_(GetThrottleResetPeriod()), max_form_cache_size_(kAutofillDownloadManagerMaxFormCacheSize), loader_backoff_(&kAutofillBackoffPolicy), weak_factory_(this) { @@ -472,6 +521,7 @@ bool AutofillDownloadManager::StartQueryRequest( if (CountActiveFieldsInForms(forms) > kMaxFieldsPerQueryRequest) return false; + // Encode the query for the requested forms. AutofillQueryContents query; FormRequestData request_data; if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures, @@ -479,6 +529,17 @@ bool AutofillDownloadManager::StartQueryRequest( return false; } + // The set of active autofill experiments is constant for the life of the + // process. We initialize and statically cache it on first use. Leaked on + // process termination. + if (active_experiments_ == nullptr) + InitActiveExperiments(); + + // Attach any active autofill experiments. + query.mutable_experiments()->Reserve(active_experiments_->size()); + for (int id : *active_experiments_) + query.mutable_experiments()->Add(id); + // Get the query request payload. std::string payload; bool is_payload_serialized = @@ -515,7 +576,18 @@ bool AutofillDownloadManager::StartUploadRequest( const std::string& login_form_signature, bool observed_submission, PrefService* prefs) { - if (!IsEnabled() || !IsUploadAllowed(form, prefs)) + if (!IsEnabled()) + return false; + + bool can_throttle_upload = + CanThrottleUpload(form, throttle_reset_period_, prefs); + bool throttling_is_enabled = + base::FeatureList::IsEnabled(features::kAutofillUploadThrottling); + bool is_small_form = form.active_field_count() < 3; + bool allow_upload = + !(can_throttle_upload && (throttling_is_enabled || is_small_form)); + AutofillMetrics::LogUploadEvent(form.submission_source(), allow_upload); + if (!allow_upload) return false; AutofillUploadContents upload; @@ -525,6 +597,18 @@ bool AutofillDownloadManager::StartUploadRequest( return false; } + // If this upload was a candidate for throttling, tag it and make sure that + // any throttling sensitive features are enforced. + if (can_throttle_upload) { + upload.set_was_throttleable(true); + + // Don't send randomized metadata. + upload.clear_randomized_form_metadata(); + for (auto& f : *upload.mutable_field()) { + f.clear_randomized_field_metadata(); + } + } + // Get the POST payload that contains upload data. std::string payload; bool is_payload = UseApi() ? GetUploadPayloadForApi(upload, &payload) @@ -637,11 +721,11 @@ bool AutofillDownloadManager::StartRequest(FormRequestData request_data) { resource_request->method = method; // Add Chrome experiment state to the request headers. - variations::AppendVariationHeadersUnknownSignedIn( + variations::AppendVariationsHeaderUnknownSignedIn( request_url, driver_->IsIncognito() ? variations::InIncognito::kYes : variations::InIncognito::kNo, - &resource_request->headers); + resource_request.get()); // Set headers specific to the API if using it. if (UseApi()) @@ -649,10 +733,10 @@ bool AutofillDownloadManager::StartRequest(FormRequestData request_data) { resource_request->headers.SetHeader(kGoogEncodeResponseIfExecutable, "base64"); - // Put API key in request's header if there is. - if (!api_key_.empty() && - variations::ShouldAppendVariationHeaders(request_url)) { - // Make sure that we only send the API key to endpoints trusted by Chrome. + // Put API key in request's header if a key exists, and the endpoint is + // trusted by Google. + if (!api_key_.empty() && request_url.SchemeIs(url::kHttpsScheme) && + google_util::IsGoogleAssociatedDomainUrl(request_url)) { resource_request->headers.SetHeader(kGoogApiKey, api_key_); } @@ -738,6 +822,16 @@ std::string AutofillDownloadManager::GetCombinedSignature( return signature; } +// static +int AutofillDownloadManager::GetMaxServerAttempts() { + // This value is constant for the life of the browser, so we cache it + // statically on first use to avoid re-parsing the param on each retry + // opportunity. The range is forced to be within [1, 20]. + static int max_attempts = + std::max(1, std::min(20, kAutofillMaxServerAttempts.Get())); + return max_attempts; +} + void AutofillDownloadManager::OnSimpleLoaderComplete( std::list<std::unique_ptr<network::SimpleURLLoader>>::iterator it, FormRequestData request_data, @@ -786,6 +880,10 @@ void AutofillDownloadManager::OnSimpleLoaderComplete( if (response_code >= 400 && response_code <= 499) return; + // If we've exhausted the maximum number of attempts, don't retry. + if (++request_data.num_attempts >= GetMaxServerAttempts()) + return; + base::TimeDelta backoff = loader_backoff_.GetTimeUntilRelease(); LogExponentialBackoffDelay(request_data.request_type, backoff); @@ -815,4 +913,25 @@ void AutofillDownloadManager::OnSimpleLoaderComplete( observer_->OnUploadedPossibleFieldTypes(); } +void AutofillDownloadManager::InitActiveExperiments() { + auto* variations_http_header_provider = + variations::VariationsHttpHeaderProvider::GetInstance(); + DCHECK(variations_http_header_provider != nullptr); + + delete active_experiments_; + active_experiments_ = new std::vector<variations::VariationID>( + variations_http_header_provider->GetVariationsVector( + variations::GOOGLE_WEB_PROPERTIES_TRIGGER)); + base::EraseIf(*active_experiments_, [](variations::VariationID id) { + return !IsAutofillExperimentId(id); + }); + std::sort(active_experiments_->begin(), active_experiments_->end()); +} + +// static +void AutofillDownloadManager::ResetActiveExperiments() { + delete active_experiments_; + active_experiments_ = nullptr; +} + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.h b/chromium/components/autofill/core/browser/autofill_download_manager.h index ae7a8a988b2..f38c3ae8218 100644 --- a/chromium/components/autofill/core/browser/autofill_download_manager.h +++ b/chromium/components/autofill/core/browser/autofill_download_manager.h @@ -19,6 +19,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_type.h" +#include "components/variations/variations_http_header_provider.h" #include "net/base/backoff_entry.h" #include "services/network/public/cpp/simple_url_loader.h" #include "url/gurl.h" @@ -30,6 +31,13 @@ namespace autofill { class AutofillDriver; class FormStructure; +// A helper to make sure that tests which modify the set of active autofill +// experiments do not interfere with one another. +struct ScopedActiveAutofillExperiments { + ScopedActiveAutofillExperiments(); + ~ScopedActiveAutofillExperiments(); +}; + // Handles getting and updating Autofill heuristics. class AutofillDownloadManager { public: @@ -108,9 +116,12 @@ class AutofillDownloadManager { private: friend class AutofillDownloadManagerTest; + friend struct ScopedActiveAutofillExperiments; FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, QueryAndUploadTest); FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, BackoffLogic_Upload); FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, BackoffLogic_Query); + FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, RetryLimit_Upload); + FRIEND_TEST_ALL_PREFIXES(AutofillDownloadManagerTest, RetryLimit_Query); struct FormRequestData; typedef std::list<std::pair<std::string, std::string> > QueryRequestCache; @@ -151,12 +162,18 @@ class AutofillDownloadManager { std::string GetCombinedSignature( const std::vector<std::string>& forms_in_query) const; + // Returns the maximum number of attempts for a given autofill server request. + static int GetMaxServerAttempts(); + 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); + static void InitActiveExperiments(); + static void ResetActiveExperiments(); + // The AutofillDriver that this instance will use. Must not be null, and must // outlive this instance. AutofillDriver* const driver_; // WEAK @@ -172,6 +189,12 @@ class AutofillDownloadManager { // final path component for the request and the query params. const GURL autofill_server_url_; + // The period after which the tracked set of uploads to throttle is reset. + const base::TimeDelta throttle_reset_period_; + + // The set of active autofill server experiments. + static std::vector<variations::VariationID>* active_experiments_; + // 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 13d7f760d5c..9e23fc158a4 100644 --- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc @@ -38,6 +38,7 @@ #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/form_data.h" #include "components/prefs/pref_service.h" +#include "components/variations/variations_http_header_provider.h" #include "net/http/http_status_code.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -127,7 +128,7 @@ bool GetUploadRequestProtoFromRequest( // The responses in test are out of order and verify: successful query request, // successful upload request, failed upload request. class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer, - public testing::Test { + public ::testing::Test { public: AutofillDownloadManagerTest() : test_shared_loader_factory_( @@ -186,6 +187,7 @@ class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer, ResponseData() : type_of_response(REQUEST_QUERY_FAILED), error(0) {} }; + ScopedActiveAutofillExperiments scoped_active_autofill_experiments; base::test::ScopedTaskEnvironment task_environment_; std::list<ResponseData> responses_; scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; @@ -766,6 +768,163 @@ TEST_F(AutofillDownloadManagerTest, BackoffLogic_Upload) { EXPECT_EQ(1, buckets[0].count); } +TEST_F(AutofillDownloadManagerTest, RetryLimit_Query) { + FormData form; + FormFieldData field; + field.label = UTF8ToUTF16("address"); + field.name = UTF8ToUTF16("address"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = UTF8ToUTF16("address2"); + field.name = UTF8ToUTF16("address2"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = UTF8ToUTF16("city"); + field.name = UTF8ToUTF16("city"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = base::string16(); + field.name = UTF8ToUTF16("Submit"); + field.form_control_type = "submit"; + form.fields.push_back(field); + + std::vector<std::unique_ptr<FormStructure>> form_structures; + form_structures.push_back(std::make_unique<FormStructure>(form)); + + // Request with id 0. + base::HistogramTester histogram; + EXPECT_TRUE( + download_manager_.StartQueryRequest(ToRawPointerVector(form_structures))); + histogram.ExpectUniqueSample("Autofill.ServerQueryResponse", + AutofillMetrics::QUERY_SENT, 1); + + const auto kTimeDeltaMargin = base::TimeDelta::FromMilliseconds(100); + const int max_attempts = download_manager_.GetMaxServerAttempts(); + int attempt = 0; + while (true) { + auto* request = test_url_loader_factory_.GetPendingRequest(attempt); + ASSERT_TRUE(request != nullptr); + + // Request error incurs a retry after 1 second. + test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList( + request, + network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR), + "<html></html>", network::URLLoaderCompletionStatus(net::OK)); + + EXPECT_EQ(1U, responses_.size()); + const auto& response = responses_.front(); + EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_QUERY_FAILED, + response.type_of_response); + EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, response.error); + responses_.pop_front(); + + if (++attempt >= max_attempts) + break; + + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), + download_manager_.loader_backoff_.GetTimeUntilRelease() + + kTimeDeltaMargin); + run_loop.Run(); + } + + // There should not be an additional retry. + EXPECT_EQ(attempt, max_attempts); + EXPECT_EQ(nullptr, test_url_loader_factory_.GetPendingRequest(attempt)); + EXPECT_EQ(test_url_loader_factory_.NumPending(), 0); + + // Verify metrics. + histogram.ExpectBucketCount("Autofill.Query.HttpResponseOrErrorCode", + net::HTTP_INTERNAL_SERVER_ERROR, max_attempts); + auto buckets = histogram.GetAllSamples("Autofill.Query.FailingPayloadSize"); + ASSERT_EQ(1U, buckets.size()); + EXPECT_EQ(max_attempts, buckets[0].count); +} + +TEST_F(AutofillDownloadManagerTest, RetryLimit_Upload) { + FormData form; + FormFieldData field; + field.label = UTF8ToUTF16("address"); + field.name = UTF8ToUTF16("address"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = UTF8ToUTF16("address2"); + field.name = UTF8ToUTF16("address2"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = UTF8ToUTF16("city"); + field.name = UTF8ToUTF16("city"); + field.form_control_type = "text"; + form.fields.push_back(field); + + field.label = base::string16(); + field.name = UTF8ToUTF16("Submit"); + field.form_control_type = "submit"; + form.fields.push_back(field); + + base::HistogramTester histogram; + const auto kTimeDeltaMargin = base::TimeDelta::FromMilliseconds(100); + + auto form_structure = std::make_unique<FormStructure>(form); + form_structure->set_submission_source(SubmissionSource::FORM_SUBMISSION); + + // Request with id 0. + EXPECT_TRUE(download_manager_.StartUploadRequest( + *form_structure, true, ServerFieldTypeSet(), std::string(), true, + pref_service_.get())); + + const int max_attempts = download_manager_.GetMaxServerAttempts(); + int attempt = 0; + while (true) { + auto* request = test_url_loader_factory_.GetPendingRequest(attempt); + ASSERT_TRUE(request != nullptr); + + // Simulate a server failure. + test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList( + request, + network::CreateResourceResponseHead(net::HTTP_INTERNAL_SERVER_ERROR), + "", network::URLLoaderCompletionStatus(net::OK)); + + // Check that it was a failure. + ASSERT_EQ(1U, responses_.size()); + const auto& response = responses_.front(); + EXPECT_EQ(AutofillDownloadManagerTest::REQUEST_UPLOAD_FAILED, + response.type_of_response); + EXPECT_EQ(net::HTTP_INTERNAL_SERVER_ERROR, response.error); + responses_.pop_front(); + + if (++attempt >= max_attempts) + break; + + // A retry should have been scheduled with wait time on the order of + // |delay|. + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), + download_manager_.loader_backoff_.GetTimeUntilRelease() + + kTimeDeltaMargin); + run_loop.Run(); + } + + // There should not be an additional retry. + EXPECT_EQ(attempt, max_attempts); + EXPECT_EQ(nullptr, test_url_loader_factory_.GetPendingRequest(attempt)); + EXPECT_EQ(test_url_loader_factory_.NumPending(), 0); + + // Verify metrics. + histogram.ExpectBucketCount("Autofill.Upload.HttpResponseOrErrorCode", + net::HTTP_INTERNAL_SERVER_ERROR, max_attempts); + auto buckets = histogram.GetAllSamples("Autofill.Upload.FailingPayloadSize"); + ASSERT_EQ(1U, buckets.size()); + EXPECT_EQ(max_attempts, buckets[0].count); +} + TEST_F(AutofillDownloadManagerTest, QueryTooManyFieldsTest) { // Create a query that contains too many fields for the server. std::vector<FormData> forms(21); @@ -773,8 +932,8 @@ TEST_F(AutofillDownloadManagerTest, QueryTooManyFieldsTest) { for (auto& form : forms) { for (size_t i = 0; i < 5; ++i) { FormFieldData field; - field.label = base::IntToString16(i); - field.name = base::IntToString16(i); + field.label = base::NumberToString16(i); + field.name = base::NumberToString16(i); field.form_control_type = "text"; form.fields.push_back(field); } @@ -794,8 +953,8 @@ TEST_F(AutofillDownloadManagerTest, QueryNotTooManyFieldsTest) { for (auto& form : forms) { for (size_t i = 0; i < 4; ++i) { FormFieldData field; - field.label = base::IntToString16(i); - field.name = base::IntToString16(i); + field.label = base::NumberToString16(i); + field.name = base::NumberToString16(i); field.form_control_type = "text"; form.fields.push_back(field); } @@ -1024,6 +1183,11 @@ class AutofillServerCommunicationTest void TearDown() override { if (server_.Started()) ASSERT_TRUE(server_.ShutdownAndWaitUntilComplete()); + + auto* variations_http_header_provider = + variations::VariationsHttpHeaderProvider::GetInstance(); + if (variations_http_header_provider != nullptr) + variations_http_header_provider->ResetForTesting(); } // AutofillDownloadManager::Observer implementation. @@ -1098,6 +1262,7 @@ class AutofillServerCommunicationTest EXPECT_EQ(run_loop_, nullptr); run_loop_ = std::make_unique<base::RunLoop>(); + ScopedActiveAutofillExperiments scoped_active_autofill_experiments; AutofillDownloadManager download_manager(driver_.get(), this); bool succeeded = download_manager.StartQueryRequest(ToRawPointerVector(form_structures)); @@ -1115,6 +1280,7 @@ class AutofillServerCommunicationTest EXPECT_EQ(run_loop_, nullptr); run_loop_ = std::make_unique<base::RunLoop>(); + ScopedActiveAutofillExperiments scoped_active_autofill_experiments; AutofillDownloadManager download_manager(driver_.get(), this); bool succeeded = download_manager.StartUploadRequest( form, form_was_autofilled, available_field_types, login_form_signature, @@ -1188,11 +1354,11 @@ TEST_P(AutofillServerCommunicationTest, Upload) { // 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)); +INSTANTIATE_TEST_SUITE_P(All, + AutofillServerCommunicationTest, + ::testing::Values(DISABLED, + FINCHED_URL, + COMMAND_LINE_URL)); using AutofillQueryTest = AutofillServerCommunicationTest; @@ -1221,8 +1387,8 @@ TEST_P(AutofillQueryTest, CacheableResponse) { histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1); } - // Query again the next day. This should go to the cache, since the max-age - // for the cached response is 2 days. + // Query again. This should go to the cache, since the max-age for the cached + // response is 2 days. { SCOPED_TRACE("Second Query"); base::HistogramTester histogram; @@ -1236,6 +1402,76 @@ TEST_P(AutofillQueryTest, CacheableResponse) { } } +TEST_P(AutofillQueryTest, SendsExperiment) { + FormFieldData field; + field.label = UTF8ToUTF16("First Name:"); + field.name = UTF8ToUTF16("firstname"); + field.form_control_type = "text"; + + FormData form; + form.fields.push_back(field); + + std::vector<std::unique_ptr<FormStructure>> form_structures; + form_structures.push_back(std::make_unique<FormStructure>(form)); + + // Query for the form. This should go to the embedded server. + { + SCOPED_TRACE("First Query"); + base::HistogramTester histogram; + call_count_ = 0; + ASSERT_TRUE(SendQueryRequest(form_structures)); + EXPECT_EQ(1u, call_count_); + histogram.ExpectBucketCount("Autofill.ServerQueryResponse", + AutofillMetrics::QUERY_SENT, 1); + histogram.ExpectBucketCount("Autofill.Query.Method", METHOD_GET, 1); + histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1); + } + + // Add experiment/variation idd from the range reserved for autofill. + auto* variations_http_header_provider = + variations::VariationsHttpHeaderProvider::GetInstance(); + ASSERT_TRUE(variations_http_header_provider != nullptr); + variations_http_header_provider->ForceVariationIds( + {"t3314883", "t3312923", "t3314885"}, // first two valid, out-of-order + {}); + + // Query again. This should go to the embedded server since it's not the same + // as the previously cached query. + { + SCOPED_TRACE("Second Query"); + base::HistogramTester histogram; + call_count_ = 0; + payloads_.clear(); + ASSERT_TRUE(SendQueryRequest(form_structures)); + EXPECT_EQ(1u, call_count_); + histogram.ExpectBucketCount("Autofill.ServerQueryResponse", + AutofillMetrics::QUERY_SENT, 1); + histogram.ExpectBucketCount("Autofill.Query.Method", METHOD_GET, 1); + histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1); + + ASSERT_EQ(1u, payloads_.size()); + AutofillQueryContents query_contents; + ASSERT_TRUE(query_contents.ParseFromString(payloads_[0])); + ASSERT_EQ(2, query_contents.experiments_size()); + EXPECT_EQ(3312923, query_contents.experiments(0)); + EXPECT_EQ(3314883, query_contents.experiments(1)); + } + + // Query a third time (will experiments still enabled). This should go to the + // cache. + { + SCOPED_TRACE("Third Query"); + base::HistogramTester histogram; + call_count_ = 0; + ASSERT_TRUE(SendQueryRequest(form_structures)); + EXPECT_EQ(0u, call_count_); + histogram.ExpectBucketCount("Autofill.ServerQueryResponse", + AutofillMetrics::QUERY_SENT, 1); + histogram.ExpectBucketCount("Autofill.Query.Method", METHOD_GET, 1); + histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_HIT, 1); + } +} + TEST_P(AutofillQueryTest, ExpiredCacheInResponse) { FormFieldData field; field.label = UTF8ToUTF16("First Name:"); @@ -1468,9 +1704,9 @@ TEST_P(AutofillQueryTest, RichMetadata_Disabled) { // 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)); +INSTANTIATE_TEST_SUITE_P(All, + AutofillQueryTest, + ::testing::Values(FINCHED_URL, COMMAND_LINE_URL)); using AutofillUploadTest = AutofillServerCommunicationTest; @@ -1622,19 +1858,29 @@ TEST_P(AutofillUploadTest, Throttling) { TEST_P(AutofillUploadTest, ThrottlingDisabled) { ASSERT_NE(DISABLED, GetParam()); + base::test::ScopedFeatureList local_feature; + local_feature.InitWithFeatures( + // Enabled. + {}, + // Disabled + {features::kAutofillUploadThrottling, + features::kAutofillEnforceMinRequiredFieldsForUpload}); FormData form; + FormData small_form; FormFieldData field; field.label = UTF8ToUTF16("First Name:"); field.name = UTF8ToUTF16("firstname"); field.form_control_type = "text"; form.fields.push_back(field); + small_form.fields.push_back(field); field.label = UTF8ToUTF16("Last Name:"); field.name = UTF8ToUTF16("lastname"); field.form_control_type = "text"; form.fields.push_back(field); + small_form.fields.push_back(field); field.label = UTF8ToUTF16("Email:"); field.name = UTF8ToUTF16("email"); @@ -1643,15 +1889,16 @@ TEST_P(AutofillUploadTest, ThrottlingDisabled) { AutofillDownloadManager download_manager(driver_.get(), this); FormStructure form_structure(form); - - base::test::ScopedFeatureList local_feature; - local_feature.InitAndDisableFeature(features::kAutofillUploadThrottling); + FormStructure small_form_structure(small_form); for (int i = 0; i < 8; ++i) { SCOPED_TRACE(base::StringPrintf("submission source = %d", i)); base::HistogramTester histogram_tester; auto submission_source = static_cast<SubmissionSource>(i); form_structure.set_submission_source(submission_source); + small_form_structure.set_submission_source(submission_source); + + payloads_.clear(); // The first attempt should succeed. EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); @@ -1662,19 +1909,45 @@ TEST_P(AutofillUploadTest, ThrottlingDisabled) { // The third attempt should also succeed EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); - // No throttling metrics should be logged. - EXPECT_TRUE(histogram_tester.GetAllSamples("Autofill.UploadEvent").empty()); - EXPECT_TRUE( - histogram_tester - .GetAllSamples(AutofillMetrics::SubmissionSourceToUploadEventMetric( - submission_source)) - .empty()); + // The first small form attempt should succeed + EXPECT_TRUE(SendUploadRequest(small_form_structure, true, {}, "", true)); + + // The second small form attempt should be throttled, even if throttling + // is disabled. + EXPECT_FALSE(SendUploadRequest(small_form_structure, true, {}, "", true)); + + // All uploads were allowed.. + histogram_tester.ExpectBucketCount("Autofill.UploadEvent", 1, 4); + histogram_tester.ExpectBucketCount( + AutofillMetrics::SubmissionSourceToUploadEventMetric(submission_source), + 1, 4); + histogram_tester.ExpectBucketCount( + AutofillMetrics::SubmissionSourceToUploadEventMetric(submission_source), + 0, 1); + + // The last middle two uploads were marked as throttle-able. + ASSERT_EQ(4u, payloads_.size()); + for (size_t i = 0; i < payloads_.size(); ++i) { + AutofillUploadContents upload_contents; + ASSERT_TRUE(upload_contents.ParseFromString(payloads_[i])); + EXPECT_EQ(upload_contents.was_throttleable(), (i == 1 || i == 2)) + << "Wrong was_throttleable value for upload " << i; + EXPECT_FALSE(upload_contents.has_randomized_form_metadata()); + for (const auto& field : upload_contents.field()) { + EXPECT_FALSE(field.has_randomized_field_metadata()); + } + } } } TEST_P(AutofillUploadTest, PeriodicReset) { ASSERT_NE(DISABLED, GetParam()); + base::test::ScopedFeatureList local_feature; + local_feature.InitAndEnableFeatureWithParameters( + features::kAutofillUploadThrottling, + {{switches::kAutofillUploadThrottlingPeriodInDays, "16"}}); + FormData form; FormFieldData field; @@ -1708,11 +1981,11 @@ TEST_P(AutofillUploadTest, PeriodicReset) { EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); // Advance the clock, but not past the reset period. The pref won't reset, - // so the upload should never be sent. - test_clock.Advance(base::TimeDelta::FromDays(27)); + // so the upload should not be sent. + test_clock.Advance(base::TimeDelta::FromDays(15)); EXPECT_FALSE(SendUploadRequest(form_structure, true, {}, "", true)); - // Advance the clock beyond the reset period. The pref should bfde reset and + // Advance the clock beyond the reset period. The pref should be reset and // the upload should succeed. test_clock.Advance(base::TimeDelta::FromDays(2)); // Total = 29 EXPECT_TRUE(SendUploadRequest(form_structure, true, {}, "", true)); @@ -1779,8 +2052,8 @@ TEST_P(AutofillUploadTest, ResetOnClearUploadHisotry) { // 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, - AutofillUploadTest, - ::testing::Values(FINCHED_URL, COMMAND_LINE_URL)); +INSTANTIATE_TEST_SUITE_P(All, + AutofillUploadTest, + ::testing::Values(FINCHED_URL, COMMAND_LINE_URL)); } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory.h b/chromium/components/autofill/core/browser/autofill_driver_factory.h index cfb7d05b855..0c1a0a1062d 100644 --- a/chromium/components/autofill/core/browser/autofill_driver_factory.h +++ b/chromium/components/autofill/core/browser/autofill_driver_factory.h @@ -34,7 +34,7 @@ class AutofillDriverFactory { // Handles hiding of the corresponding tab. void TabHidden(); - AutofillClient* client() { return client_; }; + AutofillClient* client() { return client_; } protected: // The API manipulating the drivers map is protected to guarantee subclasses diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc index 0df561935d5..7e11d2a33f8 100644 --- a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc @@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/bind.h" #include "base/bind_helpers.h" #include "base/test/scoped_task_environment.h" #include "components/autofill/core/browser/test_autofill_client.h" diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc index 13e96ebe22c..ffc1f9c2c89 100644 --- a/chromium/components/autofill/core/browser/autofill_experiments.cc +++ b/chromium/components/autofill/core/browser/autofill_experiments.cc @@ -20,6 +20,7 @@ #include "components/strings/grit/components_strings.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_service_utils.h" +#include "components/sync/driver/sync_user_settings.h" #include "components/variations/variations_associated_data.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/google_service_auth_error.h" @@ -70,7 +71,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service, // Users who have enabled a passphrase have chosen to not make their sync // information accessible to Google. Since upload makes credit card data // available to other Google systems, disable it for passphrase users. - if (sync_service->IsUsingSecondaryPassphrase()) + if (sync_service->GetUserSettings()->IsUsingSecondaryPassphrase()) return false; // Don't offer upload for users that are only syncing locally, since they diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc index 2f40e6d1911..0024f2d615f 100644 --- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc +++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc @@ -90,7 +90,7 @@ void AutofillExternalDelegate::OnSuggestionsReturned( Suggestion scan_credit_card( l10n_util::GetStringUTF16(IDS_AUTOFILL_SCAN_CREDIT_CARD)); scan_credit_card.frontend_id = POPUP_ITEM_ID_SCAN_CREDIT_CARD; - scan_credit_card.icon = base::ASCIIToUTF16("scanCreditCardIcon"); + scan_credit_card.icon = "scanCreditCardIcon"; suggestions.push_back(scan_credit_card); } @@ -108,7 +108,7 @@ void AutofillExternalDelegate::OnSuggestionsReturned( suggestions.emplace_back( l10n_util::GetStringUTF16(IDS_AUTOFILL_SHOW_ACCOUNT_CARDS)); suggestions.back().frontend_id = POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS; - suggestions.back().icon = base::ASCIIToUTF16("google"); + suggestions.back().icon = "google"; } if (has_autofill_suggestions_) @@ -358,12 +358,12 @@ void AutofillExternalDelegate::ApplyAutofillOptions( // So Google Pay Icon is just attached to an existing menu item. if (is_all_server_suggestions) { #if defined(OS_ANDROID) || defined(OS_IOS) - suggestions->back().icon = base::ASCIIToUTF16("googlePay"); + suggestions->back().icon = "googlePay"; #else - suggestions->back().icon = base::ASCIIToUTF16( + suggestions->back().icon = ui::NativeTheme::GetInstanceForNativeUi()->SystemDarkModeEnabled() ? "googlePayDark" - : "googlePay"); + : "googlePay"; #endif } @@ -373,7 +373,7 @@ void AutofillExternalDelegate::ApplyAutofillOptions( features::kAutofillDownstreamUseGooglePayBrandingOniOS) && is_all_server_suggestions) { Suggestion googlepay_icon; - googlepay_icon.icon = base::ASCIIToUTF16("googlePay"); + googlepay_icon.icon = "googlePay"; googlepay_icon.frontend_id = POPUP_ITEM_ID_GOOGLE_PAY_BRANDING; suggestions->insert(suggestions->begin(), googlepay_icon); } @@ -381,10 +381,10 @@ void AutofillExternalDelegate::ApplyAutofillOptions( #if defined(OS_ANDROID) if (IsKeyboardAccessoryEnabled()) { - suggestions->back().icon = base::ASCIIToUTF16("settings"); + suggestions->back().icon = "settings"; if (IsHintEnabledInKeyboardAccessory() && !query_field_.is_autofilled) { Suggestion create_icon; - create_icon.icon = base::ASCIIToUTF16("create"); + create_icon.icon = "create"; create_icon.frontend_id = POPUP_ITEM_ID_CREATE_HINT; suggestions->push_back(create_icon); } @@ -419,8 +419,12 @@ void AutofillExternalDelegate::InsertDataListValues( suggestions->insert(suggestions->begin(), data_list_values_.size(), Suggestion()); for (size_t i = 0; i < data_list_values_.size(); i++) { + // A suggestion's label has one line of disambiguating information to show + // to the user. However, when the two-line suggestion display experiment is + // enabled on desktop, label is replaced by additional label. (*suggestions)[i].value = data_list_values_[i]; (*suggestions)[i].label = data_list_labels_[i]; + (*suggestions)[i].additional_label = data_list_labels_[i]; (*suggestions)[i].frontend_id = POPUP_ITEM_ID_DATALIST_ENTRY; } } 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 32c3dd956b0..3e7d77e2a14 100644 --- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc @@ -408,15 +408,16 @@ TEST_F(AutofillExternalDelegateUnitTest, UpdateDataListWhileShowingPopup) { TEST_F(AutofillExternalDelegateUnitTest, DuplicateAutofillDatalistValues) { IssueOnQuery(kQueryId); - std::vector<base::string16> data_list_items; - data_list_items.push_back(base::ASCIIToUTF16("Rick")); - data_list_items.push_back(base::ASCIIToUTF16("Deckard")); + std::vector<base::string16> data_list_values{base::ASCIIToUTF16("Rick"), + base::ASCIIToUTF16("Beyonce")}; + std::vector<base::string16> data_list_labels{base::ASCIIToUTF16("Deckard"), + base::ASCIIToUTF16("Knowles")}; EXPECT_CALL(autofill_client_, UpdateAutofillPopupDataListValues( - data_list_items, data_list_items)); + data_list_values, data_list_labels)); - external_delegate_->SetCurrentDataListValues(data_list_items, - data_list_items); + external_delegate_->SetCurrentDataListValues(data_list_values, + data_list_labels); // The enums must be cast to ints to prevent compile errors on linux_rel. auto element_ids = testing::ElementsAre( @@ -434,6 +435,8 @@ TEST_F(AutofillExternalDelegateUnitTest, DuplicateAutofillDatalistValues) { std::vector<Suggestion> autofill_item; autofill_item.push_back(Suggestion()); autofill_item[0].value = ASCIIToUTF16("Rick"); + autofill_item[0].label = ASCIIToUTF16("Deckard"); + autofill_item[0].additional_label = ASCIIToUTF16("Deckard"); autofill_item[0].frontend_id = kAutofillProfileId; external_delegate_->OnSuggestionsReturned( kQueryId, autofill_item, /*autoselect_first_suggestion=*/false); @@ -444,15 +447,16 @@ TEST_F(AutofillExternalDelegateUnitTest, DuplicateAutofillDatalistValues) { TEST_F(AutofillExternalDelegateUnitTest, DuplicateAutocompleteDatalistValues) { IssueOnQuery(kQueryId); - std::vector<base::string16> data_list_items; - data_list_items.push_back(base::ASCIIToUTF16("Rick")); - data_list_items.push_back(base::ASCIIToUTF16("Deckard")); + std::vector<base::string16> data_list_values{base::ASCIIToUTF16("Rick"), + base::ASCIIToUTF16("Beyonce")}; + std::vector<base::string16> data_list_labels{base::ASCIIToUTF16("Deckard"), + base::ASCIIToUTF16("Knowles")}; EXPECT_CALL(autofill_client_, UpdateAutofillPopupDataListValues( - data_list_items, data_list_items)); + data_list_values, data_list_labels)); - external_delegate_->SetCurrentDataListValues(data_list_items, - data_list_items); + external_delegate_->SetCurrentDataListValues(data_list_values, + data_list_labels); // The enums must be cast to ints to prevent compile errors on linux_rel. auto element_ids = testing::ElementsAre( @@ -753,8 +757,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateFillFieldWithValue) { TEST_F(AutofillExternalDelegateUnitTest, ShouldShowGooglePayIcon) { IssueOnQuery(kQueryId); - auto element_icons = testing::ElementsAre( - base::string16(), base::ASCIIToUTF16("googlePay")); + auto element_icons = testing::ElementsAre(std::string(), "googlePay"); EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, SuggestionVectorIconsAre(element_icons), false, _)); @@ -777,8 +780,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ShouldShowGooglePayIconOniOS) { IssueOnQuery(kQueryId); auto element_icons = - testing::ElementsAre(base::ASCIIToUTF16("googlePay"), base::string16(), - base::ASCIIToUTF16("googlePay")); + testing::ElementsAre("googlePay", std::string(), "googlePay"); EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, SuggestionVectorIconsAre(element_icons), false, _)); @@ -801,8 +803,8 @@ TEST_F(AutofillExternalDelegateUnitTest, IssueOnQuery(kQueryId); auto element_icons = testing::ElementsAre( - base::string16(), - base::string16() /* Autofill setting item does not have icon. */); + std::string(), + std::string() /* Autofill setting item does not have icon. */); EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, SuggestionVectorIconsAre(element_icons), false, _)); @@ -822,8 +824,8 @@ TEST_F(AutofillExternalDelegateUnitTest, IssueOnQuery(kQueryId); auto element_icons = testing::ElementsAre( - base::string16(), - base::string16() /* Autofill setting item does not have icon. */); + std::string(), + std::string() /* Autofill setting item does not have icon. */); EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, SuggestionVectorIconsAre(element_icons), false, _)); diff --git a/chromium/components/autofill/core/browser/autofill_field.cc b/chromium/components/autofill/core/browser/autofill_field.cc index e0eb40ca514..e60544c60ab 100644 --- a/chromium/components/autofill/core/browser/autofill_field.cc +++ b/chromium/components/autofill/core/browser/autofill_field.cc @@ -6,8 +6,6 @@ #include <stdint.h> -#include <utility> - #include "base/feature_list.h" #include "base/strings/string_number_conversions.h" #include "components/autofill/core/browser/field_types.h" @@ -73,18 +71,17 @@ void AutofillField::set_server_type(ServerFieldType type) { } void AutofillField::add_possible_types_validities( - const std::map<ServerFieldType, AutofillProfile::ValidityState>& - possible_types_validities) { + const ServerFieldTypeValidityStateMap& possible_types_validities) { for (const auto& possible_type_validity : possible_types_validities) { possible_types_validities_[possible_type_validity.first].push_back( possible_type_validity.second); } } -std::vector<AutofillProfile::ValidityState> +std::vector<AutofillDataModel::ValidityState> AutofillField::get_validities_for_possible_type(ServerFieldType type) { if (possible_types_validities_.find(type) == possible_types_validities_.end()) - return {AutofillProfile::UNVALIDATED}; + return {AutofillDataModel::UNVALIDATED}; return possible_types_validities_[type]; } @@ -172,7 +169,7 @@ FieldSignature AutofillField::GetFieldSignature() const { } std::string AutofillField::FieldSignatureAsStr() const { - return base::UintToString(GetFieldSignature()); + return base::NumberToString(GetFieldSignature()); } bool AutofillField::IsFieldFillable() const { @@ -187,7 +184,7 @@ void AutofillField::NormalizePossibleTypesValidities() { for (const auto& possible_type : possible_types_) { if (possible_types_validities_[possible_type].empty()) { possible_types_validities_[possible_type].push_back( - AutofillProfile::UNVALIDATED); + AutofillDataModel::UNVALIDATED); } } } diff --git a/chromium/components/autofill/core/browser/autofill_field.h b/chromium/components/autofill/core/browser/autofill_field.h index 8b565fb0b9d..b7f9069b16f 100644 --- a/chromium/components/autofill/core/browser/autofill_field.h +++ b/chromium/components/autofill/core/browser/autofill_field.h @@ -7,7 +7,10 @@ #include <stddef.h> +#include <map> #include <string> +#include <utility> +#include <vector> #include "base/macros.h" #include "base/optional.h" @@ -22,9 +25,12 @@ namespace autofill { -typedef std::map<ServerFieldType, std::vector<AutofillProfile::ValidityState>> +typedef std::map<ServerFieldType, std::vector<AutofillDataModel::ValidityState>> ServerFieldTypeValidityStatesMap; +typedef std::map<ServerFieldType, AutofillDataModel::ValidityState> + ServerFieldTypeValidityStateMap; + class AutofillField : public FormFieldData { public: enum PhonePart { @@ -60,8 +66,7 @@ class AutofillField : public FormFieldData { void set_heuristic_type(ServerFieldType type); void set_server_type(ServerFieldType type); void add_possible_types_validities( - const std::map<ServerFieldType, AutofillProfile::ValidityState>& - possible_types_validities); + const ServerFieldTypeValidityStateMap& possible_types_validities); void set_server_predictions( const std::vector<AutofillQueryResponseContents::Field::FieldPrediction> predictions) { @@ -74,8 +79,8 @@ class AutofillField : public FormFieldData { const ServerFieldTypeValidityStatesMap& possible_types_validities) { possible_types_validities_ = possible_types_validities; } - std::vector<AutofillProfile::ValidityState> get_validities_for_possible_type( - ServerFieldType); + std::vector<AutofillDataModel::ValidityState> + get_validities_for_possible_type(ServerFieldType); void SetHtmlType(HtmlFieldType type, HtmlFieldMode mode); void set_previously_autofilled(bool previously_autofilled) { diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc index 95dcd22455c..dcc247b97d0 100644 --- a/chromium/components/autofill/core/browser/autofill_manager.cc +++ b/chromium/components/autofill/core/browser/autofill_manager.cc @@ -51,6 +51,9 @@ #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_data_importer.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/metrics/address_form_event_logger.h" +#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h" +#include "components/autofill/core/browser/metrics/form_events.h" #include "components/autofill/core/browser/payments/payments_client.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/phone_number.h" @@ -395,10 +398,11 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form, form_for_autocomplete, client_->IsAutocompleteEnabled()); if (IsProfileAutofillEnabled()) { - address_form_event_logger_->OnWillSubmitForm(sync_state_); + address_form_event_logger_->OnWillSubmitForm(sync_state_, *submitted_form); } if (IsCreditCardAutofillEnabled()) { - credit_card_form_event_logger_->OnWillSubmitForm(sync_state_); + credit_card_form_event_logger_->OnWillSubmitForm(sync_state_, + *submitted_form); } submitted_form->set_submission_source(source); @@ -414,19 +418,13 @@ void AutofillManager::OnFormSubmittedImpl(const FormData& form, submitted_form->set_submission_source(source); - CreditCard credit_card = - client_->GetFormDataImporter()->ExtractCreditCardFromForm( - *submitted_form); - AutofillMetrics::CardNumberStatus card_number_status = - GetCardNumberStatus(credit_card); - if (IsProfileAutofillEnabled()) { - address_form_event_logger_->OnFormSubmitted( - /*force_logging=*/false, card_number_status, sync_state_); + address_form_event_logger_->OnFormSubmitted(/*force_logging=*/false, + sync_state_, *submitted_form); } if (IsCreditCardAutofillEnabled()) { credit_card_form_event_logger_->OnFormSubmitted( - enable_ablation_logging_, card_number_status, sync_state_); + enable_ablation_logging_, sync_state_, *submitted_form); } if (!submitted_form->IsAutofillable()) @@ -711,7 +709,7 @@ void AutofillManager::FillOrPreviewCreditCardForm( masked_card_, AutofillClient::UNMASK_FOR_AUTOFILL, weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr()); credit_card_form_event_logger_->OnDidSelectMaskedServerCardSuggestion( - form_structure->form_parsed_timestamp(), sync_state_); + *form_structure, sync_state_); return; } credit_card_form_event_logger_->OnDidFillSuggestion( @@ -1228,12 +1226,11 @@ void AutofillManager::Reset() { form_interactions_ukm_logger_.reset( new AutofillMetrics::FormInteractionsUkmLogger( client_->GetUkmRecorder(), client_->GetUkmSourceId())); - address_form_event_logger_.reset(new AutofillMetrics::FormEventLogger( - /*is_for_credit_card=*/false, driver()->IsInMainFrame(), - form_interactions_ukm_logger_.get())); - credit_card_form_event_logger_.reset(new AutofillMetrics::FormEventLogger( - /*is_for_credit_card=*/true, driver()->IsInMainFrame(), - form_interactions_ukm_logger_.get())); + address_form_event_logger_.reset(new AddressFormEventLogger( + driver()->IsInMainFrame(), form_interactions_ukm_logger_.get())); + credit_card_form_event_logger_.reset(new CreditCardFormEventLogger( + driver()->IsInMainFrame(), form_interactions_ukm_logger_.get(), + personal_data_, client_)); #if defined(OS_ANDROID) || defined(OS_IOS) autofill_assistant_.Reset(); #endif @@ -1270,16 +1267,15 @@ AutofillManager::AutofillManager( std::make_unique<AutofillMetrics::FormInteractionsUkmLogger>( client->GetUkmRecorder(), client->GetUkmSourceId())), - address_form_event_logger_( - std::make_unique<AutofillMetrics::FormEventLogger>( - /*is_for_credit_card=*/false, - driver->IsInMainFrame(), - form_interactions_ukm_logger_.get())), + address_form_event_logger_(std::make_unique<AddressFormEventLogger>( + driver->IsInMainFrame(), + form_interactions_ukm_logger_.get())), credit_card_form_event_logger_( - std::make_unique<AutofillMetrics::FormEventLogger>( - /*is_for_credit_card=*/true, + std::make_unique<CreditCardFormEventLogger>( driver->IsInMainFrame(), - form_interactions_ukm_logger_.get())), + form_interactions_ukm_logger_.get(), + personal_data_, + client_)), #if defined(OS_ANDROID) || defined(OS_IOS) autofill_assistant_(this), #endif @@ -1661,10 +1657,10 @@ void AutofillManager::OnFormsParsed( } } if (card_form) { - credit_card_form_event_logger_->OnDidParseForm(); + credit_card_form_event_logger_->OnDidParseForm(*form_structure); } if (address_form) { - address_form_event_logger_->OnDidParseForm(); + address_form_event_logger_->OnDidParseForm(*form_structure); } // If a form with the same name was previously filled, and there has not @@ -1824,8 +1820,7 @@ void AutofillManager::DeterminePossibleFieldTypesForUpload( base::TrimWhitespace(field->value, base::TRIM_ALL, &value); for (const AutofillProfile& profile : profiles) { - std::map<ServerFieldType, AutofillProfile::ValidityState> - matching_types_validities; + ServerFieldTypeValidityStateMap matching_types_validities; profile.GetMatchingTypesAndValidities(value, app_locale, &matching_types, &matching_types_validities); field->add_possible_types_validities(matching_types_validities); @@ -1838,9 +1833,8 @@ void AutofillManager::DeterminePossibleFieldTypesForUpload( if (matching_types.empty()) { matching_types.insert(UNKNOWN_TYPE); - std::map<ServerFieldType, AutofillProfile::ValidityState> - matching_types_validities; - matching_types_validities[UNKNOWN_TYPE] = AutofillProfile::UNVALIDATED; + ServerFieldTypeValidityStateMap matching_types_validities; + matching_types_validities[UNKNOWN_TYPE] = AutofillDataModel::UNVALIDATED; field->add_possible_types_validities(matching_types_validities); } @@ -2029,7 +2023,8 @@ bool AutofillManager::ShouldTriggerRefill(const FormStructure& form_structure) { if (itr == filling_contexts_map_.end()) return false; - address_form_event_logger_->OnDidSeeFillableDynamicForm(sync_state_); + address_form_event_logger_->OnDidSeeFillableDynamicForm(sync_state_, + form_structure); FillingContext* filling_context = itr->second.get(); base::TimeTicks now = base::TimeTicks::Now(); @@ -2037,7 +2032,8 @@ bool AutofillManager::ShouldTriggerRefill(const FormStructure& form_structure) { if (filling_context->attempted_refill && delta.InMilliseconds() < kLimitBeforeRefillMs) { - address_form_event_logger_->OnSubsequentRefillAttempt(sync_state_); + address_form_event_logger_->OnSubsequentRefillAttempt(sync_state_, + form_structure); } return !filling_context->attempted_refill && @@ -2051,7 +2047,7 @@ void AutofillManager::TriggerRefill(const FormData& form) { DCHECK(form_structure); - address_form_event_logger_->OnDidRefill(sync_state_); + address_form_event_logger_->OnDidRefill(sync_state_, *form_structure); auto itr = filling_contexts_map_.find(form_structure->GetIdentifierForRefill()); @@ -2117,10 +2113,10 @@ void AutofillManager::GetAvailableSuggestions( if (context->focused_field->Type().group() == CREDIT_CARD) { context->is_filling_credit_card = true; credit_card_form_event_logger_->OnDidInteractWithAutofillableForm( - context->form_structure->form_signature(), sync_state_); + *(context->form_structure), sync_state_); } else { address_form_event_logger_->OnDidInteractWithAutofillableForm( - context->form_structure->form_signature(), sync_state_); + *(context->form_structure), sync_state_); } } @@ -2179,19 +2175,4 @@ void AutofillManager::GetAvailableSuggestions( } } -AutofillMetrics::CardNumberStatus AutofillManager::GetCardNumberStatus( - CreditCard& credit_card) { - base::string16 number = credit_card.number(); - if (number.empty()) - return AutofillMetrics::EMPTY_CARD; - else if (!HasCorrectLength(number)) - return AutofillMetrics::WRONG_SIZE_CARD; - else if (!PassesLuhnCheck(number)) - return AutofillMetrics::FAIL_LUHN_CHECK_CARD; - else if (personal_data_->IsKnownCard(credit_card)) - return AutofillMetrics::KNOWN_CARD; - else - return AutofillMetrics::UNKNOWN_CARD; -} - } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h index 588f1ee0693..e9871cd2c89 100644 --- a/chromium/components/autofill/core/browser/autofill_manager.h +++ b/chromium/components/autofill/core/browser/autofill_manager.h @@ -29,6 +29,8 @@ #include "components/autofill/core/browser/card_unmask_delegate.h" #include "components/autofill/core/browser/field_filler.h" #include "components/autofill/core/browser/form_types.h" +#include "components/autofill/core/browser/metrics/address_form_event_logger.h" +#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h" #include "components/autofill/core/browser/payments/full_card_request.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/popup_types.h" @@ -433,9 +435,10 @@ class AutofillManager : public AutofillHandler, // |FieldTypeGroup|. bool FormHasAddressField(const FormData& 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. + // Returns Suggestions corresponding to both the |autofill_field| type and + // stored profiles whose values match the contents of |field|. |form| stores + // data about the form with which the user is interacting, e.g. the number and + // types of form fields. std::vector<Suggestion> GetProfileSuggestions( const FormStructure& form, const FormFieldData& field, @@ -498,9 +501,6 @@ class AutofillManager : public AutofillHandler, bool should_notify, const base::string16& cvc); - AutofillMetrics::CardNumberStatus GetCardNumberStatus( - CreditCard& credit_card); - // Whether there should be an attemps to refill the form. Returns true if all // the following are satisfied: // There have been no refill on that page yet. @@ -550,9 +550,8 @@ class AutofillManager : public AutofillHandler, form_interactions_ukm_logger_; // Utilities for logging form events. - std::unique_ptr<AutofillMetrics::FormEventLogger> address_form_event_logger_; - std::unique_ptr<AutofillMetrics::FormEventLogger> - credit_card_form_event_logger_; + std::unique_ptr<AddressFormEventLogger> address_form_event_logger_; + std::unique_ptr<CreditCardFormEventLogger> credit_card_form_event_logger_; // Have we logged whether Autofill is enabled for this page load? bool has_logged_autofill_enabled_ = false; diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc index 68c0d62c8da..20c8ed86951 100644 --- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc @@ -8,6 +8,7 @@ #include <algorithm> #include <memory> +#include <tuple> #include <utility> #include <vector> @@ -33,6 +34,7 @@ #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/metrics/form_events.h" #include "components/autofill/core/browser/mock_autocomplete_history_manager.h" #include "components/autofill/core/browser/payments/test_payments_client.h" #include "components/autofill/core/browser/personal_data_manager.h" @@ -295,7 +297,6 @@ class AutofillManagerTest : public testing::Test { /*identity_manager=*/nullptr, /*client_profile_validator=*/nullptr, /*history_service=*/nullptr, - /*cookie_manager_sevice=*/nullptr, /*is_off_the_record=*/false); personal_data_.SetPrefService(autofill_client_.GetPrefs()); @@ -1609,9 +1610,9 @@ TEST_F(AutofillManagerTest, base::HistogramTester histogram_tester; FormSubmitted(form); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, + 1); } // Test that we return normal autofill suggestions when trying to autofill @@ -4422,8 +4423,8 @@ class ProfileMatchingTypesTest : public AutofillManagerTest, public ::testing::WithParamInterface< std::tuple<ProfileMatchingTypesTestCase, - int, // AutofillProfile::ValidityState - bool>> {}; // AutofillProfile::ValidationSource + int, // AutofillDataModel::ValidityState + bool>> {}; // AutofillDataModel::ValidationSource const ProfileMatchingTypesTestCase kProfileMatchingTypesTestCases[] = { // Profile fields matches. @@ -4517,9 +4518,9 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) { // Unpack the test paramters const auto& test_case = std::get<0>(GetParam()); auto validity_state = - static_cast<AutofillProfile::ValidityState>(std::get<1>(GetParam())); + static_cast<AutofillDataModel::ValidityState>(std::get<1>(GetParam())); const auto& validation_source = - static_cast<AutofillProfile::ValidationSource>(std::get<2>(GetParam())); + static_cast<AutofillDataModel::ValidationSource>(std::get<2>(GetParam())); SCOPED_TRACE(base::StringPrintf( "Test: input_value='%s', field_type=%s, validity_state=%d, " @@ -4528,8 +4529,8 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) { AutofillType(test_case.field_type).ToString().c_str(), validity_state, validation_source)); - ASSERT_LE(AutofillProfile::UNVALIDATED, validity_state); - ASSERT_LE(validity_state, AutofillProfile::UNSUPPORTED); + ASSERT_LE(AutofillDataModel::UNVALIDATED, validity_state); + ASSERT_LE(validity_state, AutofillDataModel::UNSUPPORTED); // Set up the test profiles. std::vector<AutofillProfile> profiles; @@ -4556,11 +4557,11 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) { for (auto& profile : profiles) { if (test_case.field_type == UNKNOWN_TYPE) { // An UNKNOWN type is always UNVALIDATED - validity_state = AutofillProfile::UNVALIDATED; + validity_state = AutofillDataModel::UNVALIDATED; } else if (profile.IsAnInvalidPhoneNumber(test_case.field_type)) { // a phone field is a compound field, an invalid part would make it // invalid. - validity_state = AutofillProfile::INVALID; + validity_state = AutofillDataModel::INVALID; } profile.SetValidityState(test_case.field_type, validity_state, validation_source); @@ -4605,19 +4606,19 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) { EXPECT_NE(possible_types_validities.end(), possible_types_validities.find(test_case.field_type)); EXPECT_EQ(possible_types_validities[test_case.field_type][0], - (validation_source == AutofillProfile::SERVER) + (validation_source == AutofillDataModel::SERVER) ? validity_state - : AutofillProfile::UNVALIDATED); + : AutofillDataModel::UNVALIDATED); } } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillManagerTest, ProfileMatchingTypesTest, testing::Combine( testing::ValuesIn(kProfileMatchingTypesTestCases), - testing::Range(static_cast<int>(AutofillProfile::UNVALIDATED), - static_cast<int>(AutofillProfile::UNSUPPORTED) + 1), + testing::Range(static_cast<int>(AutofillDataModel::UNVALIDATED), + static_cast<int>(AutofillDataModel::UNSUPPORTED) + 1), testing::Bool())); // Tests that DeterminePossibleFieldTypesForUpload is called when a form is @@ -4683,8 +4684,8 @@ TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesWithMultipleValidities) { "", "Memphis", "Tennessee", "38116", "US", "(234) 567-8901"); profile.set_guid("00000000-0000-0000-0000-000000000001"); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID, - AutofillProfile::SERVER); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID, + AutofillDataModel::SERVER); profiles.push_back(profile); } { @@ -4693,8 +4694,8 @@ TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesWithMultipleValidities) { "1331 W Georgia", "", "Vancouver", "Tennessee", "V4D 4S4", "CA", "(778) 567-8901"); profile.set_guid("00000000-0000-0000-0000-000000000002"); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, - AutofillProfile::SERVER); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID, + AutofillDataModel::SERVER); profiles.push_back(profile); } @@ -4702,7 +4703,7 @@ TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesWithMultipleValidities) { typedef struct { std::string input_value; ServerFieldType field_type; - std::vector<AutofillProfile::ValidityState> expected_validity_states; + std::vector<AutofillDataModel::ValidityState> expected_validity_states; } TestFieldData; std::vector<TestFieldData> test_cases[3]; @@ -4711,16 +4712,18 @@ TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesWithMultipleValidities) { // possible_field_types would only include the type ADDRESS_HOME_STATE, and // the corresponding validity of that type would include both VALID and // INVALID. - test_cases[0].push_back({"Tennessee", - ADDRESS_HOME_STATE, - {AutofillProfile::VALID, AutofillProfile::INVALID}}); + test_cases[0].push_back( + {"Tennessee", + ADDRESS_HOME_STATE, + {AutofillDataModel::VALID, AutofillDataModel::INVALID}}); // Alice appears only in the second profile as a NAME_FIRST, and it's // UNVALIDATED. test_cases[1].push_back( - {"Alice", NAME_FIRST, {AutofillProfile::UNVALIDATED}}); + {"Alice", NAME_FIRST, {AutofillDataModel::UNVALIDATED}}); // An UNKNOWN type is always UNVALIDATED. - test_cases[2].push_back( - {"What a beautiful day!", UNKNOWN_TYPE, {AutofillProfile::UNVALIDATED}}); + test_cases[2].push_back({"What a beautiful day!", + UNKNOWN_TYPE, + {AutofillDataModel::UNVALIDATED}}); for (const std::vector<TestFieldData>& test_fields : test_cases) { FormData form; @@ -5392,9 +5395,8 @@ TEST_F(AutofillManagerTest, CreditCardDisabledDoesNotSuggest) { // Verify that typing "gmail" will match "theking@gmail.com" and // "buddy@gmail.com" when substring matching is enabled. TEST_F(AutofillManagerTest, DisplaySuggestionsWithMatchingTokens) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); // Set up our form data. FormData form; @@ -5414,9 +5416,8 @@ TEST_F(AutofillManagerTest, DisplaySuggestionsWithMatchingTokens) { // Verify that typing "apple" will match "123 Apple St." when substring matching // is enabled. TEST_F(AutofillManagerTest, DisplaySuggestionsWithMatchingTokens_CaseIgnored) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); // Set up our form data. FormData form; @@ -5435,9 +5436,8 @@ TEST_F(AutofillManagerTest, DisplaySuggestionsWithMatchingTokens_CaseIgnored) { // Verify that typing "mail" will not match any of the "@gmail.com" email // addresses when substring matching is enabled. TEST_F(AutofillManagerTest, NoSuggestionForNonPrefixTokenMatch) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); // Set up our form data. FormData form; @@ -5454,9 +5454,8 @@ TEST_F(AutofillManagerTest, NoSuggestionForNonPrefixTokenMatch) { // Verify that typing "pres" will match "Elvis Presley" when substring matching // is enabled. TEST_F(AutofillManagerTest, DisplayCreditCardSuggestionsWithMatchingTokens) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); // Set up our form data. FormData form; @@ -5485,9 +5484,8 @@ TEST_F(AutofillManagerTest, DisplayCreditCardSuggestionsWithMatchingTokens) { // Verify that typing "lvis" will not match any of the credit card name when // substring matching is enabled. TEST_F(AutofillManagerTest, NoCreditCardSuggestionsForNonPrefixTokenMatch) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); // Set up our form data. FormData form; @@ -5695,9 +5693,8 @@ TEST_F(AutofillManagerTest, ShouldShowCreditCardSigninPromo_AddressField) { // substring matched. TEST_F(AutofillManagerTest, DisplaySuggestionsWithPrefixesPrecedeSubstringMatched) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); // Set up our form data. FormData form; @@ -6233,12 +6230,10 @@ TEST_F(AutofillManagerTest, DidShowSuggestions_LogAutofillAddressShownMetric) { histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address", AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); // No Autocomplete or credit cards logs. const std::string histograms = histogram_tester.GetAllHistogramsRecorded(); @@ -6264,12 +6259,10 @@ TEST_F(AutofillManagerTest, histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard", AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); // No Autocomplete or address logs. const std::string histograms = histogram_tester.GetAllHistogramsRecorded(); @@ -6284,9 +6277,8 @@ TEST_F(AutofillManagerTest, base::HistogramTester histogram_tester; autofill_manager_->DidSuppressPopup(form, form.fields[0]); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_POPUP_SUPPRESSED, 1); // No Autocomplete or credit cards logs. const std::string histograms = histogram_tester.GetAllHistogramsRecorded(); @@ -6303,9 +6295,8 @@ TEST_F(AutofillManagerTest, base::HistogramTester histogram_tester; autofill_manager_->DidSuppressPopup(form, form.fields[0]); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_POPUP_SUPPRESSED, 1); // No Autocomplete or address logs. const std::string histograms = histogram_tester.GetAllHistogramsRecorded(); @@ -6523,6 +6514,6 @@ TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_Ablation) { CheckNoSuggestionsAvailableOnFieldFocus(); } -INSTANTIATE_TEST_CASE_P(All, OnFocusOnFormFieldTest, testing::Bool()); +INSTANTIATE_TEST_SUITE_P(All, OnFocusOnFormFieldTest, testing::Bool()); } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc index caf34836790..bd1bbb316a7 100644 --- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc @@ -304,6 +304,8 @@ TEST_P(AutofillMergeTest, DataDrivenMergeProfiles) { kIsExpectedToPass); } -INSTANTIATE_TEST_CASE_P(, AutofillMergeTest, testing::ValuesIn(GetTestFiles())); +INSTANTIATE_TEST_SUITE_P(, + AutofillMergeTest, + testing::ValuesIn(GetTestFiles())); } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_metadata.h b/chromium/components/autofill/core/browser/autofill_metadata.h index 6a70a06bb49..3fbc2e12a26 100644 --- a/chromium/components/autofill/core/browser/autofill_metadata.h +++ b/chromium/components/autofill/core/browser/autofill_metadata.h @@ -15,8 +15,8 @@ namespace autofill { // abstract the data from the metadata. struct AutofillMetadata { public: - AutofillMetadata(){}; - ~AutofillMetadata(){}; + AutofillMetadata() {} + ~AutofillMetadata() {} bool operator==(const AutofillMetadata&) const; bool operator!=(const AutofillMetadata&) const; diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc index 6e405659280..b88ad9a0269 100644 --- a/chromium/components/autofill/core/browser/autofill_metrics.cc +++ b/chromium/components/autofill/core/browser/autofill_metrics.cc @@ -23,12 +23,16 @@ #include "components/autofill/core/common/autofill_prefs.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/submission_source.h" +#include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" namespace autofill { namespace { +// Exponential bucket spacing for UKM event data. +const double kAutofillEventDataBucketSpacing = 2.0; + // Note: if adding an enum value here, update the corresponding description for // AutofillTypeQualityByFieldType in histograms.xml. enum FieldTypeGroupForMetrics { @@ -264,21 +268,6 @@ const char* GetQualityMetricTypeSuffix( } } -const char* GetSyncStateSuffix(AutofillSyncSigninState sync_state) { - switch (sync_state) { - case AutofillSyncSigninState::kSignedOut: - return ".SignedOut"; - case AutofillSyncSigninState::kSignedIn: - return ".SignedIn"; - case AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled: - return ".SignedInAndWalletSyncTransportEnabled"; - case AutofillSyncSigninState::kSignedInAndSyncFeature: - return ".SignedInAndSyncFeature"; - case AutofillSyncSigninState::kNumSyncStates: - return ".Unknown"; - } -} - // Given a set of |possible_types| for a field, select the best type to use as // the "actual" field type when calculating metrics. If the |predicted_type| is // among the |possible_types] then use that as the best type (i.e., the @@ -568,30 +557,6 @@ void LogPredictionQualityMetrics( is_empty, is_ambiguous); } -AutofillMetrics::FormEvent GetCardNumberStatusFormEvent( - const AutofillMetrics::CardNumberStatus card_number_status) { - switch (card_number_status) { - case AutofillMetrics::EMPTY_CARD: - return AutofillMetrics:: - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD; - case AutofillMetrics::WRONG_SIZE_CARD: - return AutofillMetrics:: - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD; - case AutofillMetrics::FAIL_LUHN_CHECK_CARD: - return AutofillMetrics:: - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD; - case AutofillMetrics::KNOWN_CARD: - return AutofillMetrics:: - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD; - case AutofillMetrics::UNKNOWN_CARD: - return AutofillMetrics:: - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD; - } - NOTREACHED(); - return AutofillMetrics:: - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD; -} - } // namespace const int kMaxBucketsCount = 50; @@ -614,6 +579,11 @@ void AutofillMetrics::LogSubmittedServerCardExpirationStatusMetric( } // static +void AutofillMetrics::LogMaskedCardComparisonNetworksMatch(bool matches) { + UMA_HISTOGRAM_BOOLEAN("Autofill.MaskedCardComparisonNetworksMatch", matches); +} + +// static void AutofillMetrics::LogCreditCardSaveNotOfferedDueToMaxStrikesMetric( SaveTypeMetric metric) { UMA_HISTOGRAM_ENUMERATION( @@ -622,6 +592,14 @@ void AutofillMetrics::LogCreditCardSaveNotOfferedDueToMaxStrikesMetric( } // static +void AutofillMetrics::LogLocalCardMigrationNotOfferedDueToMaxStrikesMetric( + SaveTypeMetric metric) { + UMA_HISTOGRAM_ENUMERATION( + "Autofill.StrikeDatabase.LocalCardMigrationNotOfferedDueToMaxStrikes", + metric); +} + +// static void AutofillMetrics::LogUploadDisallowedForNetworkMetric( const std::string& network) { UploadDisallowedForNetworkMetric metric; @@ -687,19 +665,31 @@ void AutofillMetrics::LogCardUploadDecisionMetrics( void AutofillMetrics::LogCreditCardInfoBarMetric( InfoBarMetric metric, bool is_uploading, - bool is_requesting_cardholder_name, + AutofillClient::SaveCreditCardOptions options, int previous_save_credit_card_prompt_user_decision) { DCHECK_LT(metric, NUM_INFO_BAR_METRICS); std::string destination = is_uploading ? ".Server" : ".Local"; base::UmaHistogramEnumeration("Autofill.CreditCardInfoBar" + destination, metric, NUM_INFO_BAR_METRICS); - if (is_requesting_cardholder_name) { + if (options.should_request_name_from_user) { base::UmaHistogramEnumeration("Autofill.CreditCardInfoBar" + destination + ".RequestingCardholderName", metric, NUM_INFO_BAR_METRICS); } + if (options.should_request_expiration_date_from_user) { + base::UmaHistogramEnumeration("Autofill.CreditCardInfoBar" + destination + + ".RequestingExpirationDate", + metric, NUM_INFO_BAR_METRICS); + } + + if (options.has_non_focusable_field) { + base::UmaHistogramEnumeration( + "Autofill.CreditCardInfoBar" + destination + ".FromNonFocusableForm", + metric, NUM_INFO_BAR_METRICS); + } + base::UmaHistogramEnumeration( "Autofill.CreditCardInfoBar" + destination + PreviousSaveCreditCardPromptUserDecisionToString( @@ -727,8 +717,7 @@ void AutofillMetrics::LogSaveCardPromptMetric( SaveCardPromptMetric metric, bool is_uploading, bool is_reshow, - bool is_requesting_cardholder_name, - bool is_requesting_expiration_date, + AutofillClient::SaveCreditCardOptions options, int previous_save_credit_card_prompt_user_decision, security_state::SecurityLevel security_level, AutofillSyncSigninState sync_state) { @@ -740,18 +729,23 @@ void AutofillMetrics::LogSaveCardPromptMetric( base::UmaHistogramEnumeration(metric_with_destination_and_show, metric, NUM_SAVE_CARD_PROMPT_METRICS); base::UmaHistogramEnumeration( - metric_with_destination_and_show + GetSyncStateSuffix(sync_state), metric, - NUM_SAVE_CARD_PROMPT_METRICS); - if (is_requesting_cardholder_name) { + metric_with_destination_and_show + GetMetricsSyncStateSuffix(sync_state), + metric, NUM_SAVE_CARD_PROMPT_METRICS); + if (options.should_request_name_from_user) { base::UmaHistogramEnumeration( metric_with_destination_and_show + ".RequestingCardholderName", metric, NUM_SAVE_CARD_PROMPT_METRICS); } - if (is_requesting_expiration_date) { + if (options.should_request_expiration_date_from_user) { base::UmaHistogramEnumeration( metric_with_destination_and_show + ".RequestingExpirationDate", metric, NUM_SAVE_CARD_PROMPT_METRICS); } + if (options.has_non_focusable_field) { + base::UmaHistogramEnumeration( + metric_with_destination_and_show + ".FromNonFocusableForm", metric, + NUM_SAVE_CARD_PROMPT_METRICS); + } base::UmaHistogramEnumeration( metric_with_destination_and_show + PreviousSaveCreditCardPromptUserDecisionToString( @@ -944,7 +938,19 @@ void AutofillMetrics::LogUnmaskPromptEvent(UnmaskPromptEvent event) { void AutofillMetrics::LogCardholderNameFixFlowPromptEvent( CardholderNameFixFlowPromptEvent event) { UMA_HISTOGRAM_ENUMERATION("Autofill.CardholderNameFixFlowPrompt.Events", - event, NUM_FIXFLOW_PROMPT_EVENTS); + event, NUM_CARDHOLDER_NAME_FIXFLOW_PROMPT_EVENTS); +} + +// static +void AutofillMetrics::LogExpirationDateFixFlowPromptEvent( + ExpirationDateFixFlowPromptEvent event) { + UMA_HISTOGRAM_ENUMERATION("Autofill.ExpirationDateFixFlowPrompt.Events", + event); +} + +// static +void AutofillMetrics::LogExpirationDateFixFlowPromptShown() { + UMA_HISTOGRAM_BOOLEAN("Autofill.ExpirationDateFixFlowPromptShown", true); } // static @@ -1246,7 +1252,8 @@ void AutofillMetrics::LogIsAutofillEnabledAtPageLoad( AutofillSyncSigninState sync_state) { std::string name("Autofill.IsEnabled.PageLoad"); UMA_HISTOGRAM_BOOLEAN(name, enabled); - base::UmaHistogramBoolean(name + GetSyncStateSuffix(sync_state), enabled); + base::UmaHistogramBoolean(name + GetMetricsSyncStateSuffix(sync_state), + enabled); } // static @@ -1670,338 +1677,16 @@ void AutofillMetrics::LogDeveloperEngagementUkm( .Record(ukm_recorder); } -AutofillMetrics::FormEventLogger::FormEventLogger( - bool is_for_credit_card, - bool is_in_main_frame, - AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) - : is_for_credit_card_(is_for_credit_card), - is_in_main_frame_(is_in_main_frame), - server_record_type_count_(0), - local_record_type_count_(0), - is_context_secure_(false), - has_logged_interacted_(false), - has_logged_popup_suppressed_(false), - has_logged_suggestions_shown_(false), - has_logged_masked_server_card_suggestion_selected_(false), - has_logged_suggestion_filled_(false), - has_logged_will_submit_(false), - has_logged_submitted_(false), - has_logged_bank_name_available_(false), - logged_suggestion_filled_was_server_data_(false), - logged_suggestion_filled_was_masked_server_card_(false), - form_interactions_ukm_logger_(form_interactions_ukm_logger) {} - -void AutofillMetrics::FormEventLogger::OnDidParseForm() { - Log(AutofillMetrics::FORM_EVENT_DID_PARSE_FORM); - if (is_for_credit_card_) { - base::RecordAction( - base::UserMetricsAction("Autofill_ParsedCreditCardForm")); - } else { - base::RecordAction(base::UserMetricsAction("Autofill_ParsedProfileForm")); - } -} - -void AutofillMetrics::FormEventLogger::OnDidInteractWithAutofillableForm( - FormSignature form_signature, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - if (!has_logged_interacted_) { - has_logged_interacted_ = true; - form_interactions_ukm_logger_->LogInteractedWithForm( - is_for_credit_card_, local_record_type_count_, - server_record_type_count_, form_signature); - Log(AutofillMetrics::FORM_EVENT_INTERACTED_ONCE); - } -} - -void AutofillMetrics::FormEventLogger::OnDidPollSuggestions( - const FormFieldData& field, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - // Record only one poll user action for consecutive polls of the same field. - // This is to avoid recording too many poll actions (for example when a user - // types in a field, triggering multiple queries) to make the analysis more - // simple. - if (!field.SameFieldAs(last_polled_field_)) { - if (is_for_credit_card_) { - base::RecordAction( - base::UserMetricsAction("Autofill_PolledCreditCardSuggestions")); - } else { - base::RecordAction( - base::UserMetricsAction("Autofill_PolledProfileSuggestions")); - } - - last_polled_field_ = field; - } -} - -void AutofillMetrics::FormEventLogger::OnPopupSuppressed( - const FormStructure& form, - const AutofillField& field) { - Log(AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED); - if (!has_logged_popup_suppressed_) { - has_logged_popup_suppressed_ = true; - Log(AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE); - } -} - -void AutofillMetrics::FormEventLogger::OnDidShowSuggestions( - const FormStructure& form, - const AutofillField& field, - const base::TimeTicks& form_parsed_timestamp, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - form_interactions_ukm_logger_->LogSuggestionsShown( - form, field, form_parsed_timestamp); - - Log(AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN); - if (!has_logged_suggestions_shown_) { - has_logged_suggestions_shown_ = true; - Log(AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE); - if (has_logged_bank_name_available_) { - Log(AutofillMetrics:: - FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE); - } - } - - if (is_for_credit_card_) { - base::RecordAction( - base::UserMetricsAction("Autofill_ShowedCreditCardSuggestions")); - } else { - base::RecordAction( - base::UserMetricsAction("Autofill_ShowedProfileSuggestions")); - } -} - -void AutofillMetrics::FormEventLogger::OnDidSelectMaskedServerCardSuggestion( - const base::TimeTicks& form_parsed_timestamp, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - DCHECK(is_for_credit_card_); - form_interactions_ukm_logger_->LogSelectedMaskedServerCard( - form_parsed_timestamp); - - Log(AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED); - if (!has_logged_masked_server_card_suggestion_selected_) { - has_logged_masked_server_card_suggestion_selected_ = true; - Log(AutofillMetrics:: - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE); - } -} - -void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( - const CreditCard& credit_card, - const FormStructure& form, - const AutofillField& field, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - DCHECK(is_for_credit_card_); - form_interactions_ukm_logger_->LogDidFillSuggestion( - static_cast<int>(credit_card.record_type()), - /*is_for_credit_card=*/true, form, field); - - if (credit_card.record_type() == CreditCard::MASKED_SERVER_CARD) - Log(AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED); - else if (credit_card.record_type() == CreditCard::FULL_SERVER_CARD) - Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED); - else - Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED); - - if (!has_logged_suggestion_filled_) { - has_logged_suggestion_filled_ = true; - logged_suggestion_filled_was_server_data_ = - credit_card.record_type() == CreditCard::MASKED_SERVER_CARD || - credit_card.record_type() == CreditCard::FULL_SERVER_CARD; - logged_suggestion_filled_was_masked_server_card_ = - credit_card.record_type() == CreditCard::MASKED_SERVER_CARD; - if (credit_card.record_type() == CreditCard::MASKED_SERVER_CARD) { - Log(AutofillMetrics:: - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE); - if (has_logged_bank_name_available_) { - Log(AutofillMetrics:: - FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE); - } - } else if (credit_card.record_type() == CreditCard::FULL_SERVER_CARD) { - Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE); - if (has_logged_bank_name_available_) { - Log(AutofillMetrics:: - FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE); - } - } else { - Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE); - } - } - - base::RecordAction( - base::UserMetricsAction("Autofill_FilledCreditCardSuggestion")); -} - -void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( - const AutofillProfile& profile, - const FormStructure& form, - const AutofillField& field, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - DCHECK(!is_for_credit_card_); - form_interactions_ukm_logger_->LogDidFillSuggestion( - static_cast<int>(profile.record_type()), - /*is_for_for_credit_card=*/false, form, field); - - if (profile.record_type() == AutofillProfile::SERVER_PROFILE) - Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED); - else - Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED); - - if (!has_logged_suggestion_filled_) { - has_logged_suggestion_filled_ = true; - logged_suggestion_filled_was_server_data_ = - profile.record_type() == AutofillProfile::SERVER_PROFILE; - Log(profile.record_type() == AutofillProfile::SERVER_PROFILE - ? AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE - : AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE); - } - - base::RecordAction( - base::UserMetricsAction("Autofill_FilledProfileSuggestion")); -} - -void AutofillMetrics::FormEventLogger::OnWillSubmitForm( - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - // Not logging this kind of form if we haven't logged a user interaction. - if (!has_logged_interacted_) - return; - - // Not logging twice. - if (has_logged_will_submit_) - return; - has_logged_will_submit_ = true; - - if (!has_logged_suggestion_filled_) { - Log(AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE); - } else if (logged_suggestion_filled_was_masked_server_card_) { - Log(AutofillMetrics:: - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE); - } else if (logged_suggestion_filled_was_server_data_) { - Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE); - } else { - Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE); - } - - if (has_logged_suggestions_shown_) { - Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE); - } - - base::RecordAction(base::UserMetricsAction("Autofill_OnWillSubmitForm")); -} - -void AutofillMetrics::FormEventLogger::OnFormSubmitted( - bool force_logging, - CardNumberStatus card_number_status, - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - // Not logging this kind of form if we haven't logged a user interaction. - if (!has_logged_interacted_) - return; - - // Not logging twice. - if (has_logged_submitted_) - return; - has_logged_submitted_ = true; - - if (!has_logged_suggestion_filled_) { - Log(AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE); - } else if (logged_suggestion_filled_was_masked_server_card_) { - Log(AutofillMetrics:: - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE); - } else if (logged_suggestion_filled_was_server_data_) { - Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE); - } else { - Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE); - } - - if (has_logged_suggestions_shown_ || force_logging) { - Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE); - if (is_for_credit_card_ && !has_logged_suggestion_filled_) { - Log(GetCardNumberStatusFormEvent(card_number_status)); - } - } -} - -void AutofillMetrics::FormEventLogger::SetBankNameAvailable() { - has_logged_bank_name_available_ = true; -} - -void AutofillMetrics::FormEventLogger::OnDidSeeFillableDynamicForm( - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - Log(AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM); -} - -void AutofillMetrics::FormEventLogger::OnDidRefill( - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - Log(AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL); -} - -void AutofillMetrics::FormEventLogger::OnSubsequentRefillAttempt( - AutofillSyncSigninState sync_state) { - sync_state_ = sync_state; - Log(AutofillMetrics::FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL); -} - -void AutofillMetrics::FormEventLogger::Log(FormEvent event) const { - DCHECK_LT(event, NUM_FORM_EVENTS); - std::string name("Autofill.FormEvents."); - if (is_for_credit_card_) - name += "CreditCard"; - else - name += "Address"; - base::UmaHistogramEnumeration(name, event, NUM_FORM_EVENTS); - - // Log again in a different histogram so that iframes can be analyzed on their - // own. - base::UmaHistogramEnumeration( - name + (is_in_main_frame_ ? ".IsInMainFrame" : ".IsInIFrame"), event, - NUM_FORM_EVENTS); - - // Log again in a different histogram for credit card forms on nonsecure - // pages, so that form interactions on nonsecure pages can be analyzed on - // their own. - if (is_for_credit_card_ && !is_context_secure_) { - base::UmaHistogramEnumeration(name + ".OnNonsecurePage", event, - NUM_FORM_EVENTS); - } - - // Logging again in a different histogram for segmentation purposes. - if (server_record_type_count_ == 0 && local_record_type_count_ == 0) - name += ".WithNoData"; - else if (server_record_type_count_ > 0 && local_record_type_count_ == 0) - name += ".WithOnlyServerData"; - else if (server_record_type_count_ == 0 && local_record_type_count_ > 0) - name += ".WithOnlyLocalData"; - else - name += ".WithBothServerAndLocalData"; - base::UmaHistogramEnumeration(name, event, NUM_FORM_EVENTS); - base::UmaHistogramEnumeration(name + GetSyncStateSuffix(sync_state_), event, - NUM_FORM_EVENTS); -} - -void AutofillMetrics::FormEventLogger::Log( - BankNameDisplayedFormEvent event) const { - DCHECK_LT(event, BANK_NAME_NUM_FORM_EVENTS); - std::string name("Autofill.FormEvents.CreditCard.BankNameDisplayed"); - base::UmaHistogramEnumeration(name, event, BANK_NAME_NUM_FORM_EVENTS); -} - AutofillMetrics::FormInteractionsUkmLogger::FormInteractionsUkmLogger( ukm::UkmRecorder* ukm_recorder, const ukm::SourceId source_id) - : ukm_recorder_(ukm_recorder), source_id_(source_id) {} + : ukm_recorder_(ukm_recorder), source_id_(source_id) { + UMA_HISTOGRAM_BOOLEAN("Autofill.CanLogUKM", CanLog()); +} void AutofillMetrics::FormInteractionsUkmLogger::OnFormsParsed( const ukm::SourceId source_id) { - if (ukm_recorder_ == nullptr) + if (!CanLog()) return; source_id_ = source_id; @@ -2041,17 +1726,6 @@ void AutofillMetrics::FormInteractionsUkmLogger::LogSuggestionsShown( .Record(ukm_recorder_); } -void AutofillMetrics::FormInteractionsUkmLogger::LogSelectedMaskedServerCard( - const base::TimeTicks& form_parsed_timestamp) { - if (!CanLog()) - return; - - ukm::builders::Autofill_SelectedMaskedServerCard(source_id_) - .SetMillisecondsSinceFormParsed( - MillisecondsSinceFormParsed(form_parsed_timestamp)) - .Record(ukm_recorder_); -} - void AutofillMetrics::FormInteractionsUkmLogger::LogDidFillSuggestion( int record_type, bool is_for_credit_card, @@ -2197,6 +1871,23 @@ void AutofillMetrics::LogWalletSyncTransportCardsOptIn(bool is_opted_in) { "Autofill.HadUserOptedIn_To_WalletSyncTransportServerCards", is_opted_in); } +// static +const char* AutofillMetrics::GetMetricsSyncStateSuffix( + AutofillSyncSigninState sync_state) { + switch (sync_state) { + case AutofillSyncSigninState::kSignedOut: + return ".SignedOut"; + case AutofillSyncSigninState::kSignedIn: + return ".SignedIn"; + case AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled: + return ".SignedInAndWalletSyncTransportEnabled"; + case AutofillSyncSigninState::kSignedInAndSyncFeature: + return ".SignedInAndSyncFeature"; + case AutofillSyncSigninState::kNumSyncStates: + return ".Unknown"; + } +} + void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted( bool is_for_credit_card, bool has_upi_vpa_field, @@ -2224,6 +1915,24 @@ void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted( builder.Record(ukm_recorder_); } +void AutofillMetrics::FormInteractionsUkmLogger::LogFormEvent( + FormEvent form_event, + const std::set<FormType>& form_types, + const base::TimeTicks& form_parsed_timestamp) { + if (!CanLog()) + return; + + if (form_parsed_timestamp.is_null()) + return; + + ukm::builders::Autofill_FormEvent builder(source_id_); + builder.SetAutofillFormEvent(static_cast<int>(form_event)) + .SetFormTypes(FormTypesToBitVector(form_types)) + .SetMillisecondsSinceFormParsed( + MillisecondsSinceFormParsed(form_parsed_timestamp)) + .Record(ukm_recorder_); +} + bool AutofillMetrics::FormInteractionsUkmLogger::CanLog() const { return ukm_recorder_ != nullptr; } @@ -2234,7 +1943,10 @@ int64_t AutofillMetrics::FormInteractionsUkmLogger::MillisecondsSinceFormParsed( // Use the pinned timestamp as the current time if it's set. base::TimeTicks now = pinned_timestamp_.is_null() ? base::TimeTicks::Now() : pinned_timestamp_; - return (now - form_parsed_timestamp).InMilliseconds(); + + return ukm::GetExponentialBucketMin( + (now - form_parsed_timestamp).InMilliseconds(), + kAutofillEventDataBucketSpacing); } AutofillMetrics::UkmTimestampPin::UkmTimestampPin( diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h index 2e2f6150140..39c231415ae 100644 --- a/chromium/components/autofill/core/browser/autofill_metrics.h +++ b/chromium/components/autofill/core/browser/autofill_metrics.h @@ -18,6 +18,7 @@ #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/browser/metrics/form_events.h" #include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/signatures_util.h" @@ -110,6 +111,11 @@ class AutofillMetrics { // A pair of dropdowns for the user to select expiration date was surfaced // in the offer-to-save dialog. USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE = 1 << 14, + // All the required conditions were satisfied even though the form is + // unfocused after the user entered information into it. + UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD = 1 << 15, + // The card does not satisfy any of the ranges of supported BIN ranges. + UPLOAD_NOT_OFFERED_UNSUPPORTED_BIN_RANGE = 1 << 16, // Update |kNumCardUploadDecisionMetrics| when adding new enum here. }; @@ -169,7 +175,7 @@ class AutofillMetrics { // Metric to measure if a submitted card's expiration date matches the same // server card's expiration date (unmasked or not). Cards are considered to // be the same if they have the same card number (if unmasked) or if they have - // the same network and last four digits (if masked). + // the same last four digits (if masked). enum SubmittedServerCardExpirationStatusMetric { // The submitted card and the unmasked server card had the same expiration // date. @@ -592,111 +598,6 @@ class AutofillMetrics { NUM_USER_HAPPINESS_METRICS, }; - // Form Events for autofill. - // These events are triggered separetly for address and credit card forms. - enum FormEvent { - // User interacted with a field of this kind of form. Logged only once per - // page load. - FORM_EVENT_INTERACTED_ONCE = 0, - // A dropdown with suggestions was shown. - FORM_EVENT_SUGGESTIONS_SHOWN, - // Same as above, but recoreded only once per page load. - FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, - // A local suggestion was used to fill the form. - FORM_EVENT_LOCAL_SUGGESTION_FILLED, - // A server suggestion was used to fill the form. - // When dealing with credit cards, this means a full server card was used - // to fill. - FORM_EVENT_SERVER_SUGGESTION_FILLED, - // A masked server card suggestion was used to fill the form. - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, - // A suggestion was used to fill the form. The origin type (local or server - // or masked server card) of the first selected within a page load will - // determine which of the following two will be fired. - FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, - FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - // A form was submitted. Depending on the user filling a local, server, - // masked server card or no suggestion one of the following will be - // triggered. Only one of the following four will be triggered per page - // load. - FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, - FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, - FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, - // A masked server card suggestion was selected to fill the form. - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, - // Same as above but only triggered once per page load. - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, - // An autofillable form is about to be submitted. If the submission is not - // interrupted by JavaScript, the "form submitted" events above will also be - // logged. Depending on the user filling a local, server, masked server card - // or no suggestion one of the following will be triggered, at most once per - // page load. - FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, - FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, - FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, - FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, - // A dropdown with suggestions was shown and a form was submitted after - // that. - FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, - // A dropdown with suggestions was shown and a form is about to be - // submitted. If the submission is not interrupted by JavaScript, the "form - // submitted" event above will also be logged. - FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, - // A dropdown with credit card suggestions was shown, but they were not used - // to fill the form. Depending on the user submitting a card known by the - // browser, submitting a card that the browser does not know about, - // submitting with an empty card number, submitting with a card number of - // wrong size or submitting with a card number that does not pass luhn - // check, one of the following will be triggered. At most one of the - // following five metrics will be triggered per submit. - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, - FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, - - // The form was changed dynamically. This value has been deprecated. - FORM_EVENT_DID_SEE_DYNAMIC_FORM, - // The form was changed dynamically and was fillable. - FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, - // There was a dynamic change of the form and it got re-filled - // automatically. - FORM_EVENT_DID_DYNAMIC_REFILL, - // The form dynamically changed another time after the refill. - FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, - // The popup was suppressed because the native view couldn't be created. - FORM_EVENT_POPUP_SUPPRESSED, - // Same as above, but recoreded only once per page load. - FORM_EVENT_POPUP_SUPPRESSED_ONCE, - - // The form was parsed. - FORM_EVENT_DID_PARSE_FORM, - - NUM_FORM_EVENTS, - }; - - // Indicates submitted card information. - enum CardNumberStatus { - EMPTY_CARD, - WRONG_SIZE_CARD, - FAIL_LUHN_CHECK_CARD, - KNOWN_CARD, - UNKNOWN_CARD - }; - - // Form Events for autofill with bank name available for display. - enum BankNameDisplayedFormEvent { - // A dropdown with suggestions was shown and at least one suggestion has a - // bank name. Logged at most once per page load. - FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE = 0, - // A server suggestion was used to fill the form and at least one suggestion - // has a bank name. Logged at most once per page load. - FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE, - BANK_NAME_NUM_FORM_EVENTS, - }; - // Cardholder name fix flow prompt metrics. enum CardholderNameFixFlowPromptEvent { // The prompt was shown. @@ -707,7 +608,18 @@ class AutofillMetrics { CARDHOLDER_NAME_FIX_FLOW_PROMPT_DISMISSED, // The prompt was closed without user interaction. CARDHOLDER_NAME_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION, - NUM_FIXFLOW_PROMPT_EVENTS, + NUM_CARDHOLDER_NAME_FIXFLOW_PROMPT_EVENTS, + }; + + // Expiration date fix flow prompt metrics. + enum class ExpirationDateFixFlowPromptEvent { + // The prompt was accepted by user. + EXPIRATION_DATE_FIX_FLOW_PROMPT_ACCEPTED = 0, + // The prompt was dismissed by user. + EXPIRATION_DATE_FIX_FLOW_PROMPT_DISMISSED, + // The prompt was closed without user interaction. + EXPIRATION_DATE_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION, + kMaxValue = EXPIRATION_DATE_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION, }; // Events related to the Unmask Credit Card Prompt. @@ -872,8 +784,6 @@ class AutofillMetrics { void LogSuggestionsShown(const FormStructure& form, const AutofillField& field, const base::TimeTicks& form_parsed_timestamp); - void LogSelectedMaskedServerCard( - const base::TimeTicks& form_parsed_timestamp); void LogDidFillSuggestion(int record_type, bool is_for_credit_card, const FormStructure& form, @@ -896,6 +806,9 @@ class AutofillMetrics { AutofillFormSubmittedState state, const base::TimeTicks& form_parsed_timestamp, FormSignature form_signature); + void LogFormEvent(FormEvent form_event, + const std::set<FormType>& form_types, + const base::TimeTicks& form_parsed_timestamp); // Log whether the autofill decided to skip or to fill each // hidden/representational field. @@ -941,11 +854,20 @@ class AutofillMetrics { static void LogSubmittedServerCardExpirationStatusMetric( SubmittedServerCardExpirationStatusMetric metric); + // When a masked card is compared with another card, logs whether the cards' + // networks match. + static void LogMaskedCardComparisonNetworksMatch(bool matches); + // When credit card save is not offered (either at all on mobile or by simply // not showing the bubble on desktop), logs the occurrence. static void LogCreditCardSaveNotOfferedDueToMaxStrikesMetric( SaveTypeMetric metric); + // When local card migration is not offered due to max strike limit reached, + // logs the occurrence. + static void LogLocalCardMigrationNotOfferedDueToMaxStrikesMetric( + SaveTypeMetric metric); + // When credit card upload is disallowed for a particular network, logs which // network was blocked. static void LogUploadDisallowedForNetworkMetric(const std::string& network); @@ -977,7 +899,7 @@ class AutofillMetrics { static void LogCreditCardInfoBarMetric( InfoBarMetric metric, bool is_uploading, - bool is_requesting_cardholder_name, + AutofillClient::SaveCreditCardOptions options, int previous_save_credit_card_prompt_user_decision); static void LogCreditCardFillingInfoBarMetric(InfoBarMetric metric); static void LogSaveCardRequestExpirationDateReasonMetric( @@ -986,8 +908,7 @@ class AutofillMetrics { SaveCardPromptMetric metric, bool is_uploading, bool is_reshow, - bool is_requesting_cardholder_name, - bool is_requesting_expiration_date_from_user, + AutofillClient::SaveCreditCardOptions options, int previous_save_credit_card_prompt_user_decision, security_state::SecurityLevel security_level, AutofillSyncSigninState sync_state); @@ -1069,6 +990,13 @@ class AutofillMetrics { static void LogCardholderNameFixFlowPromptEvent( CardholderNameFixFlowPromptEvent event); + // Logs |event| to expiration date fix flow prompt events histogram. + static void LogExpirationDateFixFlowPromptEvent( + ExpirationDateFixFlowPromptEvent event); + + // Logs the count of expiration date fix flow prompts shown histogram. + static void LogExpirationDateFixFlowPromptShown(); + // Logs the time elapsed between the unmask prompt being shown and it // being closed. static void LogUnmaskPromptEventDuration(const base::TimeDelta& duration, @@ -1303,108 +1231,13 @@ class AutofillMetrics { // server cards to be shown. static void LogWalletSyncTransportCardsOptIn(bool is_opted_in); - // Utility to log autofill form events in the relevant histograms depending on - // the presence of server and/or local data. - class FormEventLogger { - public: - FormEventLogger(bool is_for_credit_card, - bool is_in_main_frame, - FormInteractionsUkmLogger* form_interactions_ukm_logger); - - inline void set_server_record_type_count(size_t server_record_type_count) { - server_record_type_count_ = server_record_type_count; - } - - inline void set_local_record_type_count(size_t local_record_type_count) { - local_record_type_count_ = local_record_type_count; - } - - inline void set_is_context_secure(bool is_context_secure) { - is_context_secure_ = is_context_secure; - } - - void OnDidInteractWithAutofillableForm(FormSignature form_signature, - AutofillSyncSigninState sync_state); - - void OnDidPollSuggestions(const FormFieldData& field, - AutofillSyncSigninState sync_state); - - void OnDidParseForm(); - - void OnDidInteractWithAutofillableForm(FormSignature form_signature); - - void OnPopupSuppressed(const FormStructure& form, - const AutofillField& field); - - void OnDidShowSuggestions(const FormStructure& form, - const AutofillField& field, - const base::TimeTicks& form_parsed_timestamp, - AutofillSyncSigninState sync_state); - - void OnDidSelectMaskedServerCardSuggestion( - const base::TimeTicks& form_parsed_timestamp, - AutofillSyncSigninState sync_state); - - // In case of masked cards, caller must make sure this gets called before - // the card is upgraded to a full card. - void OnDidFillSuggestion(const CreditCard& credit_card, - const FormStructure& form, - const AutofillField& field, - AutofillSyncSigninState sync_state); - - void OnDidFillSuggestion(const AutofillProfile& profile, - const FormStructure& form, - const AutofillField& field, - AutofillSyncSigninState sync_state); - - void OnWillSubmitForm(AutofillSyncSigninState sync_state); - - void OnFormSubmitted(bool force_logging, - const CardNumberStatus card_number_status, - AutofillSyncSigninState sync_state); - - void SetBankNameAvailable(); - - void OnDidSeeFillableDynamicForm(AutofillSyncSigninState sync_state); - - void OnDidRefill(AutofillSyncSigninState sync_state); - - void OnSubsequentRefillAttempt(AutofillSyncSigninState sync_state); - - private: - void Log(FormEvent event) const; - void Log(BankNameDisplayedFormEvent event) const; - - bool is_for_credit_card_; - bool is_in_main_frame_; - size_t server_record_type_count_; - size_t local_record_type_count_; - bool is_context_secure_; - bool has_logged_interacted_; - bool has_logged_popup_suppressed_; - bool has_logged_suggestions_shown_; - bool has_logged_masked_server_card_suggestion_selected_; - bool has_logged_suggestion_filled_; - bool has_logged_will_submit_; - bool has_logged_submitted_; - bool has_logged_bank_name_available_; - bool logged_suggestion_filled_was_server_data_; - bool logged_suggestion_filled_was_masked_server_card_; - - // The last field that was polled for suggestions. - FormFieldData last_polled_field_; - - FormInteractionsUkmLogger* - form_interactions_ukm_logger_; // Weak reference. - - AutofillSyncSigninState sync_state_ = - AutofillSyncSigninState::kNumSyncStates; - }; + static const char* GetMetricsSyncStateSuffix( + AutofillSyncSigninState sync_state); private: static void Log(AutocompleteEvent event); - static const int kNumCardUploadDecisionMetrics = 15; + static const int kNumCardUploadDecisionMetrics = 17; DISALLOW_IMPLICIT_CONSTRUCTORS(AutofillMetrics); }; diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc index 213d7d340fa..87afa30900e 100644 --- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc @@ -23,6 +23,9 @@ #include "base/time/time.h" #include "components/autofill/core/browser/autofill_external_delegate.h" #include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/metrics/address_form_event_logger.h" +#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h" +#include "components/autofill/core/browser/metrics/form_events.h" #include "components/autofill/core/browser/mock_autocomplete_history_manager.h" #include "components/autofill/core/browser/payments/test_payments_client.h" #include "components/autofill/core/browser/personal_data_manager.h" @@ -70,8 +73,6 @@ using UkmCardUploadDecisionType = ukm::builders::Autofill_CardUploadDecision; using UkmDeveloperEngagementType = ukm::builders::Autofill_DeveloperEngagement; using UkmInteractedWithFormType = ukm::builders::Autofill_InteractedWithForm; using UkmSuggestionsShownType = ukm::builders::Autofill_SuggestionsShown; -using UkmSelectedMaskedServerCardType = - ukm::builders::Autofill_SelectedMaskedServerCard; using UkmSuggestionFilledType = ukm::builders::Autofill_SuggestionFilled; using UkmTextFieldDidChangeType = ukm::builders::Autofill_TextFieldDidChange; using UkmLogHiddenRepresentationalFieldSkipDecisionType = @@ -81,10 +82,13 @@ using UkmLogRepeatedServerTypePredictionRationalized = using UkmFormSubmittedType = ukm::builders::Autofill_FormSubmitted; using UkmFieldTypeValidationType = ukm::builders::Autofill_FieldTypeValidation; using UkmFieldFillStatusType = ukm::builders::Autofill_FieldFillStatus; +using UkmFormEventType = ukm::builders::Autofill_FormEvent; using ExpectedUkmMetrics = std::vector<std::vector<std::pair<const char*, int64_t>>>; +const char* kTestGuid = "00000000-0000-0000-0000-000000000001"; + int64_t Collapse(uint64_t sig) { return sig % 1021; } @@ -131,10 +135,10 @@ MATCHER(CompareMetricsIgnoringMillisecondsSinceFormParsed, "") { UkmSuggestionFilledType::kMillisecondsSinceFormParsedName)); } -void VerifyFormInteractionUkm(const ukm::TestAutoSetUkmRecorder& ukm_recorder, - const FormData& form, - const char* event_name, - const ExpectedUkmMetrics& expected_metrics) { +void VerifyUkm(const ukm::TestAutoSetUkmRecorder& ukm_recorder, + const FormData& form, + const char* event_name, + const ExpectedUkmMetrics& expected_metrics) { auto entries = ukm_recorder.GetEntriesByName(event_name); EXPECT_LE(entries.size(), expected_metrics.size()); @@ -154,16 +158,15 @@ void VerifySubmitFormUkm(const ukm::TestAutoSetUkmRecorder& ukm_recorder, bool is_for_credit_card, bool has_upi_vpa_field, const std::set<FormType>& form_types) { - VerifyFormInteractionUkm( - ukm_recorder, form, UkmFormSubmittedType::kEntryName, - {{{UkmFormSubmittedType::kAutofillFormSubmittedStateName, state}, - {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmFormSubmittedType::kIsForCreditCardName, is_for_credit_card}, - {UkmFormSubmittedType::kHasUpiVpaFieldName, has_upi_vpa_field}, - {UkmFormSubmittedType::kFormTypesName, - AutofillMetrics::FormTypesToBitVector(form_types)}, - {UkmFormSubmittedType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}}}); + VerifyUkm(ukm_recorder, form, UkmFormSubmittedType::kEntryName, + {{{UkmFormSubmittedType::kAutofillFormSubmittedStateName, state}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmFormSubmittedType::kIsForCreditCardName, is_for_credit_card}, + {UkmFormSubmittedType::kHasUpiVpaFieldName, has_upi_vpa_field}, + {UkmFormSubmittedType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector(form_types)}, + {UkmFormSubmittedType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}}}); } void AppendFieldFillStatusUkm(const FormData& form, @@ -218,6 +221,14 @@ void AppendFieldTypeUkm(const FormData& form, } } +void SetProfileTestData(AutofillProfile* profile) { + test::SetProfileInfo(profile, "Elvis", "Aaron", "Presley", + "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", + "Apt. 10", "Memphis", "Tennessee", "38116", "US", + "12345678901"); + profile->set_guid(kTestGuid); +} + class MockAutofillClient : public TestAutofillClient { public: MockAutofillClient() {} @@ -242,7 +253,8 @@ class AutofillMetricsTest : public testing::Test { void CreateAmbiguousProfiles(); // Removes all existing profiles and creates one profile. - void RecreateProfile(); + // |is_server| allows creation of |SERVER_PROFILE|. + void RecreateProfile(bool is_server); // Removes all existing credit cards and creates a local, masked server, // and/or full server credit card, according to the parameters. @@ -353,16 +365,19 @@ void AutofillMetricsTest::CreateAmbiguousProfiles() { personal_data_->Refresh(); } -void AutofillMetricsTest::RecreateProfile() { +void AutofillMetricsTest::RecreateProfile(bool is_server) { personal_data_->ClearProfiles(); - AutofillProfile profile; - test::SetProfileInfo(&profile, "Elvis", "Aaron", "Presley", - "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", - "Apt. 10", "Memphis", "Tennessee", "38116", "US", - "12345678901"); - profile.set_guid("00000000-0000-0000-0000-000000000001"); - personal_data_->AddProfile(profile); + if (is_server) { + AutofillProfile profile(AutofillProfile::SERVER_PROFILE, "server_id"); + SetProfileTestData(&profile); + personal_data_->AddProfile(profile); + } else { + AutofillProfile profile; + SetProfileTestData(&profile); + personal_data_->AddProfile(profile); + } + personal_data_->Refresh(); } @@ -424,7 +439,7 @@ void AutofillMetricsTest::CreateTestAutofillProfiles() { "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", "Apt. 10", "Memphis", "Tennessee", "38116", "US", "12345678901"); - profile1.set_guid("00000000-0000-0000-0000-000000000001"); + profile1.set_guid(kTestGuid); personal_data_->AddProfile(profile1); AutofillProfile profile2; @@ -453,12 +468,12 @@ class AutofillMetricsIFrameTest : public AutofillMetricsTest, const std::string credit_card_form_events_frame_histogram_; }; -INSTANTIATE_TEST_CASE_P(AutofillMetricsTest, - AutofillMetricsIFrameTest, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P(AutofillMetricsTest, + AutofillMetricsIFrameTest, + testing::Bool()); -// Test parameter indicates if the metrics are being logged for a form in an -// iframe or the main frame. True means the form is in the main frame. +// Test parameter indicates if the metrics are being logged for a form +// with a companyname field specified. class AutofillMetricsCompanyTest : public AutofillMetricsTest, public testing::WithParamInterface<bool> { public: @@ -477,9 +492,9 @@ class AutofillMetricsCompanyTest : public AutofillMetricsTest, base::test::ScopedFeatureList scoped_feature_list_; }; -INSTANTIATE_TEST_CASE_P(AutofillMetricsTest, - AutofillMetricsCompanyTest, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P(AutofillMetricsTest, + AutofillMetricsCompanyTest, + testing::Bool()); // Test that we log quality metrics appropriately. TEST_F(AutofillMetricsTest, QualityMetrics) { @@ -723,7 +738,7 @@ TEST_F(AutofillMetricsTest, base::UserActionTester user_action_tester; // Simulate having seen this form on page load. autofill_manager_->AddSeenForm(form, heuristic_types, server_types); - std::string guid("00000000-0000-0000-0000-000000000001"); + std::string guid(kTestGuid); // Trigger phone number rationalization at filling time. autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), @@ -788,7 +803,7 @@ TEST_F(AutofillMetricsTest, base::UserActionTester user_action_tester; // Simulate having seen this form on page load. autofill_manager_->AddSeenForm(form, heuristic_types, server_types); - std::string guid("00000000-0000-0000-0000-000000000001"); + std::string guid(kTestGuid); // Trigger phone number rationalization at filling time. autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), @@ -815,7 +830,7 @@ TEST_F(AutofillMetricsTest, // correctly. TEST_F(AutofillMetricsTest, LogHiddenRepresentationalFieldSkipDecision) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; @@ -870,13 +885,13 @@ TEST_F(AutofillMetricsTest, LogHiddenRepresentationalFieldSkipDecision) { // Simulate filling form. { base::UserActionTester user_action_tester; - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile. + std::string guid(kTestGuid); // local profile. autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); } - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmLogHiddenRepresentationalFieldSkipDecisionType::kEntryName, {{{UkmLogHiddenRepresentationalFieldSkipDecisionType::kFormSignatureName, @@ -1019,7 +1034,7 @@ TEST_F(AutofillMetricsTest, LogRepeatedAddressTypeRationalized) { .size(), (size_t)2); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmLogRepeatedServerTypePredictionRationalized::kEntryName, {{{UkmLogRepeatedServerTypePredictionRationalized::kFormSignatureName, @@ -1134,7 +1149,7 @@ TEST_F(AutofillMetricsTest, LogRepeatedStateCountryTypeRationalized) { .size(), (size_t)3); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmLogRepeatedServerTypePredictionRationalized::kEntryName, {{{UkmLogRepeatedServerTypePredictionRationalized::kFormSignatureName, @@ -1242,7 +1257,7 @@ TEST_F(AutofillMetricsTest, base::UserActionTester user_action_tester; // Simulate having seen this form on page load. autofill_manager_->AddSeenForm(form, heuristic_types, server_types); - std::string guid("00000000-0000-0000-0000-000000000001"); + std::string guid(kTestGuid); // Trigger phone number rationalization at filling time. autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), @@ -1323,7 +1338,7 @@ TEST_F(AutofillMetricsTest, base::UserActionTester user_action_tester; // Simulate having seen this form on page load. autofill_manager_->AddSeenForm(form, heuristic_types, server_types); - std::string guid("00000000-0000-0000-0000-000000000001"); + std::string guid(kTestGuid); // Trigger phone number rationalization at filling time. autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), @@ -1622,9 +1637,8 @@ TEST_P(QualityMetricsTest, Classification) { ExpectedUkmMetrics expected_ukm_metrics; AppendFieldTypeUkm(form, heuristic_types, server_types, actual_types, &expected_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldTypeValidationType::kEntryName, - expected_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldTypeValidationType::kEntryName, + expected_ukm_metrics); // Validate the total samples and the crossed (predicted-to-actual) samples. for (const auto& source : prediction_sources) { @@ -1722,7 +1736,7 @@ TEST_P(QualityMetricsTest, Classification) { } } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillMetricsTest, QualityMetricsTest, testing::Values(QualityMetricsTestCase{NO_SERVER_DATA, EMPTY_TYPE}, @@ -2882,7 +2896,6 @@ TEST_F(AutofillMetricsTest, AutofillIsEnabledAtStartup) { /*identity_manager=*/nullptr, /*client_profile_validator=*/nullptr, /*history_service=*/nullptr, - /*cookie_manager_sevice=*/nullptr, /*is_off_the_record=*/false); histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.Startup", true, 1); } @@ -2897,7 +2910,6 @@ TEST_F(AutofillMetricsTest, AutofillIsDisabledAtStartup) { /*identity_manager=*/nullptr, /*client_profile_validator=*/nullptr, /*history_service=*/nullptr, - /*cookie_manager_sevice=*/nullptr, /*is_off_the_record=*/false); histogram_tester.ExpectUniqueSample("Autofill.IsEnabled.Startup", false, 1); } @@ -3107,7 +3119,7 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) { "Autofill_FormSubmitted_NonFillable")); } - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmTextFieldDidChangeType::kHeuristicTypeName, CREDIT_CARD_NAME_FULL}, @@ -3128,7 +3140,7 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) { // Expect 2 |FORM_EVENT_LOCAL_SUGGESTION_FILLED| events. First, from // call to |external_delegate_->DidAcceptSuggestion|. Second, from call to // |autofill_manager_->FillOrPreviewForm|. - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, {{{UkmSuggestionFilledType::kRecordTypeName, CreditCard::LOCAL_CARD}, {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, @@ -3182,7 +3194,7 @@ TEST_F(AutofillMetricsTest, UpiVpaUkmTest) { // Test that the profile checkout flow user actions are correctly logged. TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; @@ -3237,7 +3249,7 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) { // Simulate selecting a profile suggestions. { base::UserActionTester user_action_tester; - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile. + std::string guid(kTestGuid); // local profile. external_delegate_->OnQuery(0, form, form.fields.front(), gfx::RectF()); external_delegate_->DidAcceptSuggestion( ASCIIToUTF16("Test"), @@ -3249,7 +3261,7 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) { // Simulate filling a profile suggestion. { base::UserActionTester user_action_tester; - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile. + std::string guid(kTestGuid); // local profile. autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); @@ -3270,7 +3282,7 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) { "Autofill_FormSubmitted_NonFillable")); } - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmTextFieldDidChangeType::kHeuristicTypeName, ADDRESS_HOME_STATE}, @@ -3291,24 +3303,23 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) { // Expect 2 |FORM_EVENT_LOCAL_SUGGESTION_FILLED| events. First, from // call to |external_delegate_->DidAcceptSuggestion|. Second, from call to // |autofill_manager_->FillOrPreviewForm|. - VerifyFormInteractionUkm( - test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, - {{{UkmSuggestionFilledType::kRecordTypeName, - AutofillProfile::LOCAL_PROFILE}, - {UkmSuggestionFilledType::kIsForCreditCardName, false}, - {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmSuggestionFilledType::kFieldSignatureName, - Collapse(CalculateFieldSignatureForField(form.fields.front()))}, - {UkmSuggestionFilledType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}}, - {{UkmSuggestionFilledType::kRecordTypeName, - AutofillProfile::LOCAL_PROFILE}, - {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmSuggestionFilledType::kIsForCreditCardName, false}, - {UkmSuggestionsShownType::kFieldSignatureName, - Collapse(CalculateFieldSignatureForField(form.fields.front()))}, - {UkmSuggestionsShownType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}}}); + VerifyUkm(test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, + {{{UkmSuggestionFilledType::kRecordTypeName, + AutofillProfile::LOCAL_PROFILE}, + {UkmSuggestionFilledType::kIsForCreditCardName, false}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmSuggestionFilledType::kFieldSignatureName, + Collapse(CalculateFieldSignatureForField(form.fields.front()))}, + {UkmSuggestionFilledType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}}, + {{UkmSuggestionFilledType::kRecordTypeName, + AutofillProfile::LOCAL_PROFILE}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmSuggestionFilledType::kIsForCreditCardName, false}, + {UkmSuggestionsShownType::kFieldSignatureName, + Collapse(CalculateFieldSignatureForField(form.fields.front()))}, + {UkmSuggestionsShownType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}}}); // Expect |NON_FILLABLE_FORM_OR_NEW_DATA| in |AutofillFormSubmittedState| // because |field.value| is empty in |DeterminePossibleFieldTypesForUpload|. VerifySubmitFormUkm(test_ukm_recorder_, form, @@ -3443,7 +3454,7 @@ TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) { // Tests that the Autofill_PolledProfileSuggestions user action is only logged // once if the field is queried repeatedly. TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) { - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up the form data. FormData form; @@ -3528,8 +3539,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardParsedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnFormsSeen(forms, base::TimeTicks()); histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.CreditCard.WithNoData", - AutofillMetrics::FORM_EVENT_DID_PARSE_FORM, 1); + "Autofill.FormEvents.CreditCard.WithNoData", FORM_EVENT_DID_PARSE_FORM, + 1); } // Test that we log interacted form event for credit cards related. @@ -3562,12 +3573,11 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardInteractedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); + histogram_tester.ExpectUniqueSample("Autofill.FormEvents.CreditCard", + FORM_EVENT_INTERACTED_ONCE, 1); histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); - histogram_tester.ExpectUniqueSample( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + credit_card_form_events_frame_histogram_, FORM_EVENT_INTERACTED_ONCE, + 1); } // Reset the autofill manager state. @@ -3581,12 +3591,11 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardInteractedFormEvents) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); autofill_manager_->OnQueryFormFieldAutofill( 1, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); + histogram_tester.ExpectUniqueSample("Autofill.FormEvents.CreditCard", + FORM_EVENT_INTERACTED_ONCE, 1); histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); - histogram_tester.ExpectUniqueSample( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + credit_card_form_events_frame_histogram_, FORM_EVENT_INTERACTED_ONCE, + 1); } } @@ -3619,18 +3628,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardPopupSuppressedFormEvents) { // Simulating popup being suppressed. base::HistogramTester histogram_tester; autofill_manager_->DidSuppressPopup(form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_POPUP_SUPPRESSED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_POPUP_SUPPRESSED, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); } autofill_manager_->Reset(); @@ -3641,18 +3646,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardPopupSuppressedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->DidSuppressPopup(form, field); autofill_manager_->DidSuppressPopup(form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 2); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_POPUP_SUPPRESSED, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_POPUP_SUPPRESSED, 2); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); } } @@ -3685,18 +3686,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { // Simulating new popup being shown. base::HistogramTester histogram_tester; autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( @@ -3713,18 +3710,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( @@ -3741,18 +3734,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->DidShowSuggestions(false /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 0); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 0); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 0); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 0); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 0); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( @@ -3773,21 +3762,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -3803,21 +3788,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -3835,21 +3816,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -3865,21 +3842,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -3924,18 +3897,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSelectedFormEvents) { autofill_manager_->MakeFrontendID(guid, std::string())); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, 1); } // Reset the autofill manager state. @@ -3955,18 +3926,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSelectedFormEvents) { autofill_manager_->MakeFrontendID(guid, std::string())); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 2); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 2); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 2); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 2); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, 1); } } @@ -4006,18 +3975,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(guid, std::string())); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + 1); } // Reset the autofill manager state. @@ -4038,18 +4005,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, 1); } // Recreating cards as the previous test should have upgraded the masked @@ -4070,18 +4035,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(guid, std::string())); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SERVER_SUGGESTION_FILLED, 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SERVER_SUGGESTION_FILLED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, + 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, + 1); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( @@ -4103,18 +4066,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(guid, std::string())); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + 1); } // Recreate masked server cards with bank names. @@ -4140,7 +4101,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -4165,7 +4126,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -4189,7 +4150,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { autofill_manager_->MakeFrontendID(guid, std::string())); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -4213,7 +4174,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) { autofill_manager_->MakeFrontendID(guid, std::string())); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard.BankNameDisplayed", - AutofillMetrics:: + CreditCardFormEventLogger:: FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE, 1); } @@ -4328,8 +4289,7 @@ TEST_F(AutofillMetricsTest, SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, - 1); + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, 1); } TEST_P(AutofillMetricsIFrameTest, @@ -4370,12 +4330,10 @@ TEST_P(AutofillMetricsIFrameTest, SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, 1); } @@ -4419,12 +4377,10 @@ TEST_P(AutofillMetricsIFrameTest, SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, 1); } @@ -4469,12 +4425,10 @@ TEST_P(AutofillMetricsIFrameTest, SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 1); } @@ -4519,12 +4473,10 @@ TEST_P(AutofillMetricsIFrameTest, SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 1); } @@ -4574,38 +4526,32 @@ TEST_P(AutofillMetricsIFrameTest, SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, - 0); + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0); } TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -4638,8 +4584,7 @@ TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, - 0); + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, 0); } // Test that we log submitted form events for credit cards. @@ -4681,16 +4626,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, @@ -4714,18 +4659,18 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmTextFieldDidChangeType::kHeuristicTypeName, CREDIT_CARD_NUMBER}, @@ -4762,18 +4707,18 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { autofill_manager_->Reset(); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmTextFieldDidChangeType::kHeuristicTypeName, CREDIT_CARD_NUMBER}, @@ -4809,18 +4754,18 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, {{{UkmSuggestionFilledType::kRecordTypeName, CreditCard::LOCAL_CARD}, {UkmSuggestionFilledType::kIsForCreditCardName, true}, @@ -4855,18 +4800,18 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, {{{UkmSuggestionFilledType::kRecordTypeName, CreditCard::FULL_SERVER_CARD}, @@ -4902,32 +4847,26 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - 1); - - VerifyFormInteractionUkm( - test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, - {{{UkmSuggestionFilledType::kRecordTypeName, - CreditCard::MASKED_SERVER_CARD}, - {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmSuggestionFilledType::kIsForCreditCardName, true}, - {UkmSuggestionFilledType::kFieldSignatureName, - Collapse(CalculateFieldSignatureForField(form.fields.back()))}, - {UkmSuggestionFilledType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}}}); - VerifyFormInteractionUkm( - test_ukm_recorder_, form, UkmSelectedMaskedServerCardType::kEntryName, - {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, 1); + + VerifyUkm(test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, + {{{UkmSuggestionFilledType::kRecordTypeName, + CreditCard::MASKED_SERVER_CARD}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmSuggestionFilledType::kIsForCreditCardName, true}, + {UkmSuggestionFilledType::kFieldSignatureName, + Collapse(CalculateFieldSignatureForField(form.fields.back()))}, + {UkmSuggestionFilledType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}}}); VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, /*is_for_credit_card=*/true, @@ -4965,7 +4904,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { autofill_manager_->OnFormSubmitted(form, false, SubmissionSource::FORM_SUBMISSION); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, {{{UkmFormSubmittedType::kAutofillFormSubmittedStateName, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA}, @@ -4988,70 +4927,66 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); } @@ -5070,74 +5005,70 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 0); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmTextFieldDidChangeType::kHeuristicTypeName, CREDIT_CARD_NUMBER}, @@ -5195,16 +5126,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); } // Reset the autofill manager state. @@ -5221,16 +5152,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. @@ -5250,16 +5181,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. @@ -5280,16 +5211,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. @@ -5308,18 +5239,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { "6011000990139424"); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, - 1); + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, 1); } // Recreating cards as the previous test should have upgraded the masked @@ -5343,70 +5272,66 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics :: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics :: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); } @@ -5424,70 +5349,66 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 0); + histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_, + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.CreditCard", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( credit_card_form_events_frame_histogram_, - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); } @@ -5529,12 +5450,11 @@ TEST_F(AutofillMetricsTest, MixedParsedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnFormsSeen(forms, base::TimeTicks()); + histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address.WithNoData", + FORM_EVENT_DID_PARSE_FORM, 1); histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.Address.WithNoData", - AutofillMetrics::FORM_EVENT_DID_PARSE_FORM, 1); - histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.CreditCard.WithNoData", - AutofillMetrics::FORM_EVENT_DID_PARSE_FORM, 1); + "Autofill.FormEvents.CreditCard.WithNoData", FORM_EVENT_DID_PARSE_FORM, + 1); } // Test that we log parsed form events for address. @@ -5564,9 +5484,19 @@ TEST_F(AutofillMetricsTest, AddressParsedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnFormsSeen(forms, base::TimeTicks()); - histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.Address.WithNoData", - AutofillMetrics::FORM_EVENT_DID_PARSE_FORM, 1); + histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address.WithNoData", + FORM_EVENT_DID_PARSE_FORM, 1); + + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(1u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, FORM_EVENT_DID_PARSE_FORM}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } // Test that we log interacted form events for address. @@ -5599,13 +5529,25 @@ TEST_F(AutofillMetricsTest, AddressInteractedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); - histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address", + FORM_EVENT_INTERACTED_ONCE, 1); + + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(1u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_INTERACTED_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -5615,16 +5557,26 @@ TEST_F(AutofillMetricsTest, AddressInteractedFormEvents) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); autofill_manager_->OnQueryFormFieldAutofill( 1, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); - histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address", + FORM_EVENT_INTERACTED_ONCE, 1); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(1u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_INTERACTED_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } } // Test that popup suppressed form events for address are logged. TEST_F(AutofillMetricsTest, AddressSuppressedFormEvents) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -5652,16 +5604,32 @@ TEST_F(AutofillMetricsTest, AddressSuppressedFormEvents) { // Simulating new popup being shown. base::HistogramTester histogram_tester; autofill_manager_->DidSuppressPopup(form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_POPUP_SUPPRESSED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(2u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_POPUP_SUPPRESSED}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_POPUP_SUPPRESSED_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -5669,19 +5637,39 @@ TEST_F(AutofillMetricsTest, AddressSuppressedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->DidSuppressPopup(form, field); autofill_manager_->DidSuppressPopup(form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_POPUP_SUPPRESSED, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1); + + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(3u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_POPUP_SUPPRESSED}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_POPUP_SUPPRESSED_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_POPUP_SUPPRESSED}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } } // Test that we log suggestion shown form events for address. TEST_F(AutofillMetricsTest, AddressShownFormEvents) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -5709,21 +5697,36 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) { // Simulating new popup being shown. base::HistogramTester histogram_tester; autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( "Autofill.FormEvents.CreditCard") ["Autofill.FormEvents.CreditCard.BankNameDisplayed"]); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(2u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_SUGGESTIONS_SHOWN}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -5731,21 +5734,41 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 1); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( "Autofill.FormEvents.CreditCard") ["Autofill.FormEvents.CreditCard.BankNameDisplayed"]); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(3u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_SUGGESTIONS_SHOWN}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_SUGGESTIONS_SHOWN}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -5753,24 +5776,26 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->DidShowSuggestions(false /* is_new_popup */, form, field); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, 0); // Check that the bank name histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ(0, histogram_tester.GetTotalCountsForPrefix( "Autofill.FormEvents.CreditCard") ["Autofill.FormEvents.CreditCard.BankNameDisplayed"]); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(0u, entries.size()); } } // Test that we log filled form events for address. TEST_F(AutofillMetricsTest, AddressFilledFormEvents) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -5797,45 +5822,99 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) { { // Simulating selecting/filling a local profile suggestion. base::HistogramTester histogram_tester; - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile + std::string guid(kTestGuid); // local profile autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + 1); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(2u, entries.size()); + VerifyUkm( + test_ukm_recorder_, form, UkmFormEventType::kEntryName, + {{{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_LOCAL_SUGGESTION_FILLED}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}, + {{UkmFormEventType::kAutofillFormEventName, + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE}, + {UkmFormEventType::kFormTypesName, + AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}}}); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { - // Simulating selecting/filling a local profile suggestion. + // Simulating selecting/filling a local profile suggestion more than once. base::HistogramTester histogram_tester; - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile + std::string guid(kTestGuid); // local profile autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + 1); + } + + // Create a server profile and reset the autofill manager state. + RecreateProfile(/*is_server=*/true); + autofill_manager_->Reset(); + autofill_manager_->AddSeenForm(form, field_types, field_types); + + { + // Simulate selecting/filling a server profile suggestion. + base::HistogramTester histogram_tester; + std::string guid(kTestGuid); // server profile + autofill_manager_->FillOrPreviewForm( + AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), + autofill_manager_->MakeFrontendID(std::string(), guid)); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SERVER_SUGGESTION_FILLED, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, + 1); + } + + autofill_manager_->Reset(); + autofill_manager_->AddSeenForm(form, field_types, field_types); + + { + // Simulate selecting/filling a server profile suggestion more than once. + base::HistogramTester histogram_tester; + std::string guid(kTestGuid); // server profile + autofill_manager_->FillOrPreviewForm( + AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), + autofill_manager_->MakeFrontendID(std::string(), guid)); + autofill_manager_->FillOrPreviewForm( + AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), + autofill_manager_->MakeFrontendID(std::string(), guid)); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SERVER_SUGGESTION_FILLED, 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, + 1); } } // Test that we log submitted form events for address. TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -5868,10 +5947,10 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, @@ -5897,10 +5976,10 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { autofill_manager_->Reset(); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); VerifySubmitFormUkm(test_ukm_recorder_, form, AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, @@ -5923,14 +6002,15 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -5938,7 +6018,7 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile + std::string guid(kTestGuid); // local profile autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); @@ -5946,10 +6026,10 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. @@ -5968,32 +6048,33 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -6006,45 +6087,48 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); + + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(2u, entries.size()); } } // Test that we log "will submit" and "submitted" form events for address. TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { // Create a profile. - RecreateProfile(); + RecreateProfile(/*is_server=*/false); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -6077,14 +6161,15 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -6097,14 +6182,15 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -6112,7 +6198,7 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { base::HistogramTester histogram_tester; autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); - std::string guid("00000000-0000-0000-0000-000000000001"); // local profile + std::string guid(kTestGuid); // local profile autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); @@ -6120,14 +6206,15 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -6141,42 +6228,45 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 1); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(3u, entries.size()); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); { @@ -6188,38 +6278,40 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { SubmissionSource::FORM_SUBMISSION); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, 0); + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics:: FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, 0); + // Check if FormEvent UKM is logged properly + auto entries = + test_ukm_recorder_.GetEntriesByName(UkmFormEventType::kEntryName); + EXPECT_EQ(2u, entries.size()); } } @@ -6257,12 +6349,13 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) { autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.CreditCard.WithNoData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + "Autofill.FormEvents.CreditCard.WithNoData", FORM_EVENT_INTERACTED_ONCE, + 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); RecreateCreditCards(true /* include_local_credit_card */, false /* include_masked_server_credit_card */, @@ -6275,11 +6368,12 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( "Autofill.FormEvents.CreditCard.WithOnlyLocalData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + FORM_EVENT_INTERACTED_ONCE, 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); RecreateCreditCards(false /* include_local_credit_card */, true /* include_masked_server_credit_card */, @@ -6292,11 +6386,12 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( "Autofill.FormEvents.CreditCard.WithOnlyServerData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + FORM_EVENT_INTERACTED_ONCE, 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); RecreateCreditCards(false /* include_local_credit_card */, false /* include_masked_server_credit_card */, @@ -6309,11 +6404,12 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( "Autofill.FormEvents.CreditCard.WithOnlyServerData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + FORM_EVENT_INTERACTED_ONCE, 1); } // Reset the autofill manager state. autofill_manager_->Reset(); + PurgeUKM(); autofill_manager_->AddSeenForm(form, field_types, field_types); RecreateCreditCards(true /* include_local_credit_card */, false /* include_masked_server_credit_card */, @@ -6326,7 +6422,7 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( "Autofill.FormEvents.CreditCard.WithBothServerAndLocalData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + FORM_EVENT_INTERACTED_ONCE, 1); } } @@ -6362,14 +6458,14 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) { autofill_manager_->OnQueryFormFieldAutofill( 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( - "Autofill.FormEvents.Address.WithNoData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + "Autofill.FormEvents.Address.WithNoData", FORM_EVENT_INTERACTED_ONCE, + 1); } // Reset the autofill manager state. autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); - RecreateProfile(); + RecreateProfile(/*is_server=*/false); { // Simulate activating the autofill popup for the street field. @@ -6378,7 +6474,7 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) { 0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false); histogram_tester.ExpectUniqueSample( "Autofill.FormEvents.Address.WithOnlyLocalData", - AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1); + FORM_EVENT_INTERACTED_ONCE, 1); } } @@ -6476,14 +6572,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } // Non fillable form. @@ -6513,14 +6607,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } // Fillable form. @@ -6555,14 +6647,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } // Autofilled none with suggestions shown. @@ -6578,18 +6668,17 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { EXPECT_EQ(1, user_action_tester.GetActionCount( "Autofill_FormSubmitted_FilledNone_SuggestionsShown")); - VerifyFormInteractionUkm( - test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, - {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmSuggestionsShownType::kFieldSignatureName, - Collapse(CalculateFieldSignatureForField(form.fields[2]))}, - {UkmSuggestionsShownType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}, - {UkmTextFieldDidChangeType::kHeuristicTypeName, - PHONE_HOME_WHOLE_NUMBER}, - {UkmTextFieldDidChangeType::kHtmlFieldTypeName, - HTML_TYPE_UNSPECIFIED}, - {UkmTextFieldDidChangeType::kServerTypeName, NO_SERVER_DATA}}}); + VerifyUkm(test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, + {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmSuggestionsShownType::kFieldSignatureName, + Collapse(CalculateFieldSignatureForField(form.fields[2]))}, + {UkmSuggestionsShownType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}, + {UkmTextFieldDidChangeType::kHeuristicTypeName, + PHONE_HOME_WHOLE_NUMBER}, + {UkmTextFieldDidChangeType::kHtmlFieldTypeName, + HTML_TYPE_UNSPECIFIED}, + {UkmTextFieldDidChangeType::kServerTypeName, NO_SERVER_DATA}}}); expected_form_submission_ukm_metrics.push_back( {{UkmFormSubmittedType::kAutofillFormSubmittedStateName, @@ -6602,14 +6691,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } // Mark one of the fields as autofilled. @@ -6639,14 +6726,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } // Mark all of the fillable fields as autofilled. @@ -6677,14 +6762,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } // Clear out the third field's value. @@ -6722,14 +6805,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) { {FormType::ADDRESS_FORM, FormType::UNKNOWN_FORM_TYPE})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } } @@ -6797,14 +6878,12 @@ TEST_F( AutofillMetrics::FormTypesToBitVector({FormType::ADDRESS_FORM})}, {UkmFormSubmittedType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFormSubmittedType::kEntryName, - expected_form_submission_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName, + expected_form_submission_ukm_metrics); AppendFieldFillStatusUkm(form, &expected_field_fill_status_ukm_metrics); - VerifyFormInteractionUkm(test_ukm_recorder_, form, - UkmFieldFillStatusType::kEntryName, - expected_field_fill_status_ukm_metrics); + VerifyUkm(test_ukm_recorder_, form, UkmFieldFillStatusType::kEntryName, + expected_field_fill_status_ukm_metrics); } } @@ -7166,7 +7245,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) { // Simulate editing an autofilled field. { base::HistogramTester histogram_tester; - std::string guid("00000000-0000-0000-0000-000000000001"); + std::string guid(kTestGuid); autofill_manager_->FillOrPreviewForm( AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(), autofill_manager_->MakeFrontendID(std::string(), guid)); @@ -7214,12 +7293,11 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) { autofill_manager_->Reset(); - VerifyFormInteractionUkm( - test_ukm_recorder_, form, UkmInteractedWithFormType::kEntryName, - {{{UkmInteractedWithFormType::kIsForCreditCardName, false}, - {UkmInteractedWithFormType::kLocalRecordTypeCountName, 0}, - {UkmInteractedWithFormType::kServerRecordTypeCountName, 0}}}); - VerifyFormInteractionUkm( + VerifyUkm(test_ukm_recorder_, form, UkmInteractedWithFormType::kEntryName, + {{{UkmInteractedWithFormType::kIsForCreditCardName, false}, + {UkmInteractedWithFormType::kLocalRecordTypeCountName, 0}, + {UkmInteractedWithFormType::kServerRecordTypeCountName, 0}}}); + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, {UkmTextFieldDidChangeType::kHeuristicTypeName, @@ -7256,24 +7334,23 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) { Collapse(CalculateFieldSignatureForField(form.fields[1]))}, {UkmSuggestionsShownType::kFormSignatureName, Collapse(CalculateFormSignature(form))}}}); - VerifyFormInteractionUkm( - test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, - {{{UkmSuggestionFilledType::kRecordTypeName, - AutofillProfile::LOCAL_PROFILE}, - {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmSuggestionFilledType::kIsForCreditCardName, false}, - {UkmSuggestionFilledType::kFieldSignatureName, - Collapse(CalculateFieldSignatureForField(form.fields[0]))}, - {UkmSuggestionFilledType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}}, - {{UkmSuggestionFilledType::kRecordTypeName, - AutofillProfile::LOCAL_PROFILE}, - {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, - {UkmSuggestionFilledType::kFieldSignatureName, - Collapse(CalculateFieldSignatureForField(form.fields[2]))}, - {UkmSuggestionFilledType::kFormSignatureName, - Collapse(CalculateFormSignature(form))}}}); - VerifyFormInteractionUkm( + VerifyUkm(test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName, + {{{UkmSuggestionFilledType::kRecordTypeName, + AutofillProfile::LOCAL_PROFILE}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmSuggestionFilledType::kIsForCreditCardName, false}, + {UkmSuggestionFilledType::kFieldSignatureName, + Collapse(CalculateFieldSignatureForField(form.fields[0]))}, + {UkmSuggestionFilledType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}}, + {{UkmSuggestionFilledType::kRecordTypeName, + AutofillProfile::LOCAL_PROFILE}, + {UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0}, + {UkmSuggestionFilledType::kFieldSignatureName, + Collapse(CalculateFieldSignatureForField(form.fields[2]))}, + {UkmSuggestionFilledType::kFormSignatureName, + Collapse(CalculateFormSignature(form))}}}); + VerifyUkm( test_ukm_recorder_, form, UkmTextFieldDidChangeType::kEntryName, {{{UkmTextFieldDidChangeType::kFieldTypeGroupName, NAME}, {UkmTextFieldDidChangeType::kHeuristicTypeName, NAME_FULL}, @@ -8010,13 +8087,12 @@ TEST_F(AutofillMetricsTest, NonsecureCreditCardForm) { SubmissionSource::FORM_SUBMISSION); histograms.ExpectBucketCount( "Autofill.FormEvents.CreditCard.OnNonsecurePage", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); - histograms.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); histograms.ExpectBucketCount( "Autofill.FormEvents.CreditCard.WithOnlyLocalData", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); } } @@ -8066,12 +8142,10 @@ TEST_F(AutofillMetricsTest, base::HistogramTester histograms; autofill_manager_->OnFormSubmitted(form, false, SubmissionSource::FORM_SUBMISSION); - histograms.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); - histograms.ExpectBucketCount( - "Autofill.FormEvents.CreditCard", - AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); + histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1); + histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard", + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1); // Check that the nonsecure histogram was not recorded. ExpectBucketCount() // can't be used here because it expects the histogram to exist. EXPECT_EQ( @@ -8180,7 +8254,7 @@ TEST_F(AutofillMetricsTest, MAYBE_AutofillSuggestionShownTest) { // Simulate and Autofill query on credit card name field. autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, form.fields[0]); - VerifyFormInteractionUkm( + VerifyUkm( test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName, {{{UkmSuggestionsShownType::kMillisecondsSinceFormParsedName, 0}, {UkmSuggestionsShownType::kHeuristicTypeName, CREDIT_CARD_NAME_FULL}, @@ -8217,7 +8291,7 @@ TEST_F(AutofillMetricsTest, DynamicFormMetrics) { // Simulate seeing. base::HistogramTester histogram_tester; autofill_manager_->AddSeenForm(form, field_types, field_types); - std::string guid("00000000-0000-0000-0000-000000000001"); + std::string guid(kTestGuid); // Simulate checking whether to fill a dynamic form before the form was filled // initially. @@ -8233,39 +8307,33 @@ TEST_F(AutofillMetricsTest, DynamicFormMetrics) { // Simulate checking whether to fill a dynamic form after the form was filled // initially. autofill_manager_->ShouldTriggerRefill(form_structure); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL, 0); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, + 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DID_DYNAMIC_REFILL, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0); // Trigger a refill, the refill metric should be updated. autofill_manager_->TriggerRefill(form); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, + 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DID_DYNAMIC_REFILL, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0); // Trigger a check to see whether a refill should happen. The autofill_manager_->ShouldTriggerRefill(form_structure); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, 2); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL, 1); - histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.Address", - AutofillMetrics::FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, + 2); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DID_DYNAMIC_REFILL, 1); + histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address", + FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 1); } // Tests that the LogUserHappinessBySecurityLevel are recorded correctly. @@ -8433,8 +8501,7 @@ TEST_F(AutofillMetricsTest, AutofillMetrics::LogSaveCardPromptMetric( AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, /*is_uploading=*/true, /*is_reshow=*/false, - /*is_requesting_cardholder_name=*/false, - /*is_requesting_expiration_date=*/false, + AutofillClient::SaveCreditCardOptions(), /*previous_save_credit_card_prompt_user_decision=*/1, security_state::SecurityLevel::EV_SECURE, SyncSigninState::kSignedOut); histogram_tester.ExpectBucketCount( @@ -8446,8 +8513,7 @@ TEST_F(AutofillMetricsTest, base::HistogramTester histogram_tester; AutofillMetrics::LogSaveCardPromptMetric( AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, /*is_uploading=*/false, - /*is_reshow=*/true, /*is_requesting_cardholder_name=*/false, - /*is_requesting_expiration_date=*/false, + /*is_reshow=*/true, AutofillClient::SaveCreditCardOptions(), /*previous_save_credit_card_prompt_user_decision=*/0, security_state::SecurityLevel::SECURE, SyncSigninState::kSignedOut); histogram_tester.ExpectBucketCount( @@ -8499,25 +8565,32 @@ TEST_F(AutofillMetricsTest, LogNumberOfAutocompleteEntriesCleanedUp) { // Verify that we correctly log FormEvent metrics with the appropriate sync // state. TEST_F(AutofillMetricsTest, FormEventMetrics_BySyncState) { + FormData form; + FormStructure form_structure(form); + std::vector<FormData> forms(1, form); + autofill_manager_->OnFormsSeen(forms, TimeTicks::Now()); + autofill_manager_->Reset(); + { base::HistogramTester histogram_tester; - AutofillMetrics::FormEventLogger logger( - /*is_for_credit_card=*/true, /*is_in_main_frame=*/false, + AddressFormEventLogger logger( + /*is_in_main_frame=*/true, /*form_interactions_ukm_logger=*/nullptr); - logger.OnDidSeeFillableDynamicForm(AutofillSyncSigninState::kSignedOut); + logger.OnDidSeeFillableDynamicForm(AutofillSyncSigninState::kSignedOut, + form_structure); histogram_tester.ExpectBucketCount( - "Autofill.FormEvents.CreditCard.WithNoData.SignedOut", - AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, 1); + "Autofill.FormEvents.Address.WithNoData.SignedOut", + FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, 1); } { base::HistogramTester histogram_tester; - AutofillMetrics::FormEventLogger logger( - /*is_for_credit_card=*/false, /*is_in_main_frame=*/true, + AddressFormEventLogger logger( + /*is_in_main_frame=*/true, /*form_interactions_ukm_logger=*/nullptr); - logger.OnDidRefill(AutofillSyncSigninState::kSignedIn); + logger.OnDidRefill(AutofillSyncSigninState::kSignedIn, form_structure); histogram_tester.ExpectBucketCount( "Autofill.FormEvents.Address.WithNoData.SignedIn", - AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL, 1); + FORM_EVENT_DID_DYNAMIC_REFILL, 1); } } @@ -8552,8 +8625,7 @@ TEST_F(AutofillMetricsTest, LogSaveCardPromptMetric_BySyncState) { AutofillMetrics::LogSaveCardPromptMetric( AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, /*is_uploading=*/true, /*is_reshow=*/false, - /*is_requesting_cardholder_name=*/false, - /*is_requesting_expiration_date_from_user=*/false, + AutofillClient::SaveCreditCardOptions(), /*previous_save_credit_card_prompt_user_decision=*/1, security_state::SecurityLevel::EV_SECURE, SyncSigninState::kSignedIn); histogram_tester.ExpectBucketCount( @@ -8564,8 +8636,7 @@ TEST_F(AutofillMetricsTest, LogSaveCardPromptMetric_BySyncState) { base::HistogramTester histogram_tester; AutofillMetrics::LogSaveCardPromptMetric( AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, /*is_uploading=*/false, - /*is_reshow=*/true, /*is_requesting_cardholder_name=*/false, - /*is_requesting_expiration_date_from_user=*/false, + /*is_reshow=*/true, AutofillClient::SaveCreditCardOptions(), /*previous_save_credit_card_prompt_user_decision=*/0, security_state::SecurityLevel::SECURE, SyncSigninState::kSignedInAndSyncFeature); diff --git a/chromium/components/autofill/core/browser/autofill_profile.cc b/chromium/components/autofill/core/browser/autofill_profile.cc index 750b4bb9b34..dd8c59b8f7a 100644 --- a/chromium/components/autofill/core/browser/autofill_profile.cc +++ b/chromium/components/autofill/core/browser/autofill_profile.cc @@ -337,8 +337,7 @@ void AutofillProfile::GetMatchingTypesAndValidities( const base::string16& text, const std::string& app_locale, ServerFieldTypeSet* matching_types, - std::map<ServerFieldType, AutofillProfile::ValidityState>* - matching_types_validities) const { + ServerFieldTypeValidityStateMap* matching_types_validities) const { if (!matching_types && !matching_types_validities) return; @@ -828,6 +827,38 @@ void AutofillProfile::RecordAndLogUse() { RecordUse(); } +bool AutofillProfile::HasGreaterFrescocencyThan( + const AutofillProfile* other, + base::Time comparison_time, + bool use_client_validation, + bool use_server_validation) const { + bool is_valid = (!use_client_validation || IsValidByClient()) && + (!use_server_validation || IsValidByServer()); + bool other_is_valid = (!use_client_validation || other->IsValidByClient()) && + (!use_server_validation || other->IsValidByServer()); + if (is_valid == other_is_valid) + return HasGreaterFrecencyThan(other, comparison_time); + if (is_valid && !other_is_valid) + return true; + return false; +} + +bool AutofillProfile::IsValidByClient() const { + for (auto const& it : client_validity_states_) { + if (it.second == INVALID) + return false; + } + return true; +} + +bool AutofillProfile::IsValidByServer() const { + for (auto const& it : server_validity_states_) { + if (it.second == INVALID) + return false; + } + return true; +} + bool AutofillProfile::IsAnInvalidPhoneNumber(ServerFieldType type) const { if (GetValidityState(type, SERVER) == VALID || (type != PHONE_HOME_WHOLE_NUMBER && type != PHONE_HOME_NUMBER && @@ -860,7 +891,7 @@ bool AutofillProfile::IsAnInvalidPhoneNumber(ServerFieldType type) const { return false; } -AutofillProfile::ValidityState AutofillProfile::GetValidityState( +AutofillDataModel::ValidityState AutofillProfile::GetValidityState( ServerFieldType type, ValidationSource validation_source) const { if (validation_source == CLIENT) { @@ -917,7 +948,6 @@ int AutofillProfile::GetClientValidityBitfieldValue() const { int validity_value = 0; size_t field_type_shift = 0; for (ServerFieldType supported_type : kSupportedTypesByClientForValidation) { - DCHECK(GetValidityState(supported_type, CLIENT) != UNSUPPORTED); validity_value |= GetValidityState(supported_type, CLIENT) << field_type_shift; field_type_shift += kValidityBitsPerType; @@ -952,6 +982,29 @@ void AutofillProfile::SetClientValidityFromBitfieldValue( } } +bool AutofillProfile::ShouldSkipFillingOrSuggesting( + ServerFieldType type) const { + if (base::FeatureList::IsEnabled( + autofill::features::kAutofillProfileServerValidation) && + GetValidityState(type, AutofillProfile::SERVER) == + AutofillProfile::INVALID) { + return true; + } + + // We are making an exception and skipping the validation check for address + // fields when the country is empty. + if (base::FeatureList::IsEnabled( + autofill::features::kAutofillProfileClientValidation) && + GetValidityState(type, AutofillProfile::CLIENT) == + AutofillProfile::INVALID && + (GroupTypeOfServerFieldType(type) != ADDRESS_HOME || + !GetRawInfo(ADDRESS_HOME_COUNTRY).empty())) { + return true; + } + + return false; +} + base::string16 AutofillProfile::GetInfoImpl( const AutofillType& type, const std::string& app_locale) const { diff --git a/chromium/components/autofill/core/browser/autofill_profile.h b/chromium/components/autofill/core/browser/autofill_profile.h index 3d051f90202..bf1c5494762 100644 --- a/chromium/components/autofill/core/browser/autofill_profile.h +++ b/chromium/components/autofill/core/browser/autofill_profile.h @@ -9,6 +9,7 @@ #include <iosfwd> #include <list> +#include <map> #include <string> #include <vector> @@ -40,26 +41,6 @@ class AutofillProfile : public AutofillDataModel { SERVER_PROFILE, }; - enum ValidityState { - // The field has not been validated. - UNVALIDATED = 0, - // The field is empty. - EMPTY = 1, - // The field is valid. - VALID = 2, - // The field is invalid. - INVALID = 3, - // The validation for the field is unsupported. - UNSUPPORTED = 4, - }; - - enum ValidationSource { - // The validity state is according to the client validation. - CLIENT = 0, - // The validity state is according to the server validation. - SERVER = 1, - }; - AutofillProfile(const std::string& guid, const std::string& origin); // Server profile constructor. The type must be SERVER_PROFILE (this serves @@ -224,6 +205,24 @@ class AutofillProfile : public AutofillDataModel { // use and updates |previous_use_date_| to the last value of |use_date_|. void RecordAndLogUse(); + // Returns true if the current profile has greater frescocency than the + // |other|. Frescocency is a combination of validation score and frecency to + // determine the relevance of the profile. Frescocency is a total order: it + // puts all the valid profiles before the invalid ones, and uses frecency + // (another total order) in case of tie. Please see + // AutofillDataModel::HasGreaterFrecencyThan. + bool HasGreaterFrescocencyThan(const AutofillProfile* other, + base::Time comparison_time, + bool use_client_validation, + bool use_server_validation) const; + + // Returns false if the profile has any invalid field, according to the client + // source of validation. + bool IsValidByClient() const; + // Returns false if the profile has any invalid field, according to the server + // source of validation. + bool IsValidByServer() const; + const base::Time& previous_use_date() const { return previous_use_date_; } void set_previous_use_date(const base::Time& time) { previous_use_date_ = time; @@ -235,7 +234,7 @@ class AutofillProfile : public AutofillDataModel { // Returns the validity state of the specified autofill type. ValidityState GetValidityState(ServerFieldType type, - ValidationSource source) const; + ValidationSource source) const override; // Sets the validity state of the specified autofill type. // This should only be called from autofill profile validtion API or in tests. @@ -275,6 +274,10 @@ class AutofillProfile : public AutofillDataModel { is_client_validity_states_updated_ = is_client_validity_states_updated; } + // Check for the validity of the data. Leave the field empty if the data is + // invalid and the relevant feature is enabled. + bool ShouldSkipFillingOrSuggesting(ServerFieldType type) const override; + base::WeakPtr<const AutofillProfile> GetWeakPtr() const { return weak_ptr_factory_.GetWeakPtr(); } 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 f54c16134a2..0d6a67f24a8 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc @@ -5,10 +5,14 @@ #include "components/autofill/core/browser/autofill_profile_sync_util.h" #include "base/guid.h" +// TODO(crbug.com/904390): Remove when the investigation is over. +#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_data_util.h" #include "components/autofill/core/browser/autofill_profile.h" +// TODO(crbug.com/904390): Remove when the investigation is over. +#include "components/autofill/core/browser/autofill_profile_comparator.h" #include "components/autofill/core/browser/country_names.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/proto/autofill_sync.pb.h" @@ -54,72 +58,40 @@ std::unique_ptr<EntityData> CreateEntityDataFromAutofillProfile( entry.is_client_validity_states_updated()); // Set repeated fields. - if (entry.HasRawInfo(NAME_FIRST)) { - specifics->add_name_first( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FIRST)))); - } - if (entry.HasRawInfo(NAME_MIDDLE)) { - specifics->add_name_middle( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_MIDDLE)))); - } - if (entry.HasRawInfo(NAME_LAST)) { - specifics->add_name_last( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_LAST)))); - } - if (entry.HasRawInfo(NAME_FULL)) { - specifics->add_name_full( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FULL)))); - } - if (entry.HasRawInfo(EMAIL_ADDRESS)) { - specifics->add_email_address( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(EMAIL_ADDRESS)))); - } - if (entry.HasRawInfo(PHONE_HOME_WHOLE_NUMBER)) { - specifics->add_phone_home_whole_number( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)))); - } + specifics->add_name_first( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FIRST)))); + specifics->add_name_middle( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_MIDDLE)))); + specifics->add_name_last( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_LAST)))); + specifics->add_name_full( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(NAME_FULL)))); + specifics->add_email_address( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(EMAIL_ADDRESS)))); + specifics->add_phone_home_whole_number( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)))); // Set simple single-valued fields. - if (entry.HasRawInfo(COMPANY_NAME)) { - specifics->set_company_name( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(COMPANY_NAME)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_CITY)) { - specifics->set_address_home_city( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_CITY)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_STATE)) { - specifics->set_address_home_state( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STATE)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_ZIP)) { - specifics->set_address_home_zip( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_ZIP)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_SORTING_CODE)) { - specifics->set_address_home_sorting_code( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_SORTING_CODE)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)) { - specifics->set_address_home_dependent_locality(TruncateUTF8( - UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_COUNTRY)) { - specifics->set_address_home_country( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_COUNTRY)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_STREET_ADDRESS)) { - specifics->set_address_home_street_address(TruncateUTF8( - UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_LINE1)) { - specifics->set_address_home_line1( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE1)))); - } - if (entry.HasRawInfo(ADDRESS_HOME_LINE2)) { - specifics->set_address_home_line2( - TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE2)))); - } + specifics->set_company_name( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(COMPANY_NAME)))); + specifics->set_address_home_city( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_CITY)))); + specifics->set_address_home_state( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STATE)))); + specifics->set_address_home_zip( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_ZIP)))); + specifics->set_address_home_sorting_code( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_SORTING_CODE)))); + specifics->set_address_home_dependent_locality(TruncateUTF8( + UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)))); + specifics->set_address_home_country( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_COUNTRY)))); + specifics->set_address_home_street_address( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)))); + specifics->set_address_home_line1( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE1)))); + specifics->set_address_home_line2( + TruncateUTF8(UTF16ToUTF8(entry.GetRawInfo(ADDRESS_HOME_LINE2)))); return entity_data; } @@ -141,78 +113,65 @@ std::unique_ptr<AutofillProfile> CreateAutofillProfileFromSpecifics( specifics.validity_state_bitfield()); // Set repeated fields. - if (specifics.name_first_size() > 0) { - profile->SetRawInfo(NAME_FIRST, UTF8ToUTF16(specifics.name_first(0))); - } - if (specifics.name_middle_size() > 0) { - profile->SetRawInfo(NAME_MIDDLE, UTF8ToUTF16(specifics.name_middle(0))); - } - if (specifics.name_last_size() > 0) { - profile->SetRawInfo(NAME_LAST, UTF8ToUTF16(specifics.name_last(0))); - } + profile->SetRawInfo(NAME_FIRST, UTF8ToUTF16(specifics.name_first_size() + ? specifics.name_first(0) + : std::string())); + profile->SetRawInfo(NAME_MIDDLE, UTF8ToUTF16(specifics.name_middle_size() + ? specifics.name_middle(0) + : std::string())); + profile->SetRawInfo( + NAME_LAST, UTF8ToUTF16(specifics.name_last_size() ? specifics.name_last(0) + : std::string())); + profile->SetRawInfo( + EMAIL_ADDRESS, + UTF8ToUTF16(specifics.email_address_size() ? specifics.email_address(0) + : std::string())); + profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, + UTF8ToUTF16(specifics.phone_home_whole_number_size() + ? specifics.phone_home_whole_number(0) + : std::string())); + + // Older versions don't have a separate full name; don't overwrite full name + // in this case. if (specifics.name_full_size() > 0) { profile->SetRawInfo(NAME_FULL, UTF8ToUTF16(specifics.name_full(0))); } - if (specifics.email_address_size() > 0) { - profile->SetRawInfo(EMAIL_ADDRESS, UTF8ToUTF16(specifics.email_address(0))); - } - if (specifics.phone_home_whole_number_size() > 0) { - profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, - UTF8ToUTF16(specifics.phone_home_whole_number(0))); - } // Set simple single-valued fields. - if (specifics.has_company_name()) { - profile->SetRawInfo(COMPANY_NAME, UTF8ToUTF16(specifics.company_name())); - } - if (specifics.has_address_home_city()) { - profile->SetRawInfo(ADDRESS_HOME_CITY, - UTF8ToUTF16(specifics.address_home_city())); - } - if (specifics.has_address_home_state()) { - profile->SetRawInfo(ADDRESS_HOME_STATE, - UTF8ToUTF16(specifics.address_home_state())); - } - if (specifics.has_address_home_zip()) { - profile->SetRawInfo(ADDRESS_HOME_ZIP, - UTF8ToUTF16(specifics.address_home_zip())); - } - if (specifics.has_address_home_sorting_code()) { - profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, - UTF8ToUTF16(specifics.address_home_sorting_code())); - } - if (specifics.has_address_home_dependent_locality()) { - profile->SetRawInfo( - ADDRESS_HOME_DEPENDENT_LOCALITY, - UTF8ToUTF16(specifics.address_home_dependent_locality())); - } - if (specifics.has_address_home_country()) { - // Update the country field, which can contain either a country code (if set - // by a newer version of Chrome), or a country name (if set by an older - // version of Chrome). - // TODO(jkrcal): Move this migration logic into Address::SetRawInfo()? - base::string16 country_name_or_code = - base::ASCIIToUTF16(specifics.address_home_country()); - std::string country_code = - CountryNames::GetInstance()->GetCountryCode(country_name_or_code); - profile->SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16(country_code)); - } - if (specifics.has_address_home_line1()) { + profile->SetRawInfo(COMPANY_NAME, UTF8ToUTF16(specifics.company_name())); + profile->SetRawInfo(ADDRESS_HOME_CITY, + UTF8ToUTF16(specifics.address_home_city())); + profile->SetRawInfo(ADDRESS_HOME_STATE, + UTF8ToUTF16(specifics.address_home_state())); + profile->SetRawInfo(ADDRESS_HOME_ZIP, + UTF8ToUTF16(specifics.address_home_zip())); + profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, + UTF8ToUTF16(specifics.address_home_sorting_code())); + profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + UTF8ToUTF16(specifics.address_home_dependent_locality())); + + // Update the country field, which can contain either a country code (if set + // by a newer version of Chrome), or a country name (if set by an older + // version of Chrome). + // TODO(jkrcal): Move this migration logic into Address::SetRawInfo()? + base::string16 country_name_or_code = + base::ASCIIToUTF16(specifics.address_home_country()); + std::string country_code = + CountryNames::GetInstance()->GetCountryCode(country_name_or_code); + profile->SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16(country_code)); + + // Set either the deprecated subparts (line1 & line2) or the full address + // (street_address) if it is present. This is needed because all the address + // fields are backed by the same storage. + if (specifics.has_address_home_street_address()) { + profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, + UTF8ToUTF16(specifics.address_home_street_address())); + } else { profile->SetRawInfo(ADDRESS_HOME_LINE1, UTF8ToUTF16(specifics.address_home_line1())); - } - if (specifics.has_address_home_line2()) { profile->SetRawInfo(ADDRESS_HOME_LINE2, UTF8ToUTF16(specifics.address_home_line2())); } - // Set first the deprecated subparts (line1 & line2) and only after that the - // full address (street_address) so that the latter wins in case of conflict. - // This is needed because all the address fields are backed by the same - // storage. - if (specifics.has_address_home_street_address()) { - profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, - UTF8ToUTF16(specifics.address_home_street_address())); - } // This has to be the last one, otherwise setting the raw info may change it. profile->set_is_client_validity_states_updated( @@ -235,4 +194,28 @@ std::string GetStorageKeyFromAutofillProfileSpecifics( return specifics.guid(); } +bool IsLocalProfileEqualToServerProfile( + const std::vector<std::unique_ptr<AutofillProfile>>& server_profiles, + const AutofillProfile& local_profile, + const std::string& app_locale) { + AutofillProfileComparator comparator(app_locale); + for (const auto& server_profile : server_profiles) { + // The same logic as when deciding whether to convert into a new profile in + // PersonalDataManager::MergeServerAddressesIntoProfiles. + if (comparator.AreMergeable(*server_profile, local_profile) && + (!local_profile.IsVerified() || !server_profile->IsVerified())) { + return true; + } + } + return false; +} + +void ReportAutofillProfileAddOrUpdateOrigin( + AutofillProfileSyncChangeOrigin origin) { + UMA_HISTOGRAM_ENUMERATION("Sync.AutofillProfile.AddOrUpdateOrigin", origin); +} +void ReportAutofillProfileDeleteOrigin(AutofillProfileSyncChangeOrigin origin) { + UMA_HISTOGRAM_ENUMERATION("Sync.AutofillProfile.DeleteOrigin", origin); +} + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_profile_sync_util.h b/chromium/components/autofill/core/browser/autofill_profile_sync_util.h index a43595262bf..87d677a7155 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_sync_util.h +++ b/chromium/components/autofill/core/browser/autofill_profile_sync_util.h @@ -7,6 +7,8 @@ #include <memory> #include <string> +// TODO(crbug.com/904390): Remove when the investigation is over. +#include <vector> namespace syncer { struct EntityData; @@ -40,6 +42,24 @@ std::string GetStorageKeyFromAutofillProfile(const AutofillProfile& entry); std::string GetStorageKeyFromAutofillProfileSpecifics( const sync_pb::AutofillProfileSpecifics& specifics); +// TODO(crbug.com/904390): Remove when the investigation is over. +bool IsLocalProfileEqualToServerProfile( + const std::vector<std::unique_ptr<AutofillProfile>>& server_profiles, + const AutofillProfile& local_profile, + const std::string& app_locale); + +// TODO(crbug.com/904390): Remove when the investigation is over. +enum class AutofillProfileSyncChangeOrigin { + kTrulyLocal = 0, + kConvertedLocal = 1, + kIncrementalRemote = 2, + kInitial = 3, + kMaxValue = kInitial, +}; +void ReportAutofillProfileAddOrUpdateOrigin( + AutofillProfileSyncChangeOrigin origin); +void ReportAutofillProfileDeleteOrigin(AutofillProfileSyncChangeOrigin origin); + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_SYNC_UTIL_H_ diff --git a/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc index b9677d58b27..3925a7ee402 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc @@ -133,7 +133,7 @@ TEST_F(AutofillProfileSyncUtilTest, CreateEntityDataFromAutofillProfile) { entity_data->specifics.autofill_profile().SerializeAsString()); } -// Test that fields not set for the input are also not set on the output. +// Test that fields not set for the input are empty in the output. TEST_F(AutofillProfileSyncUtilTest, CreateEntityDataFromAutofillProfile_Empty) { AutofillProfile profile(kGuid, std::string()); ASSERT_FALSE(profile.HasRawInfo(NAME_FULL)); @@ -141,8 +141,10 @@ TEST_F(AutofillProfileSyncUtilTest, CreateEntityDataFromAutofillProfile_Empty) { std::unique_ptr<EntityData> entity_data = CreateEntityDataFromAutofillProfile(profile); - EXPECT_EQ(0, entity_data->specifics.autofill_profile().name_full_size()); - EXPECT_FALSE(entity_data->specifics.autofill_profile().has_company_name()); + EXPECT_EQ(1, entity_data->specifics.autofill_profile().name_full_size()); + EXPECT_EQ("", entity_data->specifics.autofill_profile().name_full(0)); + EXPECT_TRUE(entity_data->specifics.autofill_profile().has_company_name()); + EXPECT_EQ("", entity_data->specifics.autofill_profile().company_name()); } // Test that long fields get trimmed. diff --git a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc index 2a045233d55..539a255e776 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc @@ -15,12 +15,14 @@ #include "base/strings/string16.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_metadata.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/form_field_data.h" #include "testing/gtest/include/gtest/gtest.h" @@ -306,25 +308,21 @@ TEST(AutofillProfileTest, CreateInferredLabelsI18n_FR) { "antoine@exemple.com", "Exemple Inc", "8 Rue de Londres", "", "Paris", "", "75009", "FR", "+33 (0) 1 42 68 53 00"); profiles.back()->set_language_code("fr_FR"); - profiles.back()->SetInfo( - AutofillType(ADDRESS_HOME_SORTING_CODE), UTF8ToUTF16("CEDEX"), "en-US"); static const char* kExpectedLabels[] = { "", "Antoine de Saint-Exupéry", "Antoine de Saint-Exupéry, 8 Rue de Londres", "Antoine de Saint-Exupéry, 8 Rue de Londres, Paris", "Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris", - "Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris CEDEX", - "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris " - "CEDEX", - "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris " - "CEDEX, France", - "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris " - "CEDEX, France, antoine@exemple.com", - "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris " - "CEDEX, France, antoine@exemple.com, +33 (0) 1 42 68 53 00", - "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris " - "CEDEX, France, antoine@exemple.com, +33 (0) 1 42 68 53 00", + "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris", + "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris, " + "France", + "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris, " + "France, antoine@exemple.com", + "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris, " + "France, antoine@exemple.com, +33 (0) 1 42 68 53 00", + "Exemple Inc, Antoine de Saint-Exupéry, 8 Rue de Londres, 75009 Paris, " + "France, antoine@exemple.com, +33 (0) 1 42 68 53 00", }; std::vector<base::string16> labels; @@ -1058,7 +1056,7 @@ TEST(AutofillProfileTest, AutofillProfile b = a; b.SetRawInfo(NAME_FIRST, UTF8ToUTF16("Märion")); b.SetRawInfo(NAME_MIDDLE, UTF8ToUTF16("Mitchéll")); - b.SetRawInfo(NAME_LAST,UTF8ToUTF16("Morrison")); + b.SetRawInfo(NAME_LAST, UTF8ToUTF16("Morrison")); b.SetRawInfo(NAME_FULL, UTF8ToUTF16("")); EXPECT_TRUE(a.SaveAdditionalInfo(b, "en-US")); @@ -1130,7 +1128,8 @@ TEST(AutofillProfileTest, IsAnInvalidPhoneNumber) { { AutofillProfile profile; profile.SetValidityState(PHONE_HOME_CITY_AND_NUMBER, - AutofillProfile::INVALID, AutofillProfile::CLIENT); + AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // It's based on the server side validation. EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(ADDRESS_HOME_LINE1)); @@ -1144,8 +1143,8 @@ TEST(AutofillProfileTest, IsAnInvalidPhoneNumber) { { AutofillProfile profile; - profile.SetValidityState(PHONE_HOME_CITY_CODE, AutofillProfile::INVALID, - AutofillProfile::SERVER); + profile.SetValidityState(PHONE_HOME_CITY_CODE, AutofillDataModel::INVALID, + AutofillDataModel::SERVER); EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(ADDRESS_HOME_LINE2)); EXPECT_EQ(true, profile.IsAnInvalidPhoneNumber(PHONE_HOME_NUMBER)); @@ -1157,7 +1156,8 @@ TEST(AutofillProfileTest, IsAnInvalidPhoneNumber) { { AutofillProfile profile; profile.SetValidityState(PHONE_BILLING_COUNTRY_CODE, - AutofillProfile::INVALID, AutofillProfile::SERVER); + AutofillDataModel::INVALID, + AutofillDataModel::SERVER); EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(ADDRESS_HOME_LINE2)); EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_HOME_NUMBER)); @@ -1167,8 +1167,8 @@ TEST(AutofillProfileTest, IsAnInvalidPhoneNumber) { } { AutofillProfile profile; - profile.SetValidityState(PHONE_BILLING_NUMBER, AutofillProfile::EMPTY, - AutofillProfile::SERVER); + profile.SetValidityState(PHONE_BILLING_NUMBER, AutofillDataModel::EMPTY, + AutofillDataModel::SERVER); EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_HOME_CITY_CODE)); EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_HOME_NUMBER)); @@ -1179,8 +1179,9 @@ TEST(AutofillProfileTest, IsAnInvalidPhoneNumber) { } { AutofillProfile profile; - profile.SetValidityState(PHONE_BILLING_WHOLE_NUMBER, AutofillProfile::VALID, - AutofillProfile::SERVER); + profile.SetValidityState(PHONE_BILLING_WHOLE_NUMBER, + AutofillDataModel::VALID, + AutofillDataModel::SERVER); EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_BILLING_COUNTRY_CODE)); @@ -1196,52 +1197,55 @@ TEST(AutofillProfileTest, ValidityStatesClients) { AutofillProfile profile; // The default validity state should be UNVALIDATED. - EXPECT_EQ( - AutofillProfile::UNVALIDATED, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // Make sure setting the validity state works. - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); - EXPECT_EQ(AutofillProfile::VALID, + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, ValidityStatesServer) { AutofillProfile profile; + EXPECT_TRUE(test::GetFullProfile().IsValidByServer()); // The default validity state should be UNVALIDATED. - EXPECT_EQ( - AutofillProfile::UNVALIDATED, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::SERVER)); + EXPECT_EQ(AutofillDataModel::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::SERVER)); // Make sure setting the validity state works. - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::SERVER); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::SERVER); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::SERVER); - EXPECT_EQ(AutofillProfile::VALID, + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID, + AutofillDataModel::SERVER); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID, + AutofillDataModel::SERVER); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY, + AutofillDataModel::SERVER); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::SERVER)); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::SERVER)); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::SERVER)); + AutofillDataModel::SERVER)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::SERVER)); + EXPECT_EQ( + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::SERVER)); + EXPECT_FALSE(profile.IsValidByServer()); } TEST(AutofillProfileTest, ValidityStates_ClientUnsupportedTypes) { @@ -1249,26 +1253,26 @@ TEST(AutofillProfileTest, ValidityStates_ClientUnsupportedTypes) { // The validity state of unsupported types should be UNSUPPORTED. EXPECT_EQ( - AutofillProfile::UNSUPPORTED, - profile.GetValidityState(ADDRESS_HOME_LINE1, AutofillProfile::CLIENT)); + AutofillDataModel::UNSUPPORTED, + profile.GetValidityState(ADDRESS_HOME_LINE1, AutofillDataModel::CLIENT)); // Make sure setting the validity state of an unsupported type does nothing. - profile.SetValidityState(ADDRESS_HOME_LINE1, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_LINE2, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_LINE1, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_LINE2, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); profile.SetValidityState(PHONE_HOME_CITY_AND_NUMBER, - AutofillProfile::UNVALIDATED, - AutofillProfile::AutofillProfile::CLIENT); - EXPECT_EQ(AutofillProfile::UNSUPPORTED, - profile.GetValidityState(ADDRESS_HOME_LINE1, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNSUPPORTED, - profile.GetValidityState(ADDRESS_HOME_LINE2, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNVALIDATED, + AutofillDataModel::UNVALIDATED, + AutofillDataModel::CLIENT); + EXPECT_EQ( + AutofillDataModel::UNSUPPORTED, + profile.GetValidityState(ADDRESS_HOME_LINE1, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::UNSUPPORTED, + profile.GetValidityState(ADDRESS_HOME_LINE2, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNVALIDATED, profile.GetValidityState(PHONE_HOME_CITY_AND_NUMBER, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Country) { @@ -1278,18 +1282,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Country) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); // 0b01 EXPECT_EQ(1, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); // 0b10 EXPECT_EQ(2, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b11 EXPECT_EQ(3, profile.GetClientValidityBitfieldValue()); } @@ -1301,18 +1305,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_State) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); // 0b0100 EXPECT_EQ(4, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); // 0b1000 EXPECT_EQ(8, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b1100 EXPECT_EQ(12, profile.GetClientValidityBitfieldValue()); } @@ -1324,18 +1328,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Zip) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); // 0b010000 EXPECT_EQ(16, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); // 0b100000 EXPECT_EQ(32, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b110000 EXPECT_EQ(48, profile.GetClientValidityBitfieldValue()); } @@ -1347,18 +1351,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_City) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); // 0b01000000 EXPECT_EQ(64, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); // 0b10000000 EXPECT_EQ(128, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b11000000 EXPECT_EQ(192, profile.GetClientValidityBitfieldValue()); } @@ -1371,20 +1375,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_DependentLocality) { EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + AutofillDataModel::EMPTY, AutofillDataModel::CLIENT); // 0b0100000000 EXPECT_EQ(256, profile.GetClientValidityBitfieldValue()); profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + AutofillDataModel::VALID, AutofillDataModel::CLIENT); // 0b1000000000 EXPECT_EQ(512, profile.GetClientValidityBitfieldValue()); profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b1100000000 EXPECT_EQ(768, profile.GetClientValidityBitfieldValue()); } @@ -1396,18 +1398,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Email) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); // 0b010000000000 EXPECT_EQ(1024, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); // 0b100000000000 EXPECT_EQ(2048, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b110000000000 EXPECT_EQ(3072, profile.GetClientValidityBitfieldValue()); } @@ -1419,18 +1421,18 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Phone) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); // 0b01000000000000 EXPECT_EQ(4096, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); // 0b10000000000000 EXPECT_EQ(8192, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); // 0b11000000000000 EXPECT_EQ(12288, profile.GetClientValidityBitfieldValue()); } @@ -1442,39 +1444,41 @@ TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Mixed) { // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::UNVALIDATED, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::UNVALIDATED, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); + AutofillDataModel::UNVALIDATED, + AutofillDataModel::CLIENT); + profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); + EXPECT_FALSE(profile.IsValidByClient()); // 0b01110011010010 EXPECT_EQ(7378, profile.GetClientValidityBitfieldValue()); - profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID, - AutofillProfile::AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::UNVALIDATED, - AutofillProfile::AutofillProfile::CLIENT); - profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID, - AutofillProfile::AutofillProfile::CLIENT); + AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); + profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::UNVALIDATED, + AutofillDataModel::CLIENT); + profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); + EXPECT_FALSE(profile.IsValidByClient()); // 0b11001110101101 EXPECT_EQ(13229, profile.GetClientValidityBitfieldValue()); } @@ -1485,24 +1489,28 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Country) { // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b01 profile.SetClientValidityFromBitfieldValue(1); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b10 profile.SetClientValidityFromBitfieldValue(2); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b11 profile.SetClientValidityFromBitfieldValue(3); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_State) { @@ -1511,24 +1519,28 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_State) { // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b0100 profile.SetClientValidityFromBitfieldValue(4); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b1000 profile.SetClientValidityFromBitfieldValue(8); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b1100 profile.SetClientValidityFromBitfieldValue(12); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Zip) { @@ -1537,24 +1549,28 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Zip) { // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b010000 profile.SetClientValidityFromBitfieldValue(16); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_ZIP, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b100000 profile.SetClientValidityFromBitfieldValue(32); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b110000 profile.SetClientValidityFromBitfieldValue(48); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_City) { @@ -1563,24 +1579,28 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_City) { // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b01000000 profile.SetClientValidityFromBitfieldValue(64); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b10000000 profile.SetClientValidityFromBitfieldValue(128); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b11000000 profile.SetClientValidityFromBitfieldValue(192); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, @@ -1590,24 +1610,28 @@ TEST(AutofillProfileTest, // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b0100000000 profile.SetClientValidityFromBitfieldValue(256); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b1000000000 profile.SetClientValidityFromBitfieldValue(512); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b1100000000 profile.SetClientValidityFromBitfieldValue(768); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Email) { @@ -1616,24 +1640,25 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Email) { // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b010000000000 profile.SetClientValidityFromBitfieldValue(1024); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(EMAIL_ADDRESS, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b100000000000 profile.SetClientValidityFromBitfieldValue(2048); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b110000000000 profile.SetClientValidityFromBitfieldValue(3072); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, - AutofillProfile::AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Phone) { @@ -1642,24 +1667,28 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Phone) { // By default all validity statuses should be set to UNVALIDATED, thus the // bitfield value should be empty. EXPECT_EQ(0, profile.GetClientValidityBitfieldValue()); + EXPECT_TRUE(profile.IsValidByClient()); // 0b01000000000000 profile.SetClientValidityFromBitfieldValue(4096); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b10000000000000 profile.SetClientValidityFromBitfieldValue(8192); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_TRUE(profile.IsValidByClient()); // 0b11000000000000 profile.SetClientValidityFromBitfieldValue(12288); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Mixed) { @@ -1671,51 +1700,52 @@ TEST(AutofillProfileTest, SetClientValidityFromBitfieldValue_Mixed) { // 0b01110011010010 profile.SetClientValidityFromBitfieldValue(7378); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNVALIDATED, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_ZIP, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNVALIDATED, + AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNVALIDATED, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + + EXPECT_FALSE(profile.IsValidByClient()); // 0b11001110101101 profile.SetClientValidityFromBitfieldValue(13229); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, + AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNVALIDATED, - profile.GetValidityState(EMAIL_ADDRESS, - AutofillProfile::AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNVALIDATED, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_FALSE(profile.IsValidByClient()); } TEST(AutofillProfileTest, GetMetadata) { @@ -1835,4 +1865,163 @@ TEST(AutofillProfileTest, EqualsForClientValidationPurpose) { EXPECT_TRUE(profile.EqualsForClientValidationPurpose(profile3)); } +// Tests that the skip decision is made correctly. +TEST(AutofillProfileTest, ShouldSkipFillingOrSuggesting) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileServerValidation, + features::kAutofillProfileClientValidation}, + /*disabled_features=*/{}); + + AutofillProfile profile = test::GetFullProfile(); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID, + AutofillProfile::SERVER); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID, + AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_LINE1, AutofillProfile::UNSUPPORTED, + AutofillProfile::CLIENT); + + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_CITY)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_STATE)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_COUNTRY)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_LINE1)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(EMAIL_ADDRESS)); + + profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::INVALID, + AutofillProfile::CLIENT); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, + AutofillProfile::SERVER); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, + AutofillProfile::CLIENT); + + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::ASCIIToUTF16("")); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_CITY)); + EXPECT_TRUE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_STATE)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_COUNTRY)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_LINE1)); + EXPECT_TRUE(profile.ShouldSkipFillingOrSuggesting(EMAIL_ADDRESS)); + + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::ASCIIToUTF16("CA")); + EXPECT_TRUE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_CITY)); + EXPECT_TRUE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_STATE)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_COUNTRY)); + EXPECT_FALSE(profile.ShouldSkipFillingOrSuggesting(ADDRESS_HOME_LINE1)); + EXPECT_TRUE(profile.ShouldSkipFillingOrSuggesting(EMAIL_ADDRESS)); +} + +enum Expectation { GREATER, LESS, EQUAL }; + +struct HasGreaterFrescocencyTestCase { + const AutofillDataModel::ValidityState client_validity_state_a; + const AutofillDataModel::ValidityState server_validity_state_a; + const AutofillDataModel::ValidityState client_validity_state_b; + const AutofillDataModel::ValidityState server_validity_state_b; + + const bool use_client_validation; + const bool use_server_validation; + Expectation expectation; +}; + +class HasGreaterFrescocencyTest + : public testing::TestWithParam<HasGreaterFrescocencyTestCase> {}; + +TEST_P(HasGreaterFrescocencyTest, HasGreaterFrescocency) { + auto test_case = GetParam(); + AutofillProfile profile_a("00000000-0000-0000-0000-000000000001", ""); + AutofillProfile profile_b("00000000-0000-0000-0000-000000000002", ""); + + profile_a.SetValidityState(EMAIL_ADDRESS, test_case.client_validity_state_a, + AutofillDataModel::CLIENT); + profile_a.SetValidityState(ADDRESS_HOME_ZIP, + test_case.server_validity_state_a, + AutofillDataModel::SERVER); + + profile_b.SetValidityState(ADDRESS_HOME_CITY, + test_case.client_validity_state_b, + AutofillDataModel::CLIENT); + profile_b.SetValidityState(PHONE_HOME_NUMBER, + test_case.server_validity_state_b, + AutofillDataModel::SERVER); + + base::Time now = base::Time::Now(); + + if (test_case.expectation == EQUAL) { + EXPECT_EQ(profile_a.HasGreaterFrecencyThan(&profile_b, now), + profile_a.HasGreaterFrescocencyThan( + &profile_b, now, test_case.use_client_validation, + test_case.use_server_validation)); + return; + } + + EXPECT_EQ(test_case.expectation == GREATER, + profile_a.HasGreaterFrescocencyThan( + &profile_b, now, test_case.use_client_validation, + test_case.use_server_validation)); + EXPECT_NE(test_case.expectation == GREATER, + profile_b.HasGreaterFrescocencyThan( + &profile_a, now, test_case.use_client_validation, + test_case.use_server_validation)); +} + +INSTANTIATE_TEST_SUITE_P( + AutofillProfileTest, + HasGreaterFrescocencyTest, + testing::Values( + HasGreaterFrescocencyTestCase{ + AutofillDataModel::VALID, AutofillDataModel::INVALID, + AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED, false, + false, EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::VALID, + AutofillDataModel::VALID, AutofillDataModel::INVALID, false, false, + EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::VALID, + AutofillDataModel::VALID, AutofillDataModel::INVALID, false, true, + GREATER}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::INVALID, + AutofillDataModel::VALID, AutofillDataModel::INVALID, false, true, + EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::VALID, + AutofillDataModel::VALID, AutofillDataModel::VALID, false, true, + EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::INVALID, + AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED, false, + true, LESS}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::VALID, + AutofillDataModel::VALID, AutofillDataModel::INVALID, true, true, + EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::INVALID, + AutofillDataModel::UNVALIDATED, AutofillDataModel::VALID, true, + true, LESS}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::VALID, AutofillDataModel::VALID, + AutofillDataModel::VALID, AutofillDataModel::VALID, true, true, + EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED, + AutofillDataModel::VALID, AutofillDataModel::INVALID, true, true, + GREATER}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::VALID, AutofillDataModel::INVALID, + AutofillDataModel::INVALID, AutofillDataModel::VALID, true, false, + GREATER}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::INVALID, AutofillDataModel::INVALID, + AutofillDataModel::UNVALIDATED, AutofillDataModel::VALID, true, + false, LESS}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::VALID, AutofillDataModel::INVALID, + AutofillDataModel::VALID, AutofillDataModel::VALID, true, false, + EQUAL}, + HasGreaterFrescocencyTestCase{ + AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED, + AutofillDataModel::INVALID, AutofillDataModel::INVALID, true, false, + GREATER})); + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc b/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc index 15b2d5926e4..8adf7430917 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_validation_util.cc @@ -41,33 +41,34 @@ using ::i18n::addressinput::MISMATCHING_VALUE; using ::i18n::addressinput::MISSING_REQUIRED_FIELD; using ::i18n::addressinput::UNEXPECTED_FIELD; using ::i18n::addressinput::UNKNOWN_VALUE; +using ::i18n::addressinput::UNSUPPORTED_FIELD; using ::i18n::phonenumbers::PhoneNumberUtil; const AddressField kFields[] = {COUNTRY, ADMIN_AREA, LOCALITY, DEPENDENT_LOCALITY, POSTAL_CODE}; -const AddressProblem kProblems[] = {UNEXPECTED_FIELD, MISSING_REQUIRED_FIELD, - UNKNOWN_VALUE, INVALID_FORMAT, - MISMATCHING_VALUE}; +const AddressProblem kProblems[] = {UNEXPECTED_FIELD, MISSING_REQUIRED_FIELD, + UNKNOWN_VALUE, INVALID_FORMAT, + MISMATCHING_VALUE, UNSUPPORTED_FIELD}; // If the |address_field| is valid, set the validity state of the // |address_field| in the |profile| to the |state| and return true. // Otherwise, return false. bool SetValidityStateForAddressField(const AutofillProfile* profile, AddressField address_field, - AutofillProfile::ValidityState state) { + AutofillDataModel::ValidityState state) { ServerFieldType server_field = i18n::TypeForField(address_field, /*billing=*/false); if (server_field == UNKNOWN_TYPE) return false; DCHECK(profile); - profile->SetValidityState(server_field, state, AutofillProfile::CLIENT); + profile->SetValidityState(server_field, state, AutofillDataModel::CLIENT); return true; } // Set the validity state of all address fields in the |profile| to |state|. void SetAllAddressValidityStates(const AutofillProfile* profile, - AutofillProfile::ValidityState state) { + AutofillDataModel::ValidityState state) { DCHECK(profile); for (auto field : kFields) SetValidityStateForAddressField(profile, field, state); @@ -110,54 +111,56 @@ void InitializeAddressFromProfile(const AutofillProfile& profile, void SetEmptyValidityIfEmpty(const AutofillProfile* profile) { if (profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty()) - profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY, - AutofillProfile::CLIENT); + profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); if (profile->GetRawInfo(ADDRESS_HOME_STATE).empty()) - profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY, - AutofillProfile::CLIENT); + profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); if (profile->GetRawInfo(ADDRESS_HOME_CITY).empty()) - profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::EMPTY, - AutofillProfile::CLIENT); + profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); if (profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY).empty()) profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::EMPTY, AutofillProfile::CLIENT); + AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); if (profile->GetRawInfo(ADDRESS_HOME_ZIP).empty()) - profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY, - AutofillProfile::CLIENT); + profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); } void SetInvalidIfUnvalidated(const AutofillProfile* profile) { if (profile->GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { - profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { + profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } - if (profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { - profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_STATE, + AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { + profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } - if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { - profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { + profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { + AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::INVALID, - AutofillProfile::CLIENT); + AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } - if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { - profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { + profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } } @@ -166,58 +169,62 @@ void MaybeApplyValidToFields(const AutofillProfile* profile) { // subregion can only be validated if its super-region is VALID. In this // case, it's VALID if it has not been marked as INVALID or EMPTY. - if (profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { - profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_STATE, + AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { + profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); } - if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED && - profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) == - AutofillProfile::VALID) { - profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED && + profile->GetValidityState(ADDRESS_HOME_STATE, + AutofillDataModel::CLIENT) == + AutofillDataModel::VALID) { + profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); } if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED && - profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) == - AutofillProfile::VALID) { + AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED && + profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) == + AutofillDataModel::VALID) { profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::VALID, AutofillProfile::CLIENT); + AutofillDataModel::VALID, + AutofillDataModel::CLIENT); } // ZIP only depends on COUNTRY. If it's not so far marked as INVALID or EMPTY, // then it's VALID. - if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT) == - AutofillProfile::UNVALIDATED) { - profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::VALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) == + AutofillDataModel::UNVALIDATED) { + profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID, + AutofillDataModel::CLIENT); } } void ApplyValidOnlyIfAllChildrenNotInvalid(const AutofillProfile* profile) { - if (profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) == - AutofillProfile::INVALID && - profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT) == - AutofillProfile::INVALID) { - profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_STATE, + AutofillDataModel::CLIENT) == + AutofillDataModel::INVALID && + profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) == + AutofillDataModel::INVALID) { + profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } - if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) == - AutofillProfile::INVALID) { - profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) == + AutofillDataModel::INVALID) { + profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT) == - AutofillProfile::INVALID) { - profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, - AutofillProfile::CLIENT); + AutofillDataModel::CLIENT) == + AutofillDataModel::INVALID) { + profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } } @@ -239,7 +246,7 @@ AddressValidator::Status ValidateAddress(const AutofillProfile* profile, DCHECK(address_validator); DCHECK(profile); - SetAllAddressValidityStates(profile, AutofillProfile::UNVALIDATED); + SetAllAddressValidityStates(profile, AutofillDataModel::UNVALIDATED); if (!base::ContainsValue( CountryDataMap::GetInstance()->country_codes(), @@ -247,13 +254,14 @@ AddressValidator::Status ValidateAddress(const AutofillProfile* profile, // If the country code is not in the database, the country code and the // profile are invalid, and other fields cannot be validated, because it is // unclear which, if any, rule should apply. - SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::INVALID); + SetValidityStateForAddressField(profile, COUNTRY, + AutofillDataModel::INVALID); SetEmptyValidityIfEmpty(profile); return AddressValidator::SUCCESS; } // The COUNTRY was already listed in the CountryDataMap, therefore it's valid. - SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::VALID); + SetValidityStateForAddressField(profile, COUNTRY, AutofillDataModel::VALID); AddressData address; InitializeAddressFromProfile(*profile, &address); @@ -262,9 +270,25 @@ AddressValidator::Status ValidateAddress(const AutofillProfile* profile, AddressValidator::Status status = address_validator->ValidateAddress(address, GetFilter(), &problems); - for (auto problem : problems) - SetValidityStateForAddressField(profile, problem.first, - AutofillProfile::INVALID); + // The address fields for which validation is not supported by the metadata + // will be marked as UNSUPPORTED_FIELDs. These fields should be treated like + // VALID fields to stay consistent. INVALID_FORMATs, MISMATCHING_VALUEs or + // UNKNOWN_VALUEs are INVALID. MISSING_REQUIRED_FIELD would be marked as EMPTY + // along other empty fields. UNEXPECTED_FIELD would mean that there is also no + // metadata for validation, therefore, they are also UNSUPPORTED_FIELDs, and + // thus they would be treated as VALID fields. + for (auto problem : problems) { + if (problem.second == UNSUPPORTED_FIELD) { + SetValidityStateForAddressField(profile, problem.first, + AutofillDataModel::VALID); + + } else if (problem.second == INVALID_FORMAT || + problem.second == MISMATCHING_VALUE || + problem.second == UNKNOWN_VALUE) { + SetValidityStateForAddressField(profile, problem.first, + AutofillDataModel::INVALID); + } + } SetEmptyValidityIfEmpty(profile); @@ -301,24 +325,24 @@ void ValidateAddressStrictly(const AutofillProfile* profile, void ValidateEmailAddress(const AutofillProfile* profile) { const base::string16& email = profile->GetRawInfo(EMAIL_ADDRESS); if (email.empty()) { - profile->SetValidityState(EMAIL_ADDRESS, AutofillProfile::EMPTY, - AutofillProfile::CLIENT); + profile->SetValidityState(EMAIL_ADDRESS, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); return; } profile->SetValidityState(EMAIL_ADDRESS, autofill::IsValidEmailAddress(email) - ? AutofillProfile::VALID - : AutofillProfile::INVALID, - AutofillProfile::CLIENT); + ? AutofillDataModel::VALID + : AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } void ValidatePhoneNumber(const AutofillProfile* profile) { const std::string& phone_number = base::UTF16ToUTF8(profile->GetRawInfo(PHONE_HOME_WHOLE_NUMBER)); if (phone_number.empty()) { - profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY, - AutofillProfile::CLIENT); + profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY, + AutofillDataModel::CLIENT); return; } @@ -329,8 +353,8 @@ void ValidatePhoneNumber(const AutofillProfile* profile) { // If the country code is not in the database, the phone number cannot be // validated. profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::UNVALIDATED, - AutofillProfile::CLIENT); + AutofillDataModel::UNVALIDATED, + AutofillDataModel::CLIENT); return; } @@ -338,9 +362,9 @@ void ValidatePhoneNumber(const AutofillProfile* profile) { profile->SetValidityState( PHONE_HOME_WHOLE_NUMBER, phone_util->IsPossibleNumberForString(phone_number, country_code) - ? AutofillProfile::VALID - : AutofillProfile::INVALID, - AutofillProfile::CLIENT); + ? AutofillDataModel::VALID + : AutofillDataModel::INVALID, + AutofillDataModel::CLIENT); } } // namespace profile_validation_util diff --git a/chromium/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc index 6b609ed9125..59a29b7a650 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc @@ -84,24 +84,24 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateFullValidProfileForCanada) { // Postal Code: "H3B 2T9", Country Code: "CA", AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // For Canada, there is no rule and data to validate the city. EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // Canada doesn't have a dependent locality. It's not filled, and yet the // profile is valid. - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -112,23 +112,23 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); ValidateAddressTest(&profile); - EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The zip, the state and the city can't be validated, because we don't know // the country, in the strict validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -138,23 +138,23 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("")); ValidateAddressTest(&profile); - EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The zip, the state and the city can't be validated, because we don't know // the country, in the strict validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -165,21 +165,21 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::UNVALIDATED, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::UNVALIDATED, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::UNVALIDATED, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::UNVALIDATED, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaNotExists) { @@ -188,23 +188,23 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaNotExists) { profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area_code)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // The city can't be validated, because we don't know the state, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyAdminArea) { @@ -212,23 +212,23 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyAdminArea) { profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // The city can't be validated, because we don't know the state, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaFullName) { @@ -237,21 +237,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaFullName) { profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaLowerCase) { @@ -260,21 +260,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaLowerCase) { profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -284,21 +284,21 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -313,21 +313,21 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_ValidZipNoSpace) { @@ -336,21 +336,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_ValidZipNoSpace) { profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_ValidZipLowerCase) { @@ -360,21 +360,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_ValidZipLowerCase) { profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_InvalidZip) { @@ -383,21 +383,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_InvalidZip) { profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyZip) { @@ -405,21 +405,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyZip) { profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyCity) { @@ -430,21 +430,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyCity) { profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateFullProfile_EmptyFields) { @@ -455,21 +455,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateFullProfile_EmptyFields) { profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateFullValidProfileForChina) { @@ -480,21 +480,21 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateFullValidProfileForChina) { AutofillProfile profile(autofill::test::GetFullValidProfileForChina()); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -504,25 +504,25 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(invalid_city)); ValidateAddressTest(&profile); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The city which is the only dependent field on state is invalid, in the // strict validation the state would also be considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // The dependent locality can't be validated, because we don't know the city, // in the strict validation this is considered as invalid. - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -535,25 +535,25 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(city)); ValidateAddressTest(&profile); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The city which is the only dependent field on state is invalid, in the // strict validation the state would also be considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // The dependent locality can't be validated, because we don't know the city, // in the strict validation this is considered as invalid. - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -568,21 +568,21 @@ TEST_F(AutofillProfileValidationUtilTest, base::UTF8ToUTF16(district)); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -593,21 +593,21 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, base::UTF8ToUTF16("")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -619,23 +619,23 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, base::UTF8ToUTF16("赫")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // The dependent locality which is the only dependent field on city is // invalid, in the strict validation the city would also be invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -648,23 +648,23 @@ TEST_F(AutofillProfileValidationUtilTest, base::UTF8ToUTF16("蒙城县")); ValidateAddressTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // The only that depend on city (dependent locality) is invalid, // in the strict validation city would also be considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_FullValidProfile) { @@ -672,18 +672,18 @@ TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_FullValidProfile) { // Country Code: "CA", Phone Number: "15141112233" AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_EmptyPhoneNumber) { AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16()); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -694,9 +694,9 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::UNVALIDATED, + EXPECT_EQ(AutofillDataModel::UNVALIDATED, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -708,103 +708,103 @@ TEST_F(AutofillProfileValidationUtilTest, profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16()); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_InvalidPhoneNumber) { AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("33")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("151411122334")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("1(514)111-22-334")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("251411122334")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("Hello!")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_ValidPhoneNumber) { AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("5141112233")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("514-111-2233")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("1(514)111-22-33")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("+1 514 111 22 33")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("+1 (514)-111-22-33")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("(514)-111-22-33")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("+1 650 GOO OGLE")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("778 111 22 33")); ValidatePhoneTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_FullValidProfile) { @@ -812,16 +812,16 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_FullValidProfile) { // Email: "alice@wonderland.ca" AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_EmptyEmailAddress) { AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(EMAIL_ADDRESS, base::string16()); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::EMPTY, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -829,24 +829,24 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Hello!")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice.wonderland")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@=wonderland.com")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_ValidEmailAddress) { @@ -854,40 +854,40 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_ValidEmailAddress) { profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@wonderland")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@wonderland.fiction")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice+cat@wonderland.fiction.book")); ValidateEmailTest(&profile); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, ValidateProfile_FullValidProfile) { // This is a full valid profile: AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); ValidateProfileTest(&profile); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -896,20 +896,26 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("ABC 123")); ValidateProfileTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -918,20 +924,26 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("33")); ValidateProfileTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -940,20 +952,26 @@ TEST_F(AutofillProfileValidationUtilTest, AutofillProfile profile(autofill::test::GetFullValidProfileForCanada()); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("fakeaddress")); ValidateProfileTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -968,33 +986,33 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateProfileTest(&profile); // The fields that depend on country (state and zip) are both invalid, // therefore in the strict validation this is considered as invalid. - EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The state is not a Chinese state, so it's considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // The city can't be validated, because the state value is not // valid, in the strict validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNSUPPORTED, + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNSUPPORTED, profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); // The zip is not a Chinese one, therefore it's invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); // Phone number is validated regardless of the country. - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -1010,35 +1028,35 @@ TEST_F(AutofillProfileValidationUtilTest, // The fields that depend on Country (state and zip) are both invalid, // therefore in the strict validation this is considered as invalid. - EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The state is not a Canadian state, so it's considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // We can't validate city, because state is not valid, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // The dependent locality is not a Canadian field, so it's considered as // invalid. - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNSUPPORTED, + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNSUPPORTED, profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); // The zip is not a Canadian one, therefore it's invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); // Phone number is validated regardless of the country. - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -1052,34 +1070,34 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateProfileTest(&profile); - EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); // The only field that depends on state (city) is invalid, in the strict // validation this makes state also invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // The city is in another province. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // The dependent locality can't be validated, because the city value is not // valid, in the strict validation this is considered as invalid. - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNSUPPORTED, + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNSUPPORTED, profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); // Phone number is validated regardless of the country. - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } TEST_F(AutofillProfileValidationUtilTest, @@ -1093,33 +1111,33 @@ TEST_F(AutofillProfileValidationUtilTest, ValidateProfileTest(&profile); + EXPECT_EQ(AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_COUNTRY, + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::EMPTY, - profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); + AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); // City can't be validated, because the state is missing, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillProfile::INVALID, - profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); + AutofillDataModel::INVALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // The dependent locality can't be validated, because we don't know the city, // in the strict validation this is considered as invalid. - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNSUPPORTED, + AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::UNSUPPORTED, profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, - profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); // Phone number is validated regardless of the country. - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } } // namespace autofill diff --git a/chromium/components/autofill/core/browser/autofill_profile_validator.cc b/chromium/components/autofill/core/browser/autofill_profile_validator.cc index 35d0a46aa30..6a2744fc227 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_validator.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_validator.cc @@ -14,7 +14,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" -#include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_profile_validation_util.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h" @@ -39,14 +38,13 @@ AutofillProfileValidator::ValidationRequest::ValidationRequest( base::WeakPtr<const AutofillProfile> profile, autofill::AddressValidator* validator, AutofillProfileValidatorCallback on_validated) - : profile_(profile), + : profile_(*profile), validator_(validator), on_validated_(std::move(on_validated)), has_responded_(false), weak_factory_(this) { on_timeout_.Reset(base::BindOnce(&ValidationRequest::OnRulesLoaded, weak_factory_.GetWeakPtr())); - DCHECK(profile_); base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, on_timeout_.callback(), base::TimeDelta::FromSeconds(kRulesLoadingTimeoutSeconds)); @@ -63,12 +61,8 @@ void AutofillProfileValidator::ValidationRequest::OnRulesLoaded() { return; has_responded_ = true; - if (!profile_) - return; - - profile_validation_util::ValidateProfile(profile_.get(), validator_); - - std::move(on_validated_).Run(profile_.get()); + profile_validation_util::ValidateProfile(&profile_, validator_); + std::move(on_validated_).Run(&profile_); } AutofillProfileValidator::AutofillProfileValidator( @@ -102,7 +96,7 @@ void AutofillProfileValidator::StartProfileValidation( // Start loading the rules for the region. If the rules were already in the // process of being loaded, this call will do nothing. - address_validator_.LoadRules(region_code); + LoadRulesForRegion(region_code); } } diff --git a/chromium/components/autofill/core/browser/autofill_profile_validator.h b/chromium/components/autofill/core/browser/autofill_profile_validator.h index 52d88a8d677..2253b4d4498 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_validator.h +++ b/chromium/components/autofill/core/browser/autofill_profile_validator.h @@ -14,14 +14,13 @@ #include "base/cancelable_callback.h" #include "base/macros.h" +#include "components/autofill/core/browser/autofill_profile.h" #include "third_party/libaddressinput/chromium/chrome_address_validator.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" namespace autofill { -class AutofillProfile; - using AutofillProfileValidatorCallback = base::OnceCallback<void(const AutofillProfile*)>; @@ -45,6 +44,13 @@ class AutofillProfileValidator : public autofill::LoadRulesListener { void StartProfileValidation(const AutofillProfile* profile, AutofillProfileValidatorCallback cb); + protected: + // Starts loading the rules for the specified |region_code|. + virtual void LoadRulesForRegion(const std::string& region_code); + + // The address validator used to load rules. + AddressValidator address_validator_; + private: // ValidationRequest loads Rules from the server and validates various fields // in an autofill profile. @@ -60,7 +66,7 @@ class AutofillProfileValidator : public autofill::LoadRulesListener { void OnRulesLoaded(); private: - base::WeakPtr<const AutofillProfile> profile_; + AutofillProfile profile_; // Not owned. Outlives this object. AddressValidator* validator_; @@ -78,9 +84,6 @@ class AutofillProfileValidator : public autofill::LoadRulesListener { // Returns whether the rules for the specified |region_code| is loaded. bool AreRulesLoadedForRegion(const std::string& region_code); - // Starts loading the rules for the specified |region_code|. - void LoadRulesForRegion(const std::string& region_code); - // Implementation of the LoadRulesListener interface. Called when the address // rules for the |region_code| have finished loading. void OnAddressValidationRulesLoaded(const std::string& region_code, @@ -90,9 +93,6 @@ class AutofillProfileValidator : public autofill::LoadRulesListener { std::map<std::string, std::vector<std::unique_ptr<ValidationRequest>>> pending_requests_; - // The address validator used to load rules. - AddressValidator address_validator_; - DISALLOW_COPY_AND_ASSIGN(AutofillProfileValidator); }; diff --git a/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc index 72a48f3fce4..34203afe788 100644 --- a/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc +++ b/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc @@ -87,7 +87,7 @@ class AutofillProfileValidatorTest : public testing::Test { for (auto expectation : expected_validity_) { EXPECT_EQ(expectation.second, profile->GetValidityState(expectation.first, - AutofillProfile::CLIENT)); + AutofillDataModel::CLIENT)); } } @@ -101,7 +101,7 @@ class AutofillProfileValidatorTest : public testing::Test { AutofillProfileValidatorCallback onvalidated_cb_; - std::vector<std::pair<ServerFieldType, AutofillProfile::ValidityState>> + std::vector<std::pair<ServerFieldType, AutofillDataModel::ValidityState>> expected_validity_; private: @@ -122,11 +122,14 @@ TEST_F(AutofillProfileValidatorTest, ValidateFullValidProfile_RulesNotLoaded) { EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -143,11 +146,11 @@ TEST_F(AutofillProfileValidatorTest, ValidateAddress_RulesLoaded) { EXPECT_EQ(true, AreRulesLoadedForRegion(country_code)); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -164,11 +167,12 @@ TEST_F(AutofillProfileValidatorTest, EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID}, - {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::INVALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::UNVALIDATED}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::UNVALIDATED}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -184,11 +188,11 @@ TEST_F(AutofillProfileValidatorTest, ValidateAddress_RuleNotExists) { EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED}, - {ADDRESS_HOME_ZIP, AutofillProfile::UNVALIDATED}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::UNVALIDATED}, + {ADDRESS_HOME_ZIP, AutofillDataModel::UNVALIDATED}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -203,11 +207,12 @@ TEST_F(AutofillProfileValidatorTest, ValidateAddress_EmptyCountryCode) { // Set up the test expectations. // The phone is validated for the US. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY}, - {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::INVALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::UNVALIDATED}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::UNVALIDATED}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -220,11 +225,14 @@ TEST_F(AutofillProfileValidatorTest, StartProfileValidation_InvalidPhone) { base::UTF8ToUTF16("Invalid Phone")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -236,11 +244,14 @@ TEST_F(AutofillProfileValidatorTest, StartProfileValidation_InvalidAddress) { profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -254,11 +265,14 @@ TEST_F(AutofillProfileValidatorTest, profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY}, - {EMAIL_ADDRESS, AutofillProfile::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -272,11 +286,14 @@ TEST_F(AutofillProfileValidatorTest, profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::INVALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -290,11 +307,14 @@ TEST_F(AutofillProfileValidatorTest, profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::INVALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::EMPTY}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::EMPTY}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -308,11 +328,14 @@ TEST_F(AutofillProfileValidatorTest, profile.SetRawInfo(ADDRESS_HOME_ZIP, base::string16()); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::EMPTY}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -327,11 +350,14 @@ TEST_F(AutofillProfileValidatorTest, base::UTF8ToUTF16("Invalid Phone")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID}, - {EMAIL_ADDRESS, AutofillProfile::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -343,11 +369,14 @@ TEST_F(AutofillProfileValidatorTest, StartProfileValidation_InvalidEmail) { profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::VALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID}, - {EMAIL_ADDRESS, AutofillProfile::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -363,11 +392,14 @@ TEST_F(AutofillProfileValidatorTest, profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID}, - {ADDRESS_HOME_STATE, AutofillProfile::INVALID}, - {ADDRESS_HOME_ZIP, AutofillProfile::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID}, - {EMAIL_ADDRESS, AutofillProfile::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); 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 f46ca53cf0c..22fc50b9595 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 @@ -28,7 +28,7 @@ namespace autofill { AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile( bool upload, - bool should_request_name_from_user, + AutofillClient::SaveCreditCardOptions options, const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, AutofillClient::UploadSaveCardPromptCallback @@ -38,7 +38,7 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile( bool is_off_the_record) : ConfirmInfoBarDelegate(), upload_(upload), - should_request_name_from_user_(should_request_name_from_user), + options_(options), upload_save_card_prompt_callback_( std::move(upload_save_card_prompt_callback)), local_save_card_prompt_callback_( @@ -59,7 +59,7 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile( /*escape_apostrophes=*/true)) { AutofillMetrics::LogCreditCardInfoBarMetric( AutofillMetrics::INFOBAR_NOT_SHOWN_INVALID_LEGAL_MESSAGE, upload_, - should_request_name_from_user_, + options_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState)); return; @@ -67,7 +67,7 @@ AutofillSaveCardInfoBarDelegateMobile::AutofillSaveCardInfoBarDelegateMobile( } AutofillMetrics::LogCreditCardInfoBarMetric( - AutofillMetrics::INFOBAR_SHOWN, upload_, should_request_name_from_user_, + AutofillMetrics::INFOBAR_SHOWN, upload_, options_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState)); } @@ -153,7 +153,10 @@ base::string16 AutofillSaveCardInfoBarDelegateMobile::GetButtonLabel( return base::string16(); } - return should_request_name_from_user_ + // Requesting name or expiration date from the user makes the save prompt a + // 2-step fix flow. + return options_.should_request_name_from_user || + options_.should_request_expiration_date_from_user ? l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_CONTINUE) : l10n_util::GetStringUTF16(IDS_AUTOFILL_SAVE_CARD_PROMPT_ACCEPT); } @@ -178,7 +181,7 @@ void AutofillSaveCardInfoBarDelegateMobile::LogUserAction( DCHECK(!had_user_interaction_); AutofillMetrics::LogCreditCardInfoBarMetric( - user_action, upload_, should_request_name_from_user_, + user_action, upload_, options_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState)); pref_service_->SetInteger( 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 ed98a20297b..a99817a0ec5 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 @@ -31,7 +31,7 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate { public: AutofillSaveCardInfoBarDelegateMobile( bool upload, - bool should_request_name_from_user, + AutofillClient::SaveCreditCardOptions options, const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, AutofillClient::UploadSaveCardPromptCallback @@ -84,8 +84,10 @@ class AutofillSaveCardInfoBarDelegateMobile : public ConfirmInfoBarDelegate { // Whether the action is an upload or a local save. bool upload_; - // Whether the user should enter/confirm cardholder name. - bool should_request_name_from_user_; + // If the cardholder name is missing, request the name from the user before + // saving the card. If the expiration date is missing, request the missing + // data from the user before saving the card. + AutofillClient::SaveCreditCardOptions options_; // The callback to run once the user makes a decision with respect to the // credit card upload offer-to-save prompt (if |upload_| is true). diff --git a/chromium/components/autofill/core/browser/autofill_scanner.h b/chromium/components/autofill/core/browser/autofill_scanner.h index 0babe38a2fd..a4826a522b2 100644 --- a/chromium/components/autofill/core/browser/autofill_scanner.h +++ b/chromium/components/autofill/core/browser/autofill_scanner.h @@ -46,7 +46,7 @@ class AutofillScanner { size_t SaveCursor(); // This is only for logging purposes. - size_t CursorIndex() { return static_cast<size_t>(cursor_ - begin_); }; + size_t CursorIndex() { return static_cast<size_t>(cursor_ - begin_); } private: void Init(const std::vector<AutofillField*>& fields); diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc index 9126d95ec29..ffab385a580 100644 --- a/chromium/components/autofill/core/browser/autofill_test_utils.cc +++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc @@ -587,7 +587,7 @@ void InitializePossibleTypesAndValidities( std::vector<ServerFieldTypeValidityStatesMap>& possible_field_types_validities, const std::vector<ServerFieldType>& possible_types, - const std::vector<AutofillProfile::ValidityState>& validity_states) { + const std::vector<AutofillDataModel::ValidityState>& validity_states) { possible_field_types.push_back(ServerFieldTypeSet()); possible_field_types_validities.push_back(ServerFieldTypeValidityStatesMap()); diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.h b/chromium/components/autofill/core/browser/autofill_test_utils.h index b67a11c3655..02eb5847a07 100644 --- a/chromium/components/autofill/core/browser/autofill_test_utils.h +++ b/chromium/components/autofill/core/browser/autofill_test_utils.h @@ -216,7 +216,7 @@ void InitializePossibleTypesAndValidities( std::vector<ServerFieldTypeValidityStatesMap>& possible_field_types_validities, const std::vector<ServerFieldType>& possible_type, - const std::vector<AutofillProfile::ValidityState>& validity_state = {}); + const std::vector<AutofillDataModel::ValidityState>& validity_state = {}); // Fills the upload |field| with the information passed by parameter. If the // value of a const char* parameter is NULL, the corresponding attribute won't diff --git a/chromium/components/autofill/core/browser/autofill_type.cc b/chromium/components/autofill/core/browser/autofill_type.cc index 3f2b48a3509..62bb3c04655 100644 --- a/chromium/components/autofill/core/browser/autofill_type.cc +++ b/chromium/components/autofill/core/browser/autofill_type.cc @@ -116,6 +116,7 @@ FieldTypeGroup GroupTypeOfServerFieldType(ServerFieldType field_type) { case USERNAME: return USERNAME_FIELD; + case PRICE: case SEARCH_TERM: return UNFILLABLE; @@ -774,6 +775,8 @@ std::string AutofillType::ServerFieldTypeToString(ServerFieldType type) { return "CONFIRMATION_PASSWORD"; case SEARCH_TERM: return "SEARCH_TERM"; + case PRICE: + return "PRICE"; case AMBIGUOUS_TYPE: return "AMBIGUOUS_TYPE"; 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 0459e25d4ff..7ad8b87e824 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 @@ -11,6 +11,7 @@ #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/prefs/pref_service.h" +#include "components/sync/base/data_type_histogram.h" #include "components/sync/driver/sync_client.h" #include "components/sync/driver/sync_service.h" #include "components/sync/model/sync_error.h" @@ -24,6 +25,7 @@ AutofillWalletDataTypeController::AutofillWalletDataTypeController( const base::Closure& dump_stack, syncer::SyncService* sync_service, syncer::SyncClient* sync_client, + const PersonalDataManagerProvider& pdm_provider, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service) : AsyncDirectoryTypeController(type, dump_stack, @@ -31,6 +33,7 @@ AutofillWalletDataTypeController::AutofillWalletDataTypeController( sync_client, syncer::GROUP_DB, std::move(db_thread)), + pdm_provider_(pdm_provider), callback_registered_(false), web_data_service_(web_data_service), currently_enabled_(IsEnabled()) { @@ -95,10 +98,14 @@ void AutofillWalletDataTypeController::StopModels() { if (!sync_service()->CanSyncFeatureStart() || !sync_service()->GetPreferredDataTypes().Has(type()) || !currently_enabled_) { - autofill::PersonalDataManager* pdm = - sync_client()->GetPersonalDataManager(); - if (pdm) + autofill::PersonalDataManager* pdm = pdm_provider_.Run(); + if (pdm) { + int count = pdm->GetServerCreditCards().size() + + pdm->GetServerProfiles().size() + + (pdm->GetPaymentsCustomerData() == nullptr ? 0 : 1); + SyncWalletDataRecordClearedEntitiesCount(count); pdm->ClearAllServerData(); + } } } } diff --git a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h index 837d293a4be..be0e0fff83a 100644 --- a/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h +++ b/chromium/components/autofill/core/browser/autofill_wallet_data_type_controller.h @@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_DATA_TYPE_CONTROLLER_H_ +#include "base/callback.h" #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "components/prefs/pref_change_registrar.h" @@ -12,7 +13,8 @@ namespace autofill { class AutofillWebDataService; -} +class PersonalDataManager; +} // namespace autofill namespace syncer { class SyncClient; @@ -25,6 +27,9 @@ namespace browser_sync { class AutofillWalletDataTypeController : public syncer::AsyncDirectoryTypeController { public: + using PersonalDataManagerProvider = + base::RepeatingCallback<autofill::PersonalDataManager*()>; + // |type| should be either AUTOFILL_WALLET or AUTOFILL_WALLET_METADATA. // |dump_stack| is called when an unrecoverable error occurs. AutofillWalletDataTypeController( @@ -33,6 +38,7 @@ class AutofillWalletDataTypeController const base::Closure& dump_stack, syncer::SyncService* sync_service, syncer::SyncClient* sync_client, + const PersonalDataManagerProvider& pdm_provider, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service); ~AutofillWalletDataTypeController() override; @@ -51,6 +57,9 @@ class AutofillWalletDataTypeController // Report an error (which will stop the datatype asynchronously). void DisableForPolicy(); + // Callback that allows accessing PersonalDataManager lazily. + const PersonalDataManagerProvider pdm_provider_; + // Whether the database loaded callback has been registered. bool callback_registered_; 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 1d391861d1b..c8a98aff248 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 @@ -24,20 +24,21 @@ #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" #include "components/sync/driver/fake_sync_service.h" -#include "components/sync/driver/sync_api_component_factory_mock.h" +#include "components/sync/driver/sync_client_mock.h" #include "components/sync/driver/sync_service.h" #include "components/sync/model/fake_syncable_service.h" #include "components/sync/model/sync_error.h" #include "testing/gtest/include/gtest/gtest.h" -using autofill::AutofillWebDataService; - namespace browser_sync { namespace { +using autofill::AutofillWebDataService; +using testing::_; +using testing::Return; + // Fake WebDataService implementation that stubs out the database loading. class FakeWebDataService : public AutofillWebDataService { public: @@ -76,12 +77,9 @@ class FakeWebDataService : public AutofillWebDataService { DISALLOW_COPY_AND_ASSIGN(FakeWebDataService); }; -class AutofillWalletDataTypeControllerTest : public testing::Test, - public syncer::FakeSyncClient { +class AutofillWalletDataTypeControllerTest : public testing::Test { public: - AutofillWalletDataTypeControllerTest() - : syncer::FakeSyncClient(&profile_sync_factory_), - last_type_(syncer::UNSPECIFIED) {} + AutofillWalletDataTypeControllerTest() : last_type_(syncer::UNSPECIFIED) {} ~AutofillWalletDataTypeControllerTest() override {} void SetUp() override { @@ -90,12 +88,18 @@ class AutofillWalletDataTypeControllerTest : public testing::Test, prefs_.registry()->RegisterBooleanPref( autofill::prefs::kAutofillCreditCardEnabled, true); + ON_CALL(sync_client_, GetPrefService()).WillByDefault(Return(&prefs_)); + ON_CALL(sync_client_, GetSyncableServiceForType(_)) + .WillByDefault(Return(syncable_service_.AsWeakPtr())); + web_data_service_ = base::MakeRefCounted<FakeWebDataService>( base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get()); autofill_wallet_dtc_ = std::make_unique<AutofillWalletDataTypeController>( syncer::AUTOFILL_WALLET_DATA, base::ThreadTaskRunnerHandle::Get(), - base::DoNothing(), &sync_service_, this, web_data_service_); + base::DoNothing(), &sync_service_, &sync_client_, + AutofillWalletDataTypeController::PersonalDataManagerProvider(), + web_data_service_); last_type_ = syncer::UNSPECIFIED; last_error_ = syncer::SyncError(); @@ -108,20 +112,12 @@ class AutofillWalletDataTypeControllerTest : public testing::Test, syncable_service_.StopSyncing(syncer::AUTOFILL_WALLET_DATA); } - // FakeSyncClient overrides. - PrefService* GetPrefService() override { return &prefs_; } - - base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType( - syncer::ModelType type) override { - return syncable_service_.AsWeakPtr(); - } - protected: void SetStartExpectations() { autofill_wallet_dtc_->SetGenericChangeProcessorFactoryForTest( std::make_unique<syncer::FakeGenericChangeProcessorFactory>( std::make_unique<syncer::FakeGenericChangeProcessor>( - syncer::AUTOFILL_WALLET_DATA, this))); + syncer::AUTOFILL_WALLET_DATA))); } void Start() { @@ -147,10 +143,10 @@ class AutofillWalletDataTypeControllerTest : public testing::Test, TestingPrefServiceSimple prefs_; syncer::FakeSyncService sync_service_; syncer::StartCallbackMock start_callback_; - syncer::SyncApiComponentFactoryMock profile_sync_factory_; syncer::FakeSyncableService syncable_service_; std::unique_ptr<AutofillWalletDataTypeController> autofill_wallet_dtc_; scoped_refptr<FakeWebDataService> web_data_service_; + testing::NiceMock<syncer::SyncClientMock> sync_client_; syncer::ModelType last_type_; syncer::SyncError last_error_; @@ -183,8 +179,8 @@ TEST_F(AutofillWalletDataTypeControllerTest, EXPECT_EQ(syncer::DataTypeController::RUNNING, autofill_wallet_dtc_->state()); EXPECT_FALSE(last_error_.IsSet()); EXPECT_EQ(syncer::AUTOFILL_WALLET_DATA, last_type_); - autofill::prefs::SetPaymentsIntegrationEnabled(GetPrefService(), false); - autofill::prefs::SetCreditCardAutofillEnabled(GetPrefService(), true); + autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, false); + autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, true); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(last_error_.IsSet()); } @@ -202,8 +198,8 @@ TEST_F(AutofillWalletDataTypeControllerTest, EXPECT_EQ(syncer::DataTypeController::RUNNING, autofill_wallet_dtc_->state()); EXPECT_FALSE(last_error_.IsSet()); EXPECT_EQ(syncer::AUTOFILL_WALLET_DATA, last_type_); - autofill::prefs::SetPaymentsIntegrationEnabled(GetPrefService(), true); - autofill::prefs::SetCreditCardAutofillEnabled(GetPrefService(), false); + autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, true); + autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, false); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(last_error_.IsSet()); } @@ -212,8 +208,8 @@ TEST_F(AutofillWalletDataTypeControllerTest, DatatypeDisabledByWalletImportAtStartup) { SetStartExpectations(); web_data_service_->LoadDatabase(); - autofill::prefs::SetPaymentsIntegrationEnabled(GetPrefService(), false); - autofill::prefs::SetCreditCardAutofillEnabled(GetPrefService(), true); + autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, false); + autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, true); EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING, autofill_wallet_dtc_->state()); Start(); @@ -225,8 +221,8 @@ TEST_F(AutofillWalletDataTypeControllerTest, DatatypeDisabledByCreditCardsAtStartup) { SetStartExpectations(); web_data_service_->LoadDatabase(); - autofill::prefs::SetPaymentsIntegrationEnabled(GetPrefService(), true); - autofill::prefs::SetCreditCardAutofillEnabled(GetPrefService(), false); + autofill::prefs::SetPaymentsIntegrationEnabled(&prefs_, true); + autofill::prefs::SetCreditCardAutofillEnabled(&prefs_, false); EXPECT_EQ(syncer::DataTypeController::NOT_RUNNING, autofill_wallet_dtc_->state()); Start(); diff --git a/chromium/components/autofill/core/browser/contact_form_label_formatter.cc b/chromium/components/autofill/core/browser/contact_form_label_formatter.cc new file mode 100644 index 00000000000..47701675865 --- /dev/null +++ b/chromium/components/autofill/core/browser/contact_form_label_formatter.cc @@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/contact_form_label_formatter.h" + +namespace autofill { + +ContactFormLabelFormatter::ContactFormLabelFormatter( + const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types, + const std::set<FieldTypeGroup>& field_type_groups) + : LabelFormatter(app_locale, focused_field_type, field_types), + field_type_groups_(field_type_groups), + filtered_field_type_groups_(field_type_groups) { + for (const ServerFieldType& type : field_types) { + if (type != focused_field_type) { + field_types_for_labels_.push_back(type); + } + } + const FieldTypeGroup group = + AutofillType(AutofillType(focused_field_type).GetStorableType()).group(); + filtered_field_type_groups_.erase(group); +} + +ContactFormLabelFormatter::~ContactFormLabelFormatter() {} + +std::vector<base::string16> ContactFormLabelFormatter::GetLabels( + const std::vector<AutofillProfile*>& profiles) const { + // TODO(crbug.com/936168): Implement GetLabels(). + std::vector<base::string16> labels; + return labels; +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/contact_form_label_formatter.h b/chromium/components/autofill/core/browser/contact_form_label_formatter.h new file mode 100644 index 00000000000..38684976af4 --- /dev/null +++ b/chromium/components/autofill/core/browser/contact_form_label_formatter.h @@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_CONTACT_FORM_LABEL_FORMATTER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_CONTACT_FORM_LABEL_FORMATTER_H_ + +#include <set> +#include <string> +#include <vector> + +#include "base/strings/string16.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/label_formatter.h" + +namespace autofill { + +// A LabelFormatter that creates Suggestions' disambiguating labels for forms +// containing name and phone or email fields. +class ContactFormLabelFormatter : public LabelFormatter { + public: + ContactFormLabelFormatter(const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types, + const std::set<FieldTypeGroup>& field_type_groups); + + ~ContactFormLabelFormatter() override; + + std::vector<base::string16> GetLabels( + const std::vector<AutofillProfile*>& profiles) const override; + + private: + // A collection of field types that can be used to make labels. This + // collection excludes the focused_field_type_. + std::vector<ServerFieldType> field_types_for_labels_; + + // A collection of meaningful FieldTypeGroups in the form with which the user + // is interacting. + std::set<FieldTypeGroup> field_type_groups_; + + // A collection of meaningful FieldTypeGroups in the form with which the user + // is interacting minus the focused field's corresponding FieldTypeGroup. + std::set<FieldTypeGroup> filtered_field_type_groups_; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_CONTACT_FORM_LABEL_FORMATTER_H_ diff --git a/chromium/components/autofill/core/browser/contact_info_unittest.cc b/chromium/components/autofill/core/browser/contact_info_unittest.cc index d07dfa041f1..3f2502fa654 100644 --- a/chromium/components/autofill/core/browser/contact_info_unittest.cc +++ b/chromium/components/autofill/core/browser/contact_info_unittest.cc @@ -46,7 +46,7 @@ TEST_P(SetFullNameTest, SetFullName) { name.GetInfo(AutofillType(NAME_FULL), "en-US")); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ContactInfoTest, SetFullNameTest, testing::Values( @@ -215,7 +215,7 @@ struct ParsedNamesAreEqualTestCase { starting_profile.ParsedNamesAreEqual(additional_profile)); } - INSTANTIATE_TEST_CASE_P( + INSTANTIATE_TEST_SUITE_P( ContactInfoTest, ParsedNamesAreEqualTest, testing::Values( @@ -308,7 +308,7 @@ struct ParsedNamesAreEqualTestCase { existing_name.GetRawInfo(NAME_FULL)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ContactInfoTest, OverwriteNameTest, testing::Values( @@ -387,7 +387,7 @@ struct NamePartsAreEmptyTestCase { EXPECT_EQ(test_case.expected_result, name.NamePartsAreEmpty()); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( ContactInfoTest, NamePartsAreEmptyTest, testing::Values(NamePartsAreEmptyTestCase{"", "", "", "", true}, diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc index 139dca405e1..5d0273de71c 100644 --- a/chromium/components/autofill/core/browser/credit_card.cc +++ b/chromium/components/autofill/core/browser/credit_card.cc @@ -30,6 +30,7 @@ #include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_metadata.h" +#include "components/autofill/core/browser/autofill_metrics.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_clock.h" @@ -655,10 +656,30 @@ bool CreditCard::IsLocalDuplicateOfServerCard(const CreditCard& other) const { } bool CreditCard::HasSameNumberAs(const CreditCard& other) const { - // For masked cards, this is the best we can do to compare card numbers. + // Masked cards are considered to have the same number if their last four + // digits match and if any expiration date information available for both + // cards matches. if (record_type() == MASKED_SERVER_CARD || other.record_type() == MASKED_SERVER_CARD) { - return NetworkAndLastFourDigits() == other.NetworkAndLastFourDigits(); + bool last_four_digits_match = LastFourDigits() == other.LastFourDigits(); + // The below metric is logged because this function previously compared + // cards' last four digits and networks if one card was masked. It may be + // useful to know how often networks match when the last four digits match. + // It is expected that when two cards' last four digits are the same, their + // networks will almost always match, too. + if (last_four_digits_match) { + AutofillMetrics::LogMaskedCardComparisonNetworksMatch( + NetworkForDisplay() == other.NetworkForDisplay()); + } + + bool months_match = expiration_month() == other.expiration_month() || + expiration_month() == 0 || + other.expiration_month() == 0; + + bool years_match = expiration_year() == other.expiration_year() || + expiration_year() == 0 || other.expiration_year() == 0; + + return last_four_digits_match && months_match && years_match; } return StripSeparators(number_) == StripSeparators(other.number_); @@ -869,7 +890,7 @@ base::string16 CreditCard::ExpirationMonthAsString() const { if (expiration_month_ == 0) return base::string16(); - base::string16 month = base::IntToString16(expiration_month_); + base::string16 month = base::NumberToString16(expiration_month_); if (expiration_month_ >= 10) return month; @@ -882,7 +903,7 @@ base::string16 CreditCard::Expiration4DigitYearAsString() const { if (expiration_year_ == 0) return base::string16(); - return base::IntToString16(Expiration4DigitYear()); + return base::NumberToString16(Expiration4DigitYear()); } bool CreditCard::HasFirstAndLastName() const { @@ -898,7 +919,7 @@ base::string16 CreditCard::Expiration2DigitYearAsString() const { if (expiration_year_ == 0) return base::string16(); - return base::IntToString16(Expiration2DigitYear()); + return base::NumberToString16(Expiration2DigitYear()); } void CreditCard::GetSupportedTypes(ServerFieldTypeSet* supported_types) const { diff --git a/chromium/components/autofill/core/browser/credit_card.h b/chromium/components/autofill/core/browser/credit_card.h index deff6364ddc..397ac1bda06 100644 --- a/chromium/components/autofill/core/browser/credit_card.h +++ b/chromium/components/autofill/core/browser/credit_card.h @@ -165,7 +165,7 @@ class CreditCard : public AutofillDataModel { bool IsLocalDuplicateOfServerCard(const CreditCard& other) const; // Determines if |this| has the same number as |other|. If either is a masked - // server card, compares the last four digits only. + // server card, compares their last four digits and expiration dates. bool HasSameNumberAs(const CreditCard& other) const; // Equality operators compare GUIDs, origins, and the contents. diff --git a/chromium/components/autofill/core/browser/credit_card_field.cc b/chromium/components/autofill/core/browser/credit_card_field.cc index fb1f8bf9914..cbf5de6d188 100644 --- a/chromium/components/autofill/core/browser/credit_card_field.cc +++ b/chromium/components/autofill/core/browser/credit_card_field.cc @@ -322,7 +322,7 @@ bool CreditCardField::LikelyCardYearSelectField(AutofillScanner* scanner) { for (int year = time_exploded.year; year < time_exploded.year + kYearsToMatch; ++year) { - years_to_check.push_back(base::IntToString16(year)); + years_to_check.push_back(base::NumberToString16(year)); } return (FindConsecutiveStrings(years_to_check, field->option_values) || FindConsecutiveStrings(years_to_check, field->option_contents)); diff --git a/chromium/components/autofill/core/browser/credit_card_field_unittest.cc b/chromium/components/autofill/core/browser/credit_card_field_unittest.cc index f701a390212..35ee3dba298 100644 --- a/chromium/components/autofill/core/browser/credit_card_field_unittest.cc +++ b/chromium/components/autofill/core/browser/credit_card_field_unittest.cc @@ -375,7 +375,7 @@ TEST_P(ParseExpFieldTest, ParseExpField) { field_candidates_map_[ASCIIToUTF16("exp3")].BestHeuristicType()); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardFieldTest, ParseExpFieldTest, testing::Values( 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 cef57c082f9..910d5e02fd6 100644 --- a/chromium/components/autofill/core/browser/credit_card_save_manager.cc +++ b/chromium/components/autofill/core/browser/credit_card_save_manager.cc @@ -15,6 +15,7 @@ #include <vector> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -87,7 +88,9 @@ CreditCardSaveManager::CreditCardSaveManager( // This is to initialize StrikeDatabase is if it hasn't been already, so that // its cache would be loaded and ready to use when the first CCSM is created. if (base::FeatureList::IsEnabled( - features::kAutofillSaveCreditCardUsesStrikeSystemV2)) { + features::kAutofillSaveCreditCardUsesStrikeSystemV2) || + base::FeatureList::IsEnabled( + features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) { // Only init when |kAutofillSaveCreditCardUsesStrikeSystemV2| is enabled. If // flag is off and LegacyStrikeDatabase instead of StrikeDatabase is used, // this init will cause failure on GetStrikes(). @@ -98,9 +101,11 @@ CreditCardSaveManager::CreditCardSaveManager( CreditCardSaveManager::~CreditCardSaveManager() {} void CreditCardSaveManager::AttemptToOfferCardLocalSave( + bool has_non_focusable_field, const CreditCard& card) { local_card_save_candidate_ = card; show_save_prompt_ = base::nullopt; + has_non_focusable_field_ = has_non_focusable_field; // Query the Autofill StrikeDatabase on if we should pop up the // offer-to-save prompt for this card. @@ -125,6 +130,7 @@ void CreditCardSaveManager::AttemptToOfferCardLocalSave( void CreditCardSaveManager::AttemptToOfferCardUploadSave( const FormStructure& submitted_form, + bool has_non_focusable_field, const CreditCard& card, const bool uploading_local_card) { // Abort the uploading if |payments_client_| is nullptr. @@ -151,6 +157,8 @@ void CreditCardSaveManager::AttemptToOfferCardUploadSave( found_value_in_cvc_field_ = false; found_cvc_value_in_non_cvc_field_ = false; + has_non_focusable_field_ = has_non_focusable_field; + for (const auto& field : submitted_form) { const bool is_valid_cvc = IsValidCreditCardSecurityCode( field->value, upload_request_.card.network()); @@ -175,6 +183,11 @@ void CreditCardSaveManager::AttemptToOfferCardUploadSave( pending_upload_request_origin_ = submitted_form.main_frame_origin(); + if (has_non_focusable_field_) { + upload_decision_metrics_ |= + AutofillMetrics::UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD; + } + if (upload_request_.cvc.empty()) { // Apply the CVC decision to |upload_decision_metrics_| to denote a problem // was found. @@ -328,7 +341,9 @@ void CreditCardSaveManager::OnDidUploadCard( /*is_local=*/false, GetCreditCardSaveStrikeDatabase()->GetStrikes( base::UTF16ToUTF8(upload_request_.card.LastFourDigits()))); - // Clear all strikes for this card, in case it is later removed. + + // Clear all CreditCardSave strikes for this card, in case it is later + // removed. GetCreditCardSaveStrikeDatabase()->ClearStrikes( base::UTF16ToUTF8(upload_request_.card.LastFourDigits())); } else if (base::FeatureList::IsEnabled( @@ -377,11 +392,22 @@ void CreditCardSaveManager::OnDidUploadCard( CreditCardSaveStrikeDatabase* CreditCardSaveManager::GetCreditCardSaveStrikeDatabase() { - if (strike_database_.get() == nullptr) { - strike_database_ = std::make_unique<CreditCardSaveStrikeDatabase>( - CreditCardSaveStrikeDatabase(client_->GetStrikeDatabase())); + if (credit_card_save_strike_database_.get() == nullptr) { + credit_card_save_strike_database_ = + std::make_unique<CreditCardSaveStrikeDatabase>( + CreditCardSaveStrikeDatabase(client_->GetStrikeDatabase())); } - return strike_database_.get(); + return credit_card_save_strike_database_.get(); +} + +LocalCardMigrationStrikeDatabase* +CreditCardSaveManager::GetLocalCardMigrationStrikeDatabase() { + if (local_card_migration_strike_database_.get() == nullptr) { + local_card_migration_strike_database_ = + std::make_unique<LocalCardMigrationStrikeDatabase>( + LocalCardMigrationStrikeDatabase(client_->GetStrikeDatabase())); + } + return local_card_migration_strike_database_.get(); } void CreditCardSaveManager::OnDidGetStrikesForLocalSave(const int num_strikes) { @@ -396,8 +422,8 @@ void CreditCardSaveManager::OnDidGetStrikesForUploadSave( show_save_prompt_ = num_strikes < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; - // Only offer upload once both Payments and the Autofill LegacyStrikeDatabase - // have returned their decisions. Use population of + // Only offer upload once both Payments and the Autofill + // LegacyStrikeDatabase have returned their decisions. Use population of // |upload_request_.context_token| as an indicator of the Payments call // returning successfully. if (!upload_request_.context_token.empty()) @@ -407,12 +433,24 @@ void CreditCardSaveManager::OnDidGetStrikesForUploadSave( void CreditCardSaveManager::OnDidGetUploadDetails( AutofillClient::PaymentsRpcResult result, const base::string16& context_token, - std::unique_ptr<base::Value> legal_message) { + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_card_bin_ranges) { if (observer_for_testing_) observer_for_testing_->OnReceivedGetUploadDetailsResponse(); if (result == AutofillClient::SUCCESS) { // Do *not* call payments_client_->Prepare() here. We shouldn't send // credentials until the user has explicitly accepted a prompt to upload. + if (base::FeatureList::IsEnabled( + features::kAutofillDoNotUploadSaveUnsupportedCards) && + !supported_card_bin_ranges.empty() && + !IsCreditCardSupported(supported_card_bin_ranges)) { + AttemptToOfferCardLocalSave(has_non_focusable_field_, + upload_request_.card); + upload_decision_metrics_ |= + AutofillMetrics::UPLOAD_NOT_OFFERED_UNSUPPORTED_BIN_RANGE; + LogCardUploadDecisions(upload_decision_metrics_); + return; + } upload_request_.context_token = context_token; legal_message_ = base::DictionaryValue::From(std::move(legal_message)); @@ -445,8 +483,10 @@ void CreditCardSaveManager::OnDidGetUploadDetails( 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_) - AttemptToOfferCardLocalSave(upload_request_.card); + if (found_name_and_postal_code_and_cvc && !uploading_local_card_) { + AttemptToOfferCardLocalSave(has_non_focusable_field_, + upload_request_.card); + } upload_decision_metrics_ |= AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED; LogCardUploadDecisions(upload_decision_metrics_); @@ -467,7 +507,9 @@ void CreditCardSaveManager::OfferCardLocalSave() { if (observer_for_testing_) observer_for_testing_->OnOfferLocalSave(); client_->ConfirmSaveCreditCardLocally( - local_card_save_candidate_, show_save_prompt_.value(), + local_card_save_candidate_, + AutofillClient::SaveCreditCardOptions().with_show_prompt( + show_save_prompt_.value()), base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnLocalSave, weak_ptr_factory_.GetWeakPtr())); @@ -488,17 +530,19 @@ void CreditCardSaveManager::OfferCardUploadSave() { #else bool is_mobile_build = false; #endif // #if defined(OS_ANDROID) || defined(OS_IOS) - // If |show_save_prompt_.value()| is false, desktop builds will still offer // save in the omnibox without popping-up the bubble. Mobile builds, however, // should not display the offer-to-save infobar at all. if (!is_mobile_build || show_save_prompt_.value()) { user_did_accept_upload_prompt_ = false; - client_->ConfirmSaveCreditCardToCloud( upload_request_.card, std::move(legal_message_), - should_request_name_from_user_, - should_request_expiration_date_from_user_, show_save_prompt_.value(), + AutofillClient::SaveCreditCardOptions() + .with_has_non_focusable_field(has_non_focusable_field_) + .with_should_request_name_from_user(should_request_name_from_user_) + .with_should_request_expiration_date_from_user( + should_request_expiration_date_from_user_) + .with_show_prompt(show_save_prompt_.value()), base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnUploadSave, weak_ptr_factory_.GetWeakPtr())); client_->LoadRiskData( @@ -537,12 +581,13 @@ void CreditCardSaveManager::OnUserDidDecideOnLocalSave( /*is_local=*/true); if (base::FeatureList::IsEnabled( features::kAutofillSaveCreditCardUsesStrikeSystemV2)) { - // Log how many strikes the card had when it was saved. + // Log how many CreditCardSave strikes the card had when it was saved. LogStrikesPresentWhenCardSaved( /*is_local=*/true, GetCreditCardSaveStrikeDatabase()->GetStrikes(base::UTF16ToUTF8( local_card_save_candidate_.LastFourDigits()))); - // Clear all strikes for this card, in case it is later removed. + // Clear all CreditCardSave strikes for this card, in case it is later + // removed. GetCreditCardSaveStrikeDatabase()->ClearStrikes( base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())); } else if (base::FeatureList::IsEnabled( @@ -563,6 +608,12 @@ void CreditCardSaveManager::OnUserDidDecideOnLocalSave( base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())), base::DoNothing()); } + if (base::FeatureList::IsEnabled( + features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) { + GetLocalCardMigrationStrikeDatabase()->RemoveStrikes( + LocalCardMigrationStrikeDatabase:: + kStrikesToRemoveWhenLocalCardAdded); + } personal_data_manager_->OnAcceptedLocalCreditCardSave( local_card_save_candidate_); @@ -818,12 +869,19 @@ void CreditCardSaveManager::OnUserDidDecideOnUploadSave( const AutofillClient::UserProvidedCardDetails& user_provided_card_details) { switch (user_decision) { case AutofillClient::ACCEPTED: -// On Android, requesting cardholder name is a two step flow. +// On Android, requesting cardholder name or expiration date is a two step +// flow. #if defined(OS_ANDROID) if (should_request_name_from_user_) { client_->ConfirmAccountNameFixFlow(base::BindOnce( &CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow, weak_ptr_factory_.GetWeakPtr())); + } else if (should_request_expiration_date_from_user_) { + client_->ConfirmExpirationDateFixFlow( + upload_request_.card, + base::BindOnce( + &CreditCardSaveManager::OnUserDidAcceptExpirationDateFixFlow, + weak_ptr_factory_.GetWeakPtr())); } else { OnUserDidAcceptUploadHelper(user_provided_card_details); } @@ -850,6 +908,13 @@ void CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow( /*expiration_date_month=*/base::string16(), /*expiration_date_year=*/base::string16()}); } + +void CreditCardSaveManager::OnUserDidAcceptExpirationDateFixFlow( + const base::string16& month, + const base::string16& year) { + OnUserDidAcceptUploadHelper( + {/*cardholder_name=*/base::string16(), month, year}); +} #endif void CreditCardSaveManager::OnUserDidAcceptUploadHelper( @@ -913,7 +978,7 @@ void CreditCardSaveManager::SendUploadCardRequest() { void CreditCardSaveManager::OnUserDidIgnoreOrDeclineSave( const base::string16& card_last_four_digits) { - if (show_save_prompt_.value()) { + if (show_save_prompt_ != base::nullopt && show_save_prompt_.value()) { if (base::FeatureList::IsEnabled( features::kAutofillSaveCreditCardUsesStrikeSystemV2)) { // If the user rejected or ignored save and the offer-to-save bubble or @@ -1005,4 +1070,28 @@ void CreditCardSaveManager::LogSaveCardRequestExpirationDateReasonMetric() { } } +bool CreditCardSaveManager::IsCreditCardSupported( + std::vector<std::pair<int, int>> supported_card_bin_ranges) { + base::string16 stripped_number = + CreditCard::StripSeparators(upload_request_.card.number()); + for (auto& bin_range : supported_card_bin_ranges) { + unsigned long range_num_of_digits = + base::NumberToString(bin_range.first).size(); + DCHECK_EQ(range_num_of_digits, + base::NumberToString(bin_range.second).size()); + // The first n digits of credit card number, where n is the number of + // digits in range's starting/ending number. + int first_digits_start, first_digits_end; + base::StringToInt(stripped_number.substr(0, range_num_of_digits), + &first_digits_start); + base::StringToInt(stripped_number.substr(0, range_num_of_digits), + &first_digits_end); + if (first_digits_start >= bin_range.first && + first_digits_end <= bin_range.second) { + return true; + } + } + return false; +} + } // namespace autofill 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 a1ae70e31ff..5cffff6e8c9 100644 --- a/chromium/components/autofill/core/browser/credit_card_save_manager.h +++ b/chromium/components/autofill/core/browser/credit_card_save_manager.h @@ -8,6 +8,7 @@ #include <map> #include <memory> #include <string> +#include <utility> #include <vector> #include "base/optional.h" @@ -18,6 +19,7 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/credit_card_save_strike_database.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/local_card_migration_strike_database.h" #include "components/autofill/core/browser/payments/payments_client.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "url/origin.h" @@ -93,11 +95,18 @@ class CreditCardSaveManager { virtual ~CreditCardSaveManager(); // Begins the process to offer local credit card save to the user. - void AttemptToOfferCardLocalSave(const CreditCard& card); + // If |has_non_focusable_field| is true, the save is triggered by a form that + // has non_focusable fields. + void AttemptToOfferCardLocalSave(bool has_non_focusable_field, + const CreditCard& card); // Begins the process to offer upload credit card save to the user if the // imported card passes all requirements and Google Payments approves. + // If |has_non_focusable_field| is true, the save is triggered by a form that + // has non-focusable fields. if |uploading_local_card| is true, the card being + // offered for upload is already a local card on the device. void AttemptToOfferCardUploadSave(const FormStructure& submitted_form, + bool has_non_focusable_field, const CreditCard& card, const bool uploading_local_card); @@ -124,12 +133,17 @@ class CreditCardSaveManager { private: friend class CreditCardSaveManagerTest; friend class CreditCardSaveManagerTestObserverBridge; + friend class LocalCardMigrationBrowserTest; friend class TestCreditCardSaveManager; friend class SaveCardBubbleViewsFullFormBrowserTest; + friend class SaveCardInfobarEGTestHelper; // Returns the CreditCardSaveStrikeDatabase for |client_|. CreditCardSaveStrikeDatabase* GetCreditCardSaveStrikeDatabase(); + // Returns the GetLocalCardMigrationStrikeDatabase for |client_|. + LocalCardMigrationStrikeDatabase* GetLocalCardMigrationStrikeDatabase(); + // Sets |show_save_prompt| and moves forward with offering credit card local // save. void OnDidGetStrikesForLocalSave(const int num_strikes); @@ -140,10 +154,14 @@ class CreditCardSaveManager { // Returns the legal message retrieved from Payments. On failure or not // meeting Payments's conditions for upload, |legal_message| will contain - // nullptr. - void OnDidGetUploadDetails(AutofillClient::PaymentsRpcResult result, - const base::string16& context_token, - std::unique_ptr<base::Value> legal_message); + // nullptr. |supported_card_bin_ranges| is a list of BIN prefix ranges which + // are supoorted, with the first and second number in the pair being the start + // and end of the range. + void OnDidGetUploadDetails( + AutofillClient::PaymentsRpcResult result, + const base::string16& context_token, + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_card_bin_ranges); // Logs the number of strikes that a card had when save succeeded. void LogStrikesPresentWhenCardSaved(bool is_local, const int num_strikes); @@ -196,12 +214,16 @@ class CreditCardSaveManager { user_provided_card_details); #if defined(OS_ANDROID) - // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if - // the risk data is available. Sets the cardholder name on the upload request - // if |cardholder_name| is set. + // Upload the card details with the user provided cardholder_name. // Only relevant for mobile as fix flow is two steps on mobile compared to // one step on desktop. void OnUserDidAcceptAccountNameFixFlow(const base::string16& cardholder_name); + + // Upload the card details with the user provided expiration date month and + // year. Only relevant for mobile as fix flow is two steps on mobile compared + // to one step on desktop. + void OnUserDidAcceptExpirationDateFixFlow(const base::string16& month, + const base::string16& year); #endif // defined(OS_ANDROID) // Helper function that calls SendUploadCardRequest by setting @@ -242,6 +264,13 @@ class CreditCardSaveManager { // Logs the reason why expiration date was explicitly requested. void LogSaveCardRequestExpirationDateReasonMetric(); + // Checks if credit card matches one of the ranges in + // |supported_card_bin_ranges|, inclusive of the start and end boundaries. + // For example, if the range consists of std::pair<34, 36>, then all cards + // with first two digits of 34, 35 and 36 are supported. + bool IsCreditCardSupported( + std::vector<std::pair<int, int>> supported_card_bin_ranges); + // For testing. void SetEventObserverForTesting(ObserverForTest* observer) { observer_for_testing_ = observer; @@ -302,12 +331,22 @@ class CreditCardSaveManager { // determined to be a CVC field via heuristics has a valid CVC |value|. bool found_cvc_value_in_non_cvc_field_ = false; + // |has_non_focusable_field_| is |true| if there exists a field that + // |is_focusable| is false. + bool has_non_focusable_field_ = false; + // The origin of the top level frame from which a form is uploaded. url::Origin pending_upload_request_origin_; // The returned legal message from a GetUploadDetails call to Google Payments. std::unique_ptr<base::DictionaryValue> legal_message_; + std::unique_ptr<CreditCardSaveStrikeDatabase> + credit_card_save_strike_database_; + + std::unique_ptr<LocalCardMigrationStrikeDatabase> + local_card_migration_strike_database_; + std::unique_ptr<CreditCardSaveStrikeDatabase> strike_database_; // May be null. 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 ef3e151e073..d4d246aaf5f 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 @@ -117,7 +117,6 @@ class CreditCardSaveManagerTest : public testing::Test { /*identity_manager=*/nullptr, /*client_profile_validator=*/nullptr, /*history_service=*/nullptr, - /*cookie_manager_sevice=*/nullptr, /*is_off_the_record=*/false); personal_data_.SetSyncServiceForTest(&sync_service_); autocomplete_history_manager_.Init( @@ -183,7 +182,8 @@ class CreditCardSaveManagerTest : public testing::Test { void CreateTestCreditCardFormData(FormData* form, bool is_https, bool use_month_type, - bool split_names = false) { + bool split_names = false, + bool is_from_non_focusable_form = false) { form->name = ASCIIToUTF16("MyForm"); if (is_https) { form->origin = GURL("https://myform.com/form.html"); @@ -214,6 +214,7 @@ class CreditCardSaveManagerTest : public testing::Test { form->fields.push_back(field); } test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field); + field.is_focusable = !is_from_non_focusable_form; form->fields.push_back(field); if (use_month_type) { test::CreateTestFormField("Expiration Date", "ccmonth", "", "month", @@ -756,6 +757,170 @@ TEST_F(CreditCardSaveManagerTest, "Autofill.SaveCardReachedPersonalDataManager.Server", 0); } +// Tests metrics for supporting unfocused card form. +TEST_F(CreditCardSaveManagerTest, UploadCreditCard_WithNonFocusableField) { + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillImportNonFocusableCreditCardForms); + 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; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data with non_focusable form field. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, /*is_https=*/true, + /*use_month_type=*/false, /*split_names=*/true, + /*is_from_non_focusable_form=*/true); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo"); + credit_card_form.fields[1].value = ASCIIToUTF16("Master"); + credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[4].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[5].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + FormSubmitted(credit_card_form); + EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); + // Verify that the correct histogram entries were logged. + ExpectCardUploadDecision(histogram_tester, AutofillMetrics::UPLOAD_OFFERED); + ExpectCardUploadDecision( + histogram_tester, + AutofillMetrics::UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD); + // Verify that the correct UKM was logged. + ExpectCardUploadDecisionUkm( + AutofillMetrics::UPLOAD_OFFERED | + AutofillMetrics::UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD); +} + +// Tests upload card save will still work as usual when supporting unfocused +// card form experiment is off. +TEST_F(CreditCardSaveManagerTest, + UploadCreditCard_WithNonFocusableField_ExpOff) { + scoped_feature_list_.InitAndDisableFeature( + features::kAutofillImportNonFocusableCreditCardForms); + 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; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data with non_focusable form field. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, /*is_https=*/true, + /*use_month_type=*/false, /*split_names=*/true, + /*is_from_non_focusable_form=*/true); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo"); + credit_card_form.fields[1].value = ASCIIToUTF16("Master"); + credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[4].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[5].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + FormSubmitted(credit_card_form); + EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); +} + +// Tests local card save will still work as usual when supporting unfocused card +// form feature is already on. +TEST_F(CreditCardSaveManagerTest, LocalCreditCard_WithNonFocusableField) { + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillImportNonFocusableCreditCardForms); + credit_card_save_manager_->SetCreditCardUploadEnabled(false); + + // Create, fill and submit an address form in order to establish a recent + // profile which can be selected for the upload request. + FormData address_form; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data with non_focusable form field. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, /*is_https=*/true, + /*use_month_type=*/false, /*split_names=*/true, + /*is_from_non_focusable_form=*/true); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo"); + credit_card_form.fields[1].value = ASCIIToUTF16("Master"); + credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[4].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[5].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + FormSubmitted(credit_card_form); + EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled()); + EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); +} + +// Tests local card save will still work as usual when supporting unfocused card +// form experiment is off. +TEST_F(CreditCardSaveManagerTest, + LocalCreditCard_WithNonFocusableField_ExpOff) { + scoped_feature_list_.InitAndDisableFeature( + features::kAutofillImportNonFocusableCreditCardForms); + credit_card_save_manager_->SetCreditCardUploadEnabled(false); + + // Create, fill and submit an address form in order to establish a recent + // profile which can be selected for the upload request. + FormData address_form; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data with non_focusable form field. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, /*is_https=*/true, + /*use_month_type=*/false, /*split_names=*/true, + /*is_from_non_focusable_form=*/true); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo"); + credit_card_form.fields[1].value = ASCIIToUTF16("Master"); + credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[4].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[5].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + FormSubmitted(credit_card_form); + EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled()); + EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); +} + // 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) { @@ -2831,7 +2996,7 @@ TEST_F(CreditCardSaveManagerTest, DuplicateMaskedCreditCard_NoUpload) { } // This class is parametrized to allow running all the inheriting tests with and -// without a specific feature enabled. See INSTANTIATE_TEST_CASE_P. +// without a specific feature enabled. See INSTANTIATE_TEST_SUITE_P. class CreditCardSaveManagerFeatureParameterizedTest : public CreditCardSaveManagerTest, public ::testing::WithParamInterface< @@ -3928,9 +4093,9 @@ TEST_P(CreditCardSaveManagerFeatureParameterizedTest, // Feature disabled // CreditCardSaveManagerFeatureParameterizedTest.NothingIfNothingFound/1: // Feature enabled. -INSTANTIATE_TEST_CASE_P(, // Empty instatiation name. - CreditCardSaveManagerFeatureParameterizedTest, - ::testing::Values(false, true)); +INSTANTIATE_TEST_SUITE_P(, // Empty instatiation name. + CreditCardSaveManagerFeatureParameterizedTest, + ::testing::Values(false, true)); TEST_F(CreditCardSaveManagerTest, UploadCreditCard_DoNotAddAnyFlagStatesToRequestIfExperimentsOff) { @@ -5232,4 +5397,171 @@ TEST_F(CreditCardSaveManagerTest, OnUserDidAcceptUpload_NotifiesPDM) { UserHasAcceptedUpload({}); } +// Tests that 2 LocalCardMigrationStrikes are removed when cards are saved +// locally. +TEST_F(CreditCardSaveManagerTest, + LocalCreditCard_LocalCardMigrationStrikesRemovedOnLocalSave) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillLocalCardMigrationUsesStrikeSystemV2}, + // Disabled + {}); + + LocalCardMigrationStrikeDatabase local_card_migration_strike_database = + LocalCardMigrationStrikeDatabase(strike_database_); + + // Start with 3 strikes in |local_card_migration_strike_database|. + local_card_migration_strike_database.AddStrikes(3); + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 3); + + credit_card_save_manager_->SetCreditCardUploadEnabled(false); + + // Create, fill and submit an address form in order to establish a recent + // profile which can be selected for the upload request. + FormData address_form; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data with credit card first and last name + // fields. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, /*is_https=*/true, + /*use_month_type=*/false, /*split_names=*/true); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo"); + credit_card_form.fields[1].value = ASCIIToUTF16("Master"); + credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[4].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[5].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + FormSubmitted(credit_card_form); + EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled()); + EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); + + // 2 strikes should be removed when card was saved locally. + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 1); +} + +// Tests that no LocalCardMigrationStrikes get removed due to cards being +// uploaded. +TEST_F(CreditCardSaveManagerTest, + UploadCreditCard_NoLocalSaveMigrationStrikesRemovedOnUpload) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillLocalCardMigrationUsesStrikeSystemV2}, + // Disabled + {}); + + LocalCardMigrationStrikeDatabase local_card_migration_strike_database = + LocalCardMigrationStrikeDatabase(strike_database_); + + // Start with 3 strikes in |local_card_migration_strike_database|. + local_card_migration_strike_database.AddStrikes(3); + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 3); + + 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; + test::CreateTestAddressFormData(&address_form); + FormsSeen(std::vector<FormData>(1, address_form)); + ExpectUniqueFillableFormParsedUkm(); + + ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form); + FormSubmitted(address_form); + + // Set up our credit card form data with credit card first and last name + // fields. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, /*is_https=*/true, + /*use_month_type=*/false, /*split_names=*/true); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo"); + credit_card_form.fields[1].value = ASCIIToUTF16("Master"); + credit_card_form.fields[2].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[3].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[4].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[5].value = ASCIIToUTF16("123"); + + base::HistogramTester histogram_tester; + + FormSubmitted(credit_card_form); + EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled()); + EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); + + // Strike count shouldn't change. + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 3); +} + +// Tests that if a card doesn't fall in any of the supported bin ranges, local +// save is offered rather than upload save. +TEST_F(CreditCardSaveManagerTest, UploadSaveNotOfferedForUnsupportedCard) { + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillDoNotUploadSaveUnsupportedCards); + std::vector<std::pair<int, int>> supported_card_bin_ranges{ + std::make_pair(4111, 4113), std::make_pair(34, 34), + std::make_pair(300, 305)}; + payments_client_->SetSupportedBINRanges(supported_card_bin_ranges); + // Set up our credit card form data. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); + credit_card_form.fields[1].value = ASCIIToUTF16("5454545454545454"); + credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[4].value = ASCIIToUTF16("123"); + + // Since card isn't in any of the supported ranges, local save should be + // offered and upload save should not. + FormSubmitted(credit_card_form); + EXPECT_TRUE(autofill_client_.ConfirmSaveCardLocallyWasCalled()); + EXPECT_FALSE(credit_card_save_manager_->CreditCardWasUploaded()); +} + +// Tests that if a card falls in one of the supported bin ranges, upload save +// is offered. +TEST_F(CreditCardSaveManagerTest, UploadSaveOfferedForSupportedCard) { + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillDoNotUploadSaveUnsupportedCards); + // Set supported BIN ranges. + std::vector<std::pair<int, int>> supported_card_bin_ranges{ + std::make_pair(4111, 4113)}; + payments_client_->SetSupportedBINRanges(supported_card_bin_ranges); + + // Set up our credit card form data. + FormData credit_card_form; + CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master"); + credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111"); + credit_card_form.fields[2].value = ASCIIToUTF16(NextMonth()); + credit_card_form.fields[3].value = ASCIIToUTF16(NextYear()); + credit_card_form.fields[4].value = ASCIIToUTF16("123"); + + // Since card is in one of the supported ranges(4111-4113), upload save should + // be offered. + FormSubmitted(credit_card_form); + EXPECT_FALSE(autofill_client_.ConfirmSaveCardLocallyWasCalled()); + EXPECT_TRUE(credit_card_save_manager_->CreditCardWasUploaded()); +} + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc b/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc deleted file mode 100644 index 6628663394c..00000000000 --- a/chromium/components/autofill/core/browser/credit_card_save_strike_database_unittest.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/core/browser/credit_card_save_strike_database.h" - -#include <utility> -#include <vector> - -#include "base/files/scoped_temp_dir.h" -#include "base/run_loop.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/autofill/core/browser/proto/strike_data.pb.h" -#include "components/autofill/core/browser/test_autofill_clock.h" -#include "components/autofill/core/browser/test_credit_card_save_strike_database.h" -#include "components/autofill/core/common/autofill_clock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace autofill { - -class CreditCardSaveStrikeDatabaseTest : public ::testing::Test { - public: - CreditCardSaveStrikeDatabaseTest() - : strike_database_(new StrikeDatabase(InitFilePath())) {} - - protected: - base::HistogramTester* GetHistogramTester() { return &histogram_tester_; } - base::test::ScopedTaskEnvironment scoped_task_environment_; - TestCreditCardSaveStrikeDatabase strike_database_; - - private: - static const base::FilePath InitFilePath() { - base::ScopedTempDir temp_dir_; - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - const base::FilePath file_path = - temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest"); - return file_path; - } - - base::HistogramTester histogram_tester_; -}; - -TEST_F(CreditCardSaveStrikeDatabaseTest, GetKeyForCreditCardSaveTest) { - const std::string last_four = "1234"; - EXPECT_EQ("CreditCardSave__1234", strike_database_.GetKey(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, MaxStrikesLimitReachedTest) { - const std::string last_four = "1234"; - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(last_four)); - // 1st strike added for |last_four|. - strike_database_.AddStrike(last_four); - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(last_four)); - // 2nd strike added for |last_four|. - strike_database_.AddStrike(last_four); - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(last_four)); - // 3rd strike added for |last_four|. - strike_database_.AddStrike(last_four); - EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, - CreditCardSaveNthStrikeAddedHistogram) { - const std::string last_four1 = "1234"; - const std::string last_four2 = "9876"; - // 1st strike added for |last_four1|. - strike_database_.AddStrike(last_four1); - // 2nd strike added for |last_four1|. - strike_database_.AddStrike(last_four1); - // 1st strike added for |last_four2|. - strike_database_.AddStrike(last_four2); - std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( - "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave"); - // There should be two buckets, one for 1st strike, one for 2nd strike count. - ASSERT_EQ(2U, buckets.size()); - // Both |last_four1| and |last_four2| have 1st strikes recorded. - EXPECT_EQ(2, buckets[0].count); - // Only |last_four1| has 2nd strike recorded. - EXPECT_EQ(1, buckets[1].count); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, - AddStrikeForZeroAndNonZeroStrikesTest) { - const std::string last_four = "1234"; - EXPECT_EQ(0, strike_database_.GetStrikes(last_four)); - strike_database_.AddStrike(last_four); - EXPECT_EQ(1, strike_database_.GetStrikes(last_four)); - strike_database_.AddStrike(last_four); - EXPECT_EQ(2, strike_database_.GetStrikes(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, ClearStrikesForNonZeroStrikesTest) { - const std::string last_four = "1234"; - strike_database_.AddStrike(last_four); - EXPECT_EQ(1, strike_database_.GetStrikes(last_four)); - strike_database_.ClearStrikes(last_four); - EXPECT_EQ(0, strike_database_.GetStrikes(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, ClearStrikesForZeroStrikesTest) { - const std::string last_four = "1234"; - strike_database_.ClearStrikes(last_four); - EXPECT_EQ(0, strike_database_.GetStrikes(last_four)); -} - -TEST_F(CreditCardSaveStrikeDatabaseTest, RemoveExpiredStrikesTest) { - autofill::TestAutofillClock test_clock; - test_clock.SetNow(AutofillClock::Now()); - const std::string last_four1 = "1234"; - const std::string last_four2 = "9876"; - strike_database_.AddStrike(last_four1); - - // Advance clock to past the entry for |last_four1|'s expiry time. - test_clock.Advance(base::TimeDelta::FromMicroseconds( - strike_database_.GetExpiryTimeMicros() + 1)); - - strike_database_.AddStrike(last_four2); - strike_database_.RemoveExpiredStrikes(); - - // |last_four1|'s entry should have its most recent strike expire, but - // |last_four2|'s should not. - EXPECT_EQ(0, strike_database_.GetStrikes(last_four1)); - EXPECT_EQ(1, strike_database_.GetStrikes(last_four2)); - - // Advance clock to past |last_four2|'s expiry time. - test_clock.Advance(base::TimeDelta::FromMicroseconds( - strike_database_.GetExpiryTimeMicros() + 1)); - - strike_database_.RemoveExpiredStrikes(); - - // |last_four1| and |last_four2| should have no more unexpired strikes. - EXPECT_EQ(0, strike_database_.GetStrikes(last_four1)); - EXPECT_EQ(0, strike_database_.GetStrikes(last_four2)); -} - -} // namespace autofill diff --git a/chromium/components/autofill/core/browser/credit_card_unittest.cc b/chromium/components/autofill/core/browser/credit_card_unittest.cc index 9552cae6cd4..71153c60fab 100644 --- a/chromium/components/autofill/core/browser/credit_card_unittest.cc +++ b/chromium/components/autofill/core/browser/credit_card_unittest.cc @@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_experiments.h" @@ -364,19 +365,19 @@ TEST_P(SetExpirationYearFromStringTest, SetExpirationYearFromString) { << test_case.expiration_year << " " << test_case.expected_year; } -INSTANTIATE_TEST_CASE_P(CreditCardTest, - SetExpirationYearFromStringTest, - testing::Values( - // Valid values. - SetExpirationYearFromStringTestCase{"2040", 2040}, - SetExpirationYearFromStringTestCase{"45", 2045}, - SetExpirationYearFromStringTestCase{"045", 2045}, - SetExpirationYearFromStringTestCase{"9", 2009}, +INSTANTIATE_TEST_SUITE_P(CreditCardTest, + SetExpirationYearFromStringTest, + testing::Values( + // Valid values. + SetExpirationYearFromStringTestCase{"2040", 2040}, + SetExpirationYearFromStringTestCase{"45", 2045}, + SetExpirationYearFromStringTestCase{"045", 2045}, + SetExpirationYearFromStringTestCase{"9", 2009}, - // Unrecognized year values. - SetExpirationYearFromStringTestCase{"052045", 0}, - SetExpirationYearFromStringTestCase{"123", 0}, - SetExpirationYearFromStringTestCase{"y2045", 0})); + // Unrecognized year values. + SetExpirationYearFromStringTestCase{"052045", 0}, + SetExpirationYearFromStringTestCase{"123", 0}, + SetExpirationYearFromStringTestCase{"y2045", 0})); struct SetExpirationDateFromStringTestCase { std::string expiration_date; @@ -396,7 +397,7 @@ TEST_P(SetExpirationDateFromStringTest, SetExpirationDateFromString) { EXPECT_EQ(test_case.expected_year, card.expiration_year()); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, SetExpirationDateFromStringTest, testing::Values( @@ -486,7 +487,7 @@ TEST_P(IsLocalDuplicateOfServerCardTest, IsLocalDuplicateOfServerCard) { << " when comparing cards " << a.Label() << " and " << b.Label(); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, IsLocalDuplicateOfServerCardTest, testing::Values( @@ -517,9 +518,6 @@ INSTANTIATE_TEST_CASE_P( LOCAL_CARD, "", "423456789012", "", "", "1", MASKED_SERVER_CARD, "John Dillinger", "9012", "01", "2010", "1", kVisaCard, true}, IsLocalDuplicateOfServerCardTestCase{ - LOCAL_CARD, "", "423456789012", "", "", "1", MASKED_SERVER_CARD, - "John Dillinger", "9012", "01", "2010", "1", kMasterCard, false}, - IsLocalDuplicateOfServerCardTestCase{ LOCAL_CARD, "John Dillinger", "4234-5678-9012", "01", "2010", "1", FULL_SERVER_CARD, "John Dillinger", "423456789012", "01", "2010", "1", nullptr, true}, @@ -536,31 +534,123 @@ TEST(CreditCardTest, HasSameNumberAs) { EXPECT_TRUE(a.HasSameNumberAs(b)); EXPECT_TRUE(b.HasSameNumberAs(a)); - // Same number. + // Cards with the same number are the same. a.set_record_type(CreditCard::LOCAL_CARD); a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); - a.set_record_type(CreditCard::LOCAL_CARD); + b.set_record_type(CreditCard::LOCAL_CARD); b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); EXPECT_TRUE(a.HasSameNumberAs(b)); EXPECT_TRUE(b.HasSameNumberAs(a)); - // Local cards shouldn't match even if the last 4 are the same. + // Local cards with different overall numbers shouldn't match even if the last + // four digits are the same. a.set_record_type(CreditCard::LOCAL_CARD); a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); - a.set_record_type(CreditCard::LOCAL_CARD); + b.set_record_type(CreditCard::LOCAL_CARD); b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111222222221111")); EXPECT_FALSE(a.HasSameNumberAs(b)); EXPECT_FALSE(b.HasSameNumberAs(a)); - // Likewise if one is an unmasked server card. + // When one card is a full server card, the other is a local card, and the + // cards have different overall numbers but the same last four digits, they + // should not match. a.set_record_type(CreditCard::FULL_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + b.set_record_type(CreditCard::LOCAL_CARD); + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111222222221111")); EXPECT_FALSE(a.HasSameNumberAs(b)); EXPECT_FALSE(b.HasSameNumberAs(a)); - // But if one is a masked card, then they should. - b.set_record_type(CreditCard::MASKED_SERVER_CARD); + // When one card is a masked server card, the other is a local card, and the + // cards have the same last four digits, they should match. + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + b.set_record_type(CreditCard::LOCAL_CARD); + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4331111111111111")); + EXPECT_TRUE(a.HasSameNumberAs(b)); + EXPECT_TRUE(b.HasSameNumberAs(a)); + + // When one card is a masked server card, the other is a full server card, and + // the cards have the same last four digits, they should match. + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + b.set_record_type(CreditCard::FULL_SERVER_CARD); + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4331111111111111")); EXPECT_TRUE(a.HasSameNumberAs(b)); EXPECT_TRUE(b.HasSameNumberAs(a)); + + // If one card is masked, then partial or missing expiration date information + // should not prevent the function from returning true. + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + a.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01")); + a.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2025")); + b.set_record_type(CreditCard::LOCAL_CARD); + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("")); + EXPECT_TRUE(a.HasSameNumberAs(b)); + EXPECT_TRUE(b.HasSameNumberAs(a)); + + // If one card is masked, then non-matching expiration months should cause the + // function to return false. + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + a.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("01")); + a.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("")); + b.set_record_type(CreditCard::LOCAL_CARD); + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("03")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("")); + EXPECT_FALSE(a.HasSameNumberAs(b)); + EXPECT_FALSE(b.HasSameNumberAs(a)); + + // If one card is masked, then non-matching expiration years should cause the + // function to return false. + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + a.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("")); + a.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2025")); + b.set_record_type(CreditCard::LOCAL_CARD); + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2026")); + EXPECT_FALSE(a.HasSameNumberAs(b)); + EXPECT_FALSE(b.HasSameNumberAs(a)); +} + +TEST(CreditCardTest, HasSameNumberAs_LogMaskedCardComparisonNetworksMatch) { + CreditCard a(base::GenerateGUID(), std::string()); + CreditCard b(base::GenerateGUID(), std::string()); + + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + a.SetNetworkForMaskedCard(kVisaCard); + // CreditCard b's network is set to kVisaCard because it starts with 4, so the + // two cards have the same network. + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + base::HistogramTester histogram_tester; + EXPECT_TRUE(a.HasSameNumberAs(b)); + histogram_tester.ExpectUniqueSample( + "Autofill.MaskedCardComparisonNetworksMatch", true, 1); +} + +TEST(CreditCardTest, + HasSameNumberAs_LogMaskedCardComparisonNetworksDoNotMatch) { + CreditCard a(base::GenerateGUID(), std::string()); + CreditCard b(base::GenerateGUID(), std::string()); + + a.set_record_type(CreditCard::MASKED_SERVER_CARD); + a.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + a.SetNetworkForMaskedCard(kDiscoverCard); + // CreditCard b's network is set to kVisaCard because it starts with 4. The + // two cards have the same last four digits, but their networks are different, + // so this discrepancy should be logged. + b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); + base::HistogramTester histogram_tester; + EXPECT_TRUE(a.HasSameNumberAs(b)); + histogram_tester.ExpectUniqueSample( + "Autofill.MaskedCardComparisonNetworksMatch", false, 1); } TEST(CreditCardTest, Compare) { @@ -931,9 +1021,9 @@ TEST(CreditCardTest, IsValidCardNumberAndExpiryDate) { base::Time::Exploded now_exploded; now.LocalExplode(&now_exploded); card.SetRawInfo(CREDIT_CARD_EXP_MONTH, - base::IntToString16(now_exploded.month)); + base::NumberToString16(now_exploded.month)); card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, - base::IntToString16(now_exploded.year - 1)); + base::NumberToString16(now_exploded.year - 1)); card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); EXPECT_FALSE(card.IsValid()); EXPECT_FALSE(card.HasValidExpirationDate()); @@ -1152,9 +1242,9 @@ const CreditCardMatchingTypesCase kCreditCardMatchingTypesTestCases[] = { {"2021", "01", "2019", LOCAL_CARD, ServerFieldTypeSet()}, }; -INSTANTIATE_TEST_CASE_P(CreditCardTest, - CreditCardMatchingTypesTest, - testing::ValuesIn(kCreditCardMatchingTypesTestCases)); +INSTANTIATE_TEST_SUITE_P(CreditCardTest, + CreditCardMatchingTypesTest, + testing::ValuesIn(kCreditCardMatchingTypesTestCases)); struct GetCardNetworkTestCase { const char* card_number; @@ -1162,7 +1252,7 @@ struct GetCardNetworkTestCase { bool is_valid; }; -// We are doing batches here because INSTANTIATE_TEST_CASE_P has a +// We are doing batches here because INSTANTIATE_TEST_SUITE_P has a // 50 upper limit. class GetCardNetworkTestBatch1 : public testing::TestWithParam<GetCardNetworkTestCase> {}; @@ -1175,7 +1265,7 @@ TEST_P(GetCardNetworkTestBatch1, GetCardNetwork) { EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, GetCardNetworkTestBatch1, testing::Values( @@ -1238,7 +1328,7 @@ TEST_P(GetCardNetworkTestBatch2, GetCardNetwork) { EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, GetCardNetworkTestBatch2, testing::Values( @@ -1291,7 +1381,7 @@ TEST_P(GetCardNetworkTestBatch3, GetCardNetwork) { EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, GetCardNetworkTestBatch3, testing::Values( @@ -1351,7 +1441,7 @@ TEST_P(GetCardNetworkTestBatch4, GetCardNetwork) { EXPECT_EQ(test_case.is_valid, IsValidCreditCardNumber(card_number)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, GetCardNetworkTestBatch4, testing::Values( @@ -1482,7 +1572,7 @@ TEST_P(ShouldUpdateExpirationTest, ShouldUpdateExpiration) { card.ShouldUpdateExpiration(testingTimes.now_)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardTest, ShouldUpdateExpirationTest, testing::Values( diff --git a/chromium/components/autofill/core/browser/field_filler.cc b/chromium/components/autofill/core/browser/field_filler.cc index e1e56eb081d..736b6684b6a 100644 --- a/chromium/components/autofill/core/browser/field_filler.cc +++ b/chromium/components/autofill/core/browser/field_filler.cc @@ -624,6 +624,7 @@ bool FieldFiller::FillFormField(const AutofillField& field, FormFieldData* field_data, const base::string16& cvc) { 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(features::kAutofillAlwaysFillAddresses) && @@ -632,6 +633,9 @@ bool FieldFiller::FillFormField(const AutofillField& field, return false; } + if (data_model.ShouldSkipFillingOrSuggesting(type.GetStorableType())) + return false; + base::string16 value = data_model.GetInfo(type, app_locale_); if (type.GetStorableType() == CREDIT_CARD_VERIFICATION_CODE) value = cvc; diff --git a/chromium/components/autofill/core/browser/field_filler_unittest.cc b/chromium/components/autofill/core/browser/field_filler_unittest.cc index eb2f698627f..82728e71ec7 100644 --- a/chromium/components/autofill/core/browser/field_filler_unittest.cc +++ b/chromium/components/autofill/core/browser/field_filler_unittest.cc @@ -110,6 +110,29 @@ void TestFillingExpirationMonth(const std::vector<const char*>& values, EXPECT_EQ(ASCIIToUTF16("Nov"), field.option_contents[content_index]); } +void TestFillingInvalidFields(const base::string16& state, + const base::string16& city) { + AutofillProfile profile = test::GetFullProfile(); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, + AutofillProfile::SERVER); + profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID, + AutofillProfile::CLIENT); + + AutofillField field_state; + field_state.set_heuristic_type(ADDRESS_HOME_STATE); + AutofillField field_city; + field_city.set_heuristic_type(ADDRESS_HOME_CITY); + + FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr); + filler.FillFormField(field_state, profile, &field_state, + /*cvc=*/base::string16()); + EXPECT_EQ(state, field_state.value); + + filler.FillFormField(field_city, profile, &field_city, + /*cvc=*/base::string16()); + EXPECT_EQ(city, field_city.value); +} + struct CreditCardTestCase { std::string card_number_; size_t total_splits_; @@ -388,6 +411,82 @@ TEST_F(AutofillFieldFillerTest, FillFormField_AutocompleteOff_CreditCardField) { EXPECT_EQ(ASCIIToUTF16("4111111111111111"), field.value); } +// Verify that when the relevant feature is enabled, the invalid fields don't +// get filled. +TEST_F(AutofillFieldFillerTest, FillFormField_Validity_ServerClient) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileServerValidation, + features::kAutofillProfileClientValidation}, + /*disabled_features=*/{}); + // State's validity is set by server and city's validity by client. + TestFillingInvalidFields(/*state=*/base::string16(), + /*city=*/base::string16()); +} + +TEST_F(AutofillFieldFillerTest, FillFormField_Validity_OnlyServer) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileServerValidation}, + /*disabled_features=*/{features::kAutofillProfileClientValidation}); + // State's validity is set by server and city's validity by client. + TestFillingInvalidFields(/*state=*/base::string16(), + /*city=*/ASCIIToUTF16("Elysium")); +} + +TEST_F(AutofillFieldFillerTest, FillFormField_Validity_OnlyClient) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileClientValidation}, + /*disabled_features=*/{features::kAutofillProfileServerValidation}); + // State's validity is set by server and city's validity by client. + TestFillingInvalidFields(/*state=*/ASCIIToUTF16("CA"), + /*city=*/base::string16()); +} + +TEST_F(AutofillFieldFillerTest, FillFormField_NoValidity) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{features::kAutofillProfileServerValidation, + features::kAutofillProfileClientValidation}); + // State's validity is set by server and city's validity by client. + TestFillingInvalidFields(/*state=*/ASCIIToUTF16("CA"), + /*city=*/ASCIIToUTF16("Elysium")); +} + +// Tests that using only client side validation, if the country is empty, the +// address fields will get filled regardless of their invalidity. +TEST_F(AutofillFieldFillerTest, FillFormField_Validity_CountryEmpty) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileClientValidation}, + /*disabled_features=*/{features::kAutofillProfileServerValidation}); + AutofillProfile profile = test::GetFullProfile(); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("")); + profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID, + AutofillProfile::CLIENT); + profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::INVALID, + AutofillProfile::CLIENT); + + AutofillField field_state; + field_state.set_heuristic_type(ADDRESS_HOME_STATE); + AutofillField field_email; + field_email.set_heuristic_type(EMAIL_ADDRESS); + + FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr); + // State is filled, because it's an address field. + filler.FillFormField(field_state, profile, &field_state, + /*cvc=*/base::string16()); + EXPECT_EQ(ASCIIToUTF16("CA"), field_state.value); + + // Email is not filled, because it's not an address field, and it doesn't + // depend on the country. + filler.FillFormField(field_email, profile, &field_email, + /*cvc=*/base::string16()); + EXPECT_EQ(ASCIIToUTF16(""), field_email.value); +} + struct AutofillFieldFillerTestCase { HtmlFieldType field_type; size_t field_max_length; @@ -413,7 +512,7 @@ TEST_P(PhoneNumberTest, FillPhoneNumber) { EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillFieldFillerTest, PhoneNumberTest, testing::Values( @@ -463,7 +562,7 @@ TEST_P(ExpirationYearTest, FillExpirationYearInput) { EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillFieldFillerTest, ExpirationYearTest, testing::Values( @@ -527,7 +626,7 @@ TEST_P(ExpirationDateTest, FillExpirationDateInput) { EXPECT_EQ(response, test_case.expected_response); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillFieldFillerTest, ExpirationDateTest, testing::Values( @@ -717,7 +816,7 @@ TEST_P(AutofillSelectWithStatesTest, FillSelectWithStates) { } } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillFieldFillerTest, AutofillSelectWithStatesTest, testing::Values( @@ -805,7 +904,7 @@ TEST_P(AutofillSelectWithExpirationMonthTest, test_case.select_values.size()); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillFieldFillerTest, AutofillSelectWithExpirationMonthTest, testing::Values( @@ -1291,7 +1390,7 @@ TEST_P(AutofillStateTextTest, FillStateText) { EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillFieldFillerTest, AutofillStateTextTest, testing::Values( diff --git a/chromium/components/autofill/core/browser/field_types.h b/chromium/components/autofill/core/browser/field_types.h index fe6d8ab5c1c..c10fd8df61d 100644 --- a/chromium/components/autofill/core/browser/field_types.h +++ b/chromium/components/autofill/core/browser/field_types.h @@ -169,9 +169,12 @@ enum ServerFieldType { // Search term fields are detected, but not filled. SEARCH_TERM = 97, + // Price fields are detected, but not filled. + PRICE = 98, + // No new types can be added without a corresponding change to the Autofill // server. - MAX_VALID_FIELD_TYPE = 98, + MAX_VALID_FIELD_TYPE = 99, }; // The list of all HTML autocomplete field type hints supported by Chrome. diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc index 03b9216973a..15e57a10910 100644 --- a/chromium/components/autofill/core/browser/form_data_importer.cc +++ b/chromium/components/autofill/core/browser/form_data_importer.cc @@ -14,6 +14,7 @@ #include <set> #include <utility> +#include "base/bind.h" #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -176,7 +177,7 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form, imported_credit_card_record_type_ == ImportedCreditCardRecordType::NEW_CARD); credit_card_save_manager_->AttemptToOfferCardUploadSave( - submitted_form, *imported_credit_card, + submitted_form, has_non_focusable_field_, *imported_credit_card, /*uploading_local_card=*/imported_credit_card_record_type_ == ImportedCreditCardRecordType::LOCAL_CARD); } else { @@ -184,7 +185,7 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form, DCHECK(imported_credit_card_record_type_ == ImportedCreditCardRecordType::NEW_CARD); credit_card_save_manager_->AttemptToOfferCardLocalSave( - *imported_credit_card); + has_non_focusable_field_, *imported_credit_card); } } @@ -442,7 +443,10 @@ bool FormDataImporter::ImportCreditCard( // there is for local cards. for (const CreditCard* card : personal_data_manager_->GetServerCreditCards()) { - if (candidate_credit_card.HasSameNumberAs(*card)) { + if ((card->record_type() == CreditCard::MASKED_SERVER_CARD && + card->LastFourDigits() == candidate_credit_card.LastFourDigits()) || + (card->record_type() == CreditCard::FULL_SERVER_CARD && + candidate_credit_card.HasSameNumberAs(*card))) { // Don't update card if the expiration date is missing if (candidate_credit_card.expiration_month() == 0 || candidate_credit_card.expiration_year() == 0) { @@ -504,6 +508,9 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm( if (field_type.group() != CREDIT_CARD) continue; + if (!field->is_focusable) + has_non_focusable_field_ = true; + // If we've seen the same credit card field type twice in the same form, // set |has_duplicate_field_type| to true. ServerFieldType server_field_type = field_type.GetStorableType(); diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h index 0a11aeb00a4..a195d96cc86 100644 --- a/chromium/components/autofill/core/browser/form_data_importer.h +++ b/chromium/components/autofill/core/browser/form_data_importer.h @@ -120,6 +120,10 @@ class FormDataImporter { CreditCard ExtractCreditCardFromForm(const FormStructure& form, bool* hasDuplicateFieldType); + // Whether the form imported has non-focusable fields after user entered + // information into it. + bool has_non_focusable_field_ = false; + // The associated autofill client. Weak reference. AutofillClient* client_; @@ -145,6 +149,7 @@ class FormDataImporter { friend class AutofillMergeTest; friend class FormDataImporterTest; friend class FormDataImporterTestBase; + friend class LocalCardMigrationBrowserTest; friend class SaveCardBubbleViewsFullFormBrowserTest; friend class SaveCardInfobarEGTestHelper; FRIEND_TEST_ALL_PREFIXES(AutofillMergeTest, MergeProfiles); 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 a205459df88..00280a55dde 100644 --- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc +++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc @@ -124,7 +124,6 @@ class FormDataImporterTestBase { /*identity_manager=*/nullptr, /*client_profile_validator=*/nullptr, /*history_service=*/nullptr, - /*cookie_manager_sevice=*/nullptr, /*is_off_the_record=*/(user_mode == USER_MODE_INCOGNITO)); personal_data_manager_->AddObserver(&personal_data_observer_); personal_data_manager_->OnSyncServiceInitialized(nullptr); diff --git a/chromium/components/autofill/core/browser/form_field.cc b/chromium/components/autofill/core/browser/form_field.cc index 3328e18c6f9..7b2aac8f7ab 100644 --- a/chromium/components/autofill/core/browser/form_field.cc +++ b/chromium/components/autofill/core/browser/form_field.cc @@ -23,7 +23,9 @@ #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/name_field.h" #include "components/autofill/core/browser/phone_field.h" +#include "components/autofill/core/browser/price_field.h" #include "components/autofill/core/browser/search_field.h" +#include "components/autofill/core/browser/travel_field.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_util.h" @@ -31,14 +33,16 @@ namespace autofill { // There's an implicit precedence determined by the values assigned here. Email -// is currently the most important followed by Phone, Address, Credit Card, -// Name, and Search. +// is currently the most important followed by Phone, Travel, Address, +// Credit Card, Name, and Search. const float FormField::kBaseEmailParserScore = 1.4f; const float FormField::kBasePhoneParserScore = 1.3f; -const float FormField::kBaseAddressParserScore = 1.2f; -const float FormField::kBaseCreditCardParserScore = 1.1f; -const float FormField::kBaseNameParserScore = 1.0f; -const float FormField::kBaseSearchParserScore = 0.9f; +const float FormField::kBaseTravelParserScore = 1.2f; +const float FormField::kBaseAddressParserScore = 1.1f; +const float FormField::kBaseCreditCardParserScore = 1.0f; +const float FormField::kBasePriceParserScore = 0.95f; +const float FormField::kBaseNameParserScore = 0.9f; +const float FormField::kBaseSearchParserScore = 0.8f; // static FieldCandidatesMap FormField::ParseFormFields( @@ -69,6 +73,9 @@ FieldCandidatesMap FormField::ParseFormFields( // Phone pass. ParseFormFieldsPass(PhoneField::Parse, processed_fields, &field_candidates); + // Travel pass. + ParseFormFieldsPass(TravelField::Parse, processed_fields, &field_candidates); + // Address pass. ParseFormFieldsPass(autofill::AddressField::Parse, processed_fields, &field_candidates); @@ -77,6 +84,9 @@ FieldCandidatesMap FormField::ParseFormFields( ParseFormFieldsPass(CreditCardField::Parse, processed_fields, &field_candidates); + // Price pass. + ParseFormFieldsPass(PriceField::Parse, processed_fields, &field_candidates); + // Name pass. ParseFormFieldsPass(NameField::Parse, processed_fields, &field_candidates); diff --git a/chromium/components/autofill/core/browser/form_field.h b/chromium/components/autofill/core/browser/form_field.h index c14e88f2b98..8471b0ff3f6 100644 --- a/chromium/components/autofill/core/browser/form_field.h +++ b/chromium/components/autofill/core/browser/form_field.h @@ -60,8 +60,10 @@ class FormField { // Initial values assigned to FieldCandidates by their corresponding parsers. static const float kBaseEmailParserScore; static const float kBasePhoneParserScore; + static const float kBaseTravelParserScore; static const float kBaseAddressParserScore; static const float kBaseCreditCardParserScore; + static const float kBasePriceParserScore; static const float kBaseNameParserScore; static const float kBaseSearchParserScore; diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc index c715abb098f..07adcce22f2 100644 --- a/chromium/components/autofill/core/browser/form_structure.cc +++ b/chromium/components/autofill/core/browser/form_structure.cc @@ -18,7 +18,6 @@ #include "base/logging.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" -#include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h index 218c73ed169..414345d7744 100644 --- a/chromium/components/autofill/core/browser/form_structure.h +++ b/chromium/components/autofill/core/browser/form_structure.h @@ -319,7 +319,7 @@ class FormStructure { // - Name for Autofill of first field base::string16 GetIdentifierForRefill() const; - int developer_engagement_metrics() { return developer_engagement_metrics_; }; + int developer_engagement_metrics() { return developer_engagement_metrics_; } void set_randomized_encoder(std::unique_ptr<RandomizedEncoder> encoder); @@ -348,7 +348,7 @@ class FormStructure { if (sectioned_indexes.empty()) return (size_t)-1; // Shouldn't happen. return sectioned_indexes.back().back(); - }; + } void AddFieldIndex(const size_t index, bool is_new_section) { if (is_new_section || Empty()) { diff --git a/chromium/components/autofill/core/browser/label_formatter.cc b/chromium/components/autofill/core/browser/label_formatter.cc new file mode 100644 index 00000000000..32426dd7790 --- /dev/null +++ b/chromium/components/autofill/core/browser/label_formatter.cc @@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/label_formatter.h" + +namespace autofill { + +LabelFormatter::LabelFormatter(const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types) + : app_locale_(app_locale), + focused_field_type_(focused_field_type), + field_types_(field_types) {} +LabelFormatter::~LabelFormatter() = default; + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/label_formatter.h b/chromium/components/autofill/core/browser/label_formatter.h new file mode 100644 index 00000000000..d436401044d --- /dev/null +++ b/chromium/components/autofill/core/browser/label_formatter.h @@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_H_ + +#include <string> +#include <vector> + +#include "base/strings/string16.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" + +namespace autofill { + +// Handles the creation of Suggestions' disambiguating labels. +class LabelFormatter { + public: + LabelFormatter(const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types); + virtual ~LabelFormatter(); + + // Returns a collection of |labels| formed by extracting useful disambiguating + // information from a collection of |profiles|. + virtual std::vector<base::string16> GetLabels( + const std::vector<AutofillProfile*>& profiles) const = 0; + + protected: + const std::string& app_locale() const { return app_locale_; } + ServerFieldType focused_field_type() const { return focused_field_type_; } + const std::vector<ServerFieldType>& field_types() const { + return field_types_; + } + + private: + // The locale for which to generate labels. This reflects the language and + // country for which the application is translated, e.g. en_AU for Austalian + // English. + std::string app_locale_; + + // The field on which the user is currently focused. + ServerFieldType focused_field_type_; + + // A collection of meaningful field types in the form with which the user is + // interacting. + std::vector<ServerFieldType> field_types_; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_H_ diff --git a/chromium/components/autofill/core/browser/label_formatter_utils.cc b/chromium/components/autofill/core/browser/label_formatter_utils.cc new file mode 100644 index 00000000000..53d8eab8836 --- /dev/null +++ b/chromium/components/autofill/core/browser/label_formatter_utils.cc @@ -0,0 +1,115 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/label_formatter_utils.h" + +#include <memory> +#include <set> + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/address_form_label_formatter.h" +#include "components/autofill/core/browser/autofill_data_util.h" +#include "components/autofill/core/browser/contact_form_label_formatter.h" +#include "components/autofill/core/browser/validation.h" + +namespace autofill { +namespace { + +bool ContainsName(uint32_t groups) { + return groups & label_formatter_groups::kName; +} + +bool ContainsAddress(uint32_t groups) { + return groups & label_formatter_groups::kAddress; +} + +bool ContainsEmail(uint32_t groups) { + return groups & label_formatter_groups::kEmail; +} + +bool ContainsPhone(uint32_t groups) { + return groups & label_formatter_groups::kPhone; +} + +std::set<FieldTypeGroup> GetFieldTypeGroups(uint32_t groups) { + std::set<FieldTypeGroup> field_type_groups; + if (ContainsName(groups)) { + field_type_groups.insert(NAME); + } + if (ContainsAddress(groups)) { + field_type_groups.insert(ADDRESS_HOME); + } + if (ContainsEmail(groups)) { + field_type_groups.insert(EMAIL); + } + if (ContainsPhone(groups)) { + field_type_groups.insert(PHONE_HOME); + } + return field_type_groups; +} + +} // namespace + +std::vector<ServerFieldType> FilterFieldTypes( + const std::vector<ServerFieldType>& field_types) { + std::vector<ServerFieldType> filtered_field_types; + for (const ServerFieldType& field_type : field_types) { + const FieldTypeGroup group = + AutofillType(AutofillType(field_type).GetStorableType()).group(); + if (group == NAME || group == ADDRESS_HOME || group == EMAIL || + group == PHONE_HOME) { + filtered_field_types.push_back(field_type); + } + } + return filtered_field_types; +} + +uint32_t DetermineGroups(const std::vector<ServerFieldType>& field_types) { + uint32_t group_bitmask = 0; + for (const ServerFieldType& type : field_types) { + const FieldTypeGroup group = + AutofillType(AutofillType(type).GetStorableType()).group(); + switch (group) { + case autofill::NAME: + group_bitmask |= label_formatter_groups::kName; + break; + case autofill::ADDRESS_HOME: + group_bitmask |= label_formatter_groups::kAddress; + break; + case autofill::EMAIL: + group_bitmask |= label_formatter_groups::kEmail; + break; + case autofill::PHONE_HOME: + group_bitmask |= label_formatter_groups::kPhone; + break; + default: + break; + } + } + return group_bitmask; +} + +std::unique_ptr<LabelFormatter> Create( + const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types) { + const uint32_t groups = DetermineGroups(field_types); + + if (!ContainsName(groups)) { + return nullptr; + } + if (ContainsAddress(groups) && !ContainsEmail(groups) && + !ContainsPhone(groups)) { + return std::make_unique<AddressFormLabelFormatter>( + app_locale, focused_field_type, FilterFieldTypes(field_types)); + } + if (ContainsEmail(groups) || ContainsPhone(groups)) { + return std::make_unique<ContactFormLabelFormatter>( + app_locale, focused_field_type, FilterFieldTypes(field_types), + GetFieldTypeGroups(groups)); + } + return nullptr; +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/label_formatter_utils.h b/chromium/components/autofill/core/browser/label_formatter_utils.h new file mode 100644 index 00000000000..80b21942c39 --- /dev/null +++ b/chromium/components/autofill/core/browser/label_formatter_utils.h @@ -0,0 +1,58 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_UTILS_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_UTILS_H_ + +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/label_formatter.h" + +namespace autofill { +namespace label_formatter_groups { + +// Bits for FieldTypeGroup options. +// The form contains at least one field associated with the NAME_HOME or +// NAME_BILLING FieldTypeGroups. +constexpr uint32_t kName = 1 << 0; +// The form contains at least one field associated with the ADDRESS_HOME or +// ADDRESS_BILLING FieldTypeGroups. +constexpr uint32_t kAddress = 1 << 1; +// The form contains at least one field associated with the EMAIL +// FieldTypeGroup. +constexpr uint32_t kEmail = 1 << 2; +// The form contains at least one field associated with the PHONE_HOME or +// PHONE_BILLING FieldTypeGroup. +constexpr uint32_t kPhone = 1 << 3; + +} // namespace label_formatter_groups + +// Returns a subset of meaningful ServerFieldTypes found in |field_types|. +// ServerFieldTypes like NO_SERVER_DATA and UNKNOWN_TYPE are frequently found in +// the collection of types sent from the frontend. Other types, e.g. +// COMPANY_NAME and PHONE_FAX_WHOLE_NUMBER, are also sometimes present. These +// types are not useful to LabelFormatters, so only types related to names, +// addresses, emails, and phone numbers are in the results. +std::vector<ServerFieldType> FilterFieldTypes( + const std::vector<ServerFieldType>& field_types); + +// Returns a bitmask indicating whether the NAME, ADDRESS_HOME, EMAIL, and +// PHONE_HOME FieldTypeGroups are associated with the given |field_types|. +uint32_t DetermineGroups(const std::vector<ServerFieldType>& field_types); + +// Creates a form-specific LabelFormatter according to |field_types|. If the +// given |field_types| do not correspond to a LabelFormatter, then nullptr will +// be returned. +std::unique_ptr<LabelFormatter> Create( + const std::string& app_locale, + ServerFieldType focused_field_type, + const std::vector<ServerFieldType>& field_types); + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_LABEL_FORMATTER_UTILS_H_ diff --git a/chromium/components/autofill/core/browser/label_formatter_utils_unittest.cc b/chromium/components/autofill/core/browser/label_formatter_utils_unittest.cc new file mode 100644 index 00000000000..660cb0263d3 --- /dev/null +++ b/chromium/components/autofill/core/browser/label_formatter_utils_unittest.cc @@ -0,0 +1,100 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/label_formatter_utils.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +namespace { +using label_formatter_groups::kAddress; +using label_formatter_groups::kEmail; +using label_formatter_groups::kName; +using label_formatter_groups::kPhone; + +} // namespace + +TEST(LabelFormatterUtilsTest, FilterFieldTypesNoFiltering) { + const std::vector<ServerFieldType> field_types{ + NAME_LAST, NAME_BILLING_LAST, ADDRESS_HOME_ZIP, + ADDRESS_BILLING_ZIP, EMAIL_ADDRESS, PHONE_HOME_NUMBER, + PHONE_BILLING_NUMBER}; + const std::vector<ServerFieldType> filtered_field_types = + FilterFieldTypes(field_types); + EXPECT_EQ(field_types, filtered_field_types); +} + +TEST(LabelFormatterUtilsTest, FilterFieldTypesFilterCompany) { + const std::vector<ServerFieldType> field_types{NAME_LAST, COMPANY_NAME}; + const std::vector<ServerFieldType> expected_filtered_field_types{NAME_LAST}; + const std::vector<ServerFieldType> filtered_field_types = + FilterFieldTypes(field_types); + EXPECT_EQ(expected_filtered_field_types, filtered_field_types); +} + +TEST(LabelFormatterUtilsTest, FilterFieldTypesForNoGivenFieldTypes) { + const std::vector<ServerFieldType> field_types = + std::vector<ServerFieldType>(); + const std::vector<ServerFieldType> filtered_field_types = + FilterFieldTypes(field_types); + EXPECT_EQ(field_types, filtered_field_types); +} + +TEST(LabelFormatterUtilsTest, DetermineGroupsForHomeNameAndAddress) { + const std::vector<ServerFieldType> field_types{ + NAME_FIRST, NAME_LAST, ADDRESS_HOME_LINE1, + ADDRESS_HOME_CITY, ADDRESS_HOME_STATE, ADDRESS_HOME_ZIP}; + + const uint32_t expected_group_bitmask = kName | kAddress; + const uint32_t group_bitmask = DetermineGroups(field_types); + EXPECT_EQ(expected_group_bitmask, group_bitmask); +} + +TEST(LabelFormatterUtilsTest, DetermineGroupsForBillingNameAndAddress) { + const std::vector<ServerFieldType> field_types{ + NAME_BILLING_FULL, ADDRESS_BILLING_LINE1, ADDRESS_BILLING_CITY, + ADDRESS_BILLING_STATE, ADDRESS_BILLING_ZIP}; + + const uint32_t expected_group_bitmask = kName | kAddress; + const uint32_t group_bitmask = DetermineGroups(field_types); + EXPECT_EQ(expected_group_bitmask, group_bitmask); +} + +TEST(LabelFormatterUtilsTest, DetermineGroupsForHomeNamePhoneAndEmail) { + const std::vector<ServerFieldType> field_types{ + NAME_FULL, PHONE_HOME_CITY_AND_NUMBER, EMAIL_ADDRESS}; + + const uint32_t expected_group_bitmask = kName | kPhone | kEmail; + const uint32_t group_bitmask = DetermineGroups(field_types); + EXPECT_EQ(expected_group_bitmask, group_bitmask); +} + +TEST(LabelFormatterUtilsTest, DetermineGroupsForBillingNamePhoneAndEmail) { + const std::vector<ServerFieldType> field_types{ + NAME_BILLING_FULL, PHONE_BILLING_WHOLE_NUMBER, EMAIL_ADDRESS}; + + const uint32_t expected_group_bitmask = kName | kPhone | kEmail; + const uint32_t group_bitmask = DetermineGroups(field_types); + EXPECT_EQ(expected_group_bitmask, group_bitmask); +} + +TEST(LabelFormatterUtilsTest, DetermineGroupsForUnknownServerFieldType) { + const std::vector<ServerFieldType> field_types{UNKNOWN_TYPE, NAME_FULL, + ADDRESS_HOME_ZIP}; + + const uint32_t expected_group_bitmask = kName | kAddress; + const uint32_t group_bitmask = DetermineGroups(field_types); + EXPECT_EQ(expected_group_bitmask, group_bitmask); +} + +TEST(LabelFormatterUtilsTest, DetermineGroupsForNoServerFieldTypes) { + const std::vector<ServerFieldType> field_types = + std::vector<ServerFieldType>(); + const uint32_t expected_group_bitmask = 0; + const uint32_t group_bitmask = DetermineGroups(field_types); + EXPECT_EQ(expected_group_bitmask, group_bitmask); +} + +} // namespace autofill
\ No newline at end of file diff --git a/chromium/components/autofill/core/browser/legacy_strike_database.cc b/chromium/components/autofill/core/browser/legacy_strike_database.cc index e6fbef3f7d3..d575b2e43ae 100644 --- a/chromium/components/autofill/core/browser/legacy_strike_database.cc +++ b/chromium/components/autofill/core/browser/legacy_strike_database.cc @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/metrics/histogram_functions.h" #include "base/task/post_task.h" #include "base/time/time.h" diff --git a/chromium/components/autofill/core/browser/legacy_strike_database_unittest.cc b/chromium/components/autofill/core/browser/legacy_strike_database_unittest.cc index af63074c357..44e60a4ae0c 100644 --- a/chromium/components/autofill/core/browser/legacy_strike_database_unittest.cc +++ b/chromium/components/autofill/core/browser/legacy_strike_database_unittest.cc @@ -7,6 +7,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" diff --git a/chromium/components/autofill/core/browser/legal_message_line_unittest.cc b/chromium/components/autofill/core/browser/legal_message_line_unittest.cc index e3147f1ee7d..6a5c5ba8fd8 100644 --- a/chromium/components/autofill/core/browser/legal_message_line_unittest.cc +++ b/chromium/components/autofill/core/browser/legal_message_line_unittest.cc @@ -104,7 +104,7 @@ class LegalMessageLineTest : public ::testing::TestWithParam<TestCase> { // Verifies that legal message parsing is correct. TEST_P(LegalMessageLineTest, Parsing) { std::unique_ptr<base::Value> value( - base::JSONReader::Read(GetParam().message_json)); + base::JSONReader::ReadDeprecated(GetParam().message_json)); ASSERT_TRUE(value); base::DictionaryValue* dictionary = nullptr; EXPECT_TRUE(value->GetAsDictionary(&dictionary)); @@ -114,9 +114,9 @@ TEST_P(LegalMessageLineTest, Parsing) { GetParam().escape_apostrophes); EXPECT_EQ(GetParam().expected_lines, actual_lines); -}; +} -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( TestCases, LegalMessageLineTest, testing::Values( 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 764f9159b7f..f77d16d7bde 100644 --- a/chromium/components/autofill/core/browser/local_card_migration_manager.cc +++ b/chromium/components/autofill/core/browser/local_card_migration_manager.cc @@ -10,6 +10,8 @@ #include <vector> #include "base/bind.h" +#include "base/metrics/histogram_functions.h" +#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/autofill_experiments.h" @@ -39,7 +41,19 @@ LocalCardMigrationManager::LocalCardMigrationManager( payments_client_(payments_client), app_locale_(app_locale), personal_data_manager_(personal_data_manager), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this) { + // This is to initialize StrikeDatabase is if it hasn't been already, so that + // its cache would be loaded and ready to use when the first LCMM is created. + if (base::FeatureList::IsEnabled( + features::kAutofillSaveCreditCardUsesStrikeSystemV2) || + base::FeatureList::IsEnabled( + features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) { + // Only init when |kAutofillSaveCreditCardUsesStrikeSystemV2| is enabled. If + // flag is off and LegacyStrikeDatabase instead of StrikeDatabase is used, + // this init will cause failure on GetStrikes(). + client_->GetStrikeDatabase(); + } +} LocalCardMigrationManager::~LocalCardMigrationManager() {} @@ -62,9 +76,26 @@ bool LocalCardMigrationManager::ShouldOfferLocalCardMigration( if (!IsCreditCardMigrationEnabled()) return false; - // Don't show the the prompt if user cancelled/rejected previously. - if (prefs::IsLocalCardMigrationPromptPreviouslyCancelled(client_->GetPrefs())) + // Don't show the prompt if max strike count was reached. + if (base::FeatureList::IsEnabled( + features::kAutofillLocalCardMigrationUsesStrikeSystemV2) && + GetLocalCardMigrationStrikeDatabase()->IsMaxStrikesLimitReached()) { + switch (imported_credit_card_record_type) { + case FormDataImporter::ImportedCreditCardRecordType::LOCAL_CARD: + AutofillMetrics::LogLocalCardMigrationNotOfferedDueToMaxStrikesMetric( + AutofillMetrics::SaveTypeMetric::LOCAL); + break; + case FormDataImporter::ImportedCreditCardRecordType::SERVER_CARD: + AutofillMetrics::LogLocalCardMigrationNotOfferedDueToMaxStrikesMetric( + AutofillMetrics::SaveTypeMetric::SERVER); + break; + } + return false; + } else if (prefs::IsLocalCardMigrationPromptPreviouslyCancelled( + client_->GetPrefs())) { + // Don't show the the prompt if user cancelled/rejected previously. return false; + } // Fetch all migratable credit cards and store in |migratable_credit_cards_|. GetMigratableCreditCards(); @@ -88,6 +119,9 @@ void LocalCardMigrationManager::AttemptToOfferLocalCardMigration( return; migration_request_ = payments::PaymentsClient::MigrationRequestDetails(); + if (observer_for_testing_) + observer_for_testing_->OnDecideToRequestLocalCardMigration(); + payments_client_->GetUploadDetails( std::vector<AutofillProfile>(), GetDetectedValues(), /*active_experiments=*/std::vector<const char*>(), app_locale_, @@ -116,16 +150,32 @@ void LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog( user_accepted_main_migration_dialog_ = true; AutofillMetrics::LogLocalCardMigrationPromptMetric( local_card_migration_origin_, AutofillMetrics::MAIN_DIALOG_ACCEPTED); + + // Log number of LocalCardMigration strikes when migration was accepted. + if (base::FeatureList::IsEnabled( + features::kAutofillLocalCardMigrationUsesStrikeSystemV2)) { + base::UmaHistogramCounts1000( + "Autofill.StrikeDatabase.StrikesPresentWhenLocalCardMigrationAccepted", + GetLocalCardMigrationStrikeDatabase()->GetStrikes()); + } + + // If there are cards which aren't selected, add 3 strikes to + // LocalCardMigrationStrikeDatabase. + if (base::FeatureList::IsEnabled( + features::kAutofillLocalCardMigrationUsesStrikeSystemV2) && + (selected_card_guids.size() < migratable_credit_cards_.size())) { + GetLocalCardMigrationStrikeDatabase()->AddStrikes( + LocalCardMigrationStrikeDatabase:: + kStrikesToAddWhenCardsDeselectedAtMigration); + } + // Update the |migratable_credit_cards_| with the |selected_card_guids|. This // will remove any card from |migratable_credit_cards_| of which the GUID is // not in |selected_card_guids|. auto card_is_selected = [&selected_card_guids](MigratableCreditCard& card) { return !base::ContainsValue(selected_card_guids, card.credit_card().guid()); }; - migratable_credit_cards_.erase( - std::remove_if(migratable_credit_cards_.begin(), - migratable_credit_cards_.end(), card_is_selected), - migratable_credit_cards_.end()); + base::EraseIf(migratable_credit_cards_, card_is_selected); // 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 @@ -145,24 +195,44 @@ bool LocalCardMigrationManager::IsCreditCardMigrationEnabled() { bool migration_experiment_enabled = features::GetLocalCardMigrationExperimentalFlag() != features::LocalCardMigrationExperimentalFlag::kMigrationDisabled; - bool credit_card_upload_enabled = ::autofill::IsCreditCardUploadEnabled( - client_->GetPrefs(), client_->GetSyncService(), - client_->GetIdentityManager()->GetPrimaryAccountInfo().email); + + // If |observer_for_testing_| is set, assume we are in a browsertest and + // credit card upload should be enabled by default. Cannot get around this as + // Chrome OS testing requires an unsupported email domain (i.e. + // stub-user@example.com). + bool credit_card_upload_enabled = + observer_for_testing_ || + ::autofill::IsCreditCardUploadEnabled( + client_->GetPrefs(), client_->GetSyncService(), + personal_data_manager_->GetAccountInfoForPaymentsServer().email); + bool has_google_payments_account = (payments::GetBillingCustomerId(personal_data_manager_, payments_client_->GetPrefService()) != 0); - bool sync_feature_enabled = - (personal_data_manager_->GetSyncSigninState() == - AutofillSyncSigninState::kSignedInAndSyncFeature); + + AutofillSyncSigninState sync_state = + personal_data_manager_->GetSyncSigninState(); + return migration_experiment_enabled && credit_card_upload_enabled && - has_google_payments_account && sync_feature_enabled; + has_google_payments_account && + // User signed-in and turned sync on. + (sync_state == AutofillSyncSigninState::kSignedInAndSyncFeature || + // User signed-in but not turned on sync. + (sync_state == AutofillSyncSigninState:: + kSignedInAndWalletSyncTransportEnabled && + base::FeatureList::IsEnabled( + features::kAutofillEnableLocalCardMigrationForNonSyncUser))); } void LocalCardMigrationManager::OnDidGetUploadDetails( bool is_from_settings_page, AutofillClient::PaymentsRpcResult result, const base::string16& context_token, - std::unique_ptr<base::Value> legal_message) { + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_card_bin_ranges) { + if (observer_for_testing_) + observer_for_testing_->OnReceivedGetUploadDetailsResponse(); + if (result == AutofillClient::SUCCESS) { migration_request_.context_token = context_token; legal_message_ = base::DictionaryValue::From(std::move(legal_message)); @@ -196,6 +266,9 @@ void LocalCardMigrationManager::OnDidMigrateLocalCards( AutofillClient::PaymentsRpcResult result, std::unique_ptr<std::unordered_map<std::string, std::string>> save_result, const std::string& display_text) { + if (observer_for_testing_) + observer_for_testing_->OnReceivedMigrateCardsResponse(); + if (!save_result) return; @@ -203,26 +276,32 @@ void LocalCardMigrationManager::OnDidMigrateLocalCards( std::vector<CreditCard> migrated_cards; // Traverse the migratable credit cards to update each migrated card status. for (MigratableCreditCard& card : migratable_credit_cards_) { + // If it is run in a test, count all cards as successfully migrated. + if (observer_for_testing_) { + migrated_cards.push_back(card.credit_card()); + continue; + } + // 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:: - MigrationStatus::FAILURE_ON_UPLOAD); - } else if (it->second == kMigrationResultSuccess) { - card.set_migration_status(autofill::MigratableCreditCard:: - MigrationStatus::SUCCESS_ON_UPLOAD); - migrated_cards.push_back(card.credit_card()); - } else { - NOTREACHED(); - } + // If current card does not exist in the |save_result|, skip it. + if (it == save_result->end()) + continue; + + // Otherwise update its migration status. 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::MigrationStatus::FAILURE_ON_UPLOAD); + } else if (it->second == kMigrationResultSuccess) { + card.set_migration_status( + autofill::MigratableCreditCard::MigrationStatus::SUCCESS_ON_UPLOAD); + migrated_cards.push_back(card.credit_card()); + } else { + NOTREACHED(); } } // Remove cards that were successfully migrated from local storage. @@ -254,6 +333,9 @@ void LocalCardMigrationManager::OnDidGetMigrationRiskData( // Send the migration request. Will call payments_client to create a new // PaymentsRequest. Also create a new callback function OnDidMigrateLocalCards. void LocalCardMigrationManager::SendMigrateLocalCardsRequest() { + if (observer_for_testing_) + observer_for_testing_->OnSentMigrateCardsRequest(); + migration_request_.app_locale = app_locale_; migration_request_.billing_customer_number = payments::GetBillingCustomerId( personal_data_manager_, payments_client_->GetPrefService()); @@ -264,6 +346,16 @@ void LocalCardMigrationManager::SendMigrateLocalCardsRequest() { user_accepted_main_migration_dialog_ = false; } +LocalCardMigrationStrikeDatabase* +LocalCardMigrationManager::GetLocalCardMigrationStrikeDatabase() { + if (local_card_migration_strike_database_.get() == nullptr) { + local_card_migration_strike_database_ = + std::make_unique<LocalCardMigrationStrikeDatabase>( + LocalCardMigrationStrikeDatabase(client_->GetStrikeDatabase())); + } + return local_card_migration_strike_database_.get(); +} + // 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 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 06e5ce5832c..02365d324a1 100644 --- a/chromium/components/autofill/core/browser/local_card_migration_manager.h +++ b/chromium/components/autofill/core/browser/local_card_migration_manager.h @@ -7,11 +7,13 @@ #include <memory> #include <string> +#include <utility> #include <vector> #include "base/strings/string16.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/local_card_migration_strike_database.h" #include "components/autofill/core/browser/payments/payments_client.h" namespace autofill { @@ -43,7 +45,7 @@ class MigratableCreditCard { FAILURE_ON_UPLOAD, }; - MigratableCreditCard(const CreditCard& credit_card); + explicit MigratableCreditCard(const CreditCard& credit_card); ~MigratableCreditCard(); CreditCard credit_card() const { return credit_card_; } @@ -66,6 +68,16 @@ class MigratableCreditCard { // Owned by FormDataImporter. class LocalCardMigrationManager { public: + // An observer class used by browsertests that gets notified whenever + // particular actions occur. + class ObserverForTest { + public: + virtual void OnDecideToRequestLocalCardMigration() = 0; + virtual void OnReceivedGetUploadDetailsResponse() = 0; + virtual void OnSentMigrateCardsRequest() = 0; + virtual void OnReceivedMigrateCardsResponse() = 0; + }; + // The parameters should outlive the LocalCardMigrationManager. LocalCardMigrationManager(AutofillClient* client, payments::PaymentsClient* payments_client, @@ -123,7 +135,8 @@ class LocalCardMigrationManager { bool is_from_settings_page, AutofillClient::PaymentsRpcResult result, const base::string16& context_token, - std::unique_ptr<base::Value> legal_message); + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_card_bin_ranges); // Callback after successfully getting the migration save results. Map // migration save result to each card depending on the |save_result|. Will @@ -141,6 +154,7 @@ class LocalCardMigrationManager { payments::PaymentsClient* payments_client_; private: + friend class LocalCardMigrationBrowserTest; FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationPermanentFailure); FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest, @@ -150,6 +164,9 @@ class LocalCardMigrationManager { FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationManagerTest, MigrateCreditCard_ToggleIsChosen); + // Returns the LocalCardMigrationStrikeDatabase for |client_|. + LocalCardMigrationStrikeDatabase* GetLocalCardMigrationStrikeDatabase(); + // Pops up a larger, modal dialog showing the local cards to be uploaded. void ShowMainMigrationDialog(); @@ -161,6 +178,11 @@ class LocalCardMigrationManager { // Finalizes the migration request and calls PaymentsClient. void SendMigrateLocalCardsRequest(); + // For testing. + void SetEventObserverForTesting(ObserverForTest* observer) { + observer_for_testing_ = observer; + } + std::unique_ptr<base::DictionaryValue> legal_message_; std::string app_locale_; @@ -187,6 +209,12 @@ class LocalCardMigrationManager { // Record the triggering source of the local card migration. AutofillMetrics::LocalCardMigrationOrigin local_card_migration_origin_; + // Initialized only during tests. + ObserverForTest* observer_for_testing_ = nullptr; + + std::unique_ptr<LocalCardMigrationStrikeDatabase> + local_card_migration_strike_database_; + 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 6dd9308c48a..9e6e3a98e10 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 @@ -29,6 +29,7 @@ #include "components/autofill/core/browser/mock_autocomplete_history_manager.h" #include "components/autofill/core/browser/payments/test_payments_client.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/browser/test_autofill_driver.h" @@ -81,6 +82,10 @@ class LocalCardMigrationManagerTest : public testing::Test { local_card_migration_manager_ = new TestLocalCardMigrationManager( autofill_driver_.get(), &autofill_client_, payments_client_, &personal_data_); + std::unique_ptr<TestStrikeDatabase> test_strike_database = + std::make_unique<TestStrikeDatabase>(); + strike_database_ = test_strike_database.get(); + autofill_client_.set_test_strike_database(std::move(test_strike_database)); autofill::TestFormDataImporter* test_form_data_importer = new TestFormDataImporter( &autofill_client_, payments_client_, @@ -108,16 +113,6 @@ class LocalCardMigrationManagerTest : public testing::Test { request_context_ = nullptr; } - void EnableAutofillCreditCardLocalCardMigrationExperiment() { - scoped_feature_list_.InitAndEnableFeature( - features::kAutofillCreditCardLocalCardMigration); - } - - void DisableAutofillCreditCardLocalCardMigrationExperiment() { - scoped_feature_list_.InitAndDisableFeature( - features::kAutofillCreditCardLocalCardMigration); - } - void FormsSeen(const std::vector<FormData>& forms) { autofill_manager_->OnFormsSeen(forms, base::TimeTicks()); } @@ -177,6 +172,8 @@ class LocalCardMigrationManagerTest : public testing::Test { MockAutocompleteHistoryManager autocomplete_history_manager_; syncer::TestSyncService sync_service_; base::test::ScopedFeatureList scoped_feature_list_; + // Ends up getting owned (and destroyed) by TestAutofillClient: + TestStrikeDatabase* strike_database_; // Ends up getting owned (and destroyed) by TestFormDataImporter: TestCreditCardSaveManager* credit_card_save_manager_; // Ends up getting owned (and destroyed) by TestFormDataImporter: @@ -188,7 +185,8 @@ class LocalCardMigrationManagerTest : public testing::Test { // Having one local card on file and using it will not trigger migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_UseLocalCardWithOneLocal) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -221,7 +219,8 @@ TEST_F(LocalCardMigrationManagerTest, // trigger migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_UseNewCardWithAnyLocal) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -251,7 +250,8 @@ TEST_F(LocalCardMigrationManagerTest, // migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_UseLocalCardWithMoreLocal) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -297,7 +297,8 @@ TEST_F(LocalCardMigrationManagerTest, // cards as long as the other local cards are not eligible for migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_UseLocalCardWithInvalidLocal) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -330,7 +331,8 @@ TEST_F(LocalCardMigrationManagerTest, // will trigger migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_UseServerCardWithOneValidLocal) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -379,7 +381,8 @@ TEST_F(LocalCardMigrationManagerTest, // cards as long as the other local cards are not eligible for migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_UseServerCardWithNoneValidLocal) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -421,7 +424,8 @@ TEST_F(LocalCardMigrationManagerTest, // is off, will not trigger migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_FeatureNotEnabled) { // Turn off the experiment flag. - DisableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndDisableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -448,20 +452,22 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_FeatureNotEnabled) { } // Do not trigger migration if user only signs in. -TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_SignInOnly) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); +TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_SignInOnlyWhenExpOff) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillEnableAccountWalletStorage}, + // Disabled + {features::kAutofillEnableLocalCardMigrationForNonSyncUser}); - // Make a non-primary account available with both a refresh token and cookie - // to be in Sync Transport for Wallet mode, in which case this account is - // signed in only without sync enabled. - sync_service_.SetIsAuthenticatedAccountPrimary(false); - sync_service_.SetActiveDataTypes( - syncer::ModelTypeSet(syncer::AUTOFILL_WALLET_DATA)); + // Set the billing_customer_number Priority Preference to designate + // existence of a Payments account. + autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber, + 12345); - base::test::ScopedFeatureList scoped_features; - scoped_features.InitWithFeatures( - /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage}, - /*disabled_features=*/{}); + // Mock Chrome Sync is disabled. + local_card_migration_manager_->ResetSyncState( + AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled); // Add a local credit card whose |TypeAndLastFourDigits| matches what we will // enter below. @@ -483,10 +489,50 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_SignInOnly) { EXPECT_FALSE(local_card_migration_manager_->LocalCardMigrationWasTriggered()); } +// Trigger migration if user only signs in and if experiment is enabled. +TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_SignInOnlyWhenExpOn) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillEnableLocalCardMigrationForNonSyncUser, + features::kAutofillEnableAccountWalletStorage}, + // Disabled + {}); + + // Set the billing_customer_number Priority Preference to designate + // existence of a Payments account. + autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber, + 12345); + + // Mock Chrome Sync is disabled. + local_card_migration_manager_->ResetSyncState( + AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled); + + // Add a local credit card whose |TypeAndLastFourDigits| matches what we will + // enter below. + AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11", + test::NextYear().c_str(), "1", "guid1"); + // Add another local credit card. + AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11", + test::NextYear().c_str(), "1", "guid2"); + + // Set up our credit card form data. + FormData credit_card_form; + test::CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + // Edit the data, and submit. + EditCreditCardFrom(credit_card_form, "Flo Master", "4111111111111111", "11", + test::NextYear().c_str(), "123"); + FormSubmitted(credit_card_form); + EXPECT_TRUE(local_card_migration_manager_->LocalCardMigrationWasTriggered()); +} + // Use one local card with more valid local cards available but billing customer // number is blank, will not trigger migration. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_NoPaymentsAccount) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Add a local credit card whose |TypeAndLastFourDigits| matches what we will // enter below. @@ -512,7 +558,8 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_NoPaymentsAccount) { // migratable. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_LocalCardMatchMaskedServerCard) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -549,7 +596,8 @@ TEST_F(LocalCardMigrationManagerTest, // migratable. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_LocalCardMatchFullServerCard) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -581,7 +629,8 @@ TEST_F(LocalCardMigrationManagerTest, // GetDetectedValues() should includes cardholder name if all cards have it. TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_AllWithCardHolderName) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -613,7 +662,8 @@ TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_AllWithCardHolderName) { // a cardholder name. TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_OneCardWithoutCardHolderName) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -644,7 +694,8 @@ TEST_F(LocalCardMigrationManagerTest, // account. TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_IncludeGooglePaymentsAccount) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -675,7 +726,8 @@ TEST_F(LocalCardMigrationManagerTest, TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ShouldAddMigrateCardsBillableServiceNumberInRequest) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -708,7 +760,8 @@ TEST_F(LocalCardMigrationManagerTest, TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ShouldAddUploadCardSourceInRequest_CheckoutFlow) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -741,7 +794,8 @@ TEST_F(LocalCardMigrationManagerTest, TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ShouldAddUploadCardSourceInRequest_SettingsPage) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -770,7 +824,8 @@ TEST_F(LocalCardMigrationManagerTest, // be triggered. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_TriggerFromSettingsPage) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -809,7 +864,8 @@ TEST_F(LocalCardMigrationManagerTest, // prompt are both triggered. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_TriggerFromSubmittedForm) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -840,7 +896,8 @@ TEST_F(LocalCardMigrationManagerTest, // prompt are not triggered as user previously rejected the prompt. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_DontTriggerFromSubmittedForm) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -877,7 +934,8 @@ TEST_F(LocalCardMigrationManagerTest, // Verify that given the parsed response from the payments client, the migration // status is correctly set. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationSuccess) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -918,7 +976,8 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationSuccess) { // status is correctly set. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationTemporaryFailure) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -961,7 +1020,8 @@ TEST_F(LocalCardMigrationManagerTest, // status is correctly set. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationPermanentFailure) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); // Set the billing_customer_number Priority Preference to designate // existence of a Payments account. @@ -1002,7 +1062,8 @@ TEST_F(LocalCardMigrationManagerTest, // Verify selected cards are correctly passed to manager. TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ToggleIsChosen) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11", test::NextYear().c_str(), "1", "guid1"); AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11", @@ -1025,7 +1086,8 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ToggleIsChosen) { } TEST_F(LocalCardMigrationManagerTest, DeleteLocalCardViaMigrationDialog) { - EnableAutofillCreditCardLocalCardMigrationExperiment(); + scoped_feature_list_.InitAndEnableFeature( + features::kAutofillCreditCardLocalCardMigration); AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11", test::NextYear().c_str(), "1", "guid1"); @@ -1038,4 +1100,175 @@ TEST_F(LocalCardMigrationManagerTest, DeleteLocalCardViaMigrationDialog) { EXPECT_FALSE(personal_data_.GetCreditCardWithGUID("guid1")); } +// Use one local card with more valid local cards available, don't show prompt +// if max strikes reached. +TEST_F(LocalCardMigrationManagerTest, + MigrateLocalCreditCard_MaxStrikesReached) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillLocalCardMigrationUsesStrikeSystemV2}, + // Disabled + {}); + + LocalCardMigrationStrikeDatabase local_card_migration_strike_database = + LocalCardMigrationStrikeDatabase(strike_database_); + local_card_migration_strike_database.AddStrikes(7); + + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 7); + + // Set the billing_customer_number Priority Preference to designate + // existence of a Payments account. + autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber, + 12345); + // Add a local credit card whose |TypeAndLastFourDigits| matches what we will + // enter below. + AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11", + test::NextYear().c_str(), "1", "guid1"); + // Add another local credit card, so it will trigger migration. + AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11", + test::NextYear().c_str(), "1", "guid2"); + + // Set up our credit card form data. + FormData credit_card_form; + test::CreateTestCreditCardFormData(&credit_card_form, true, false); + FormsSeen(std::vector<FormData>(1, credit_card_form)); + + 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); + + // Local card migration not triggered since max strikes have been reached. + EXPECT_FALSE(local_card_migration_manager_->LocalCardMigrationWasTriggered()); + + // Verify that the correct histogram entry was logged. + histogram_tester.ExpectBucketCount( + "Autofill.StrikeDatabase.LocalCardMigrationNotOfferedDueToMaxStrikes", + AutofillMetrics::SaveTypeMetric::LOCAL, 1); +} + +// Use one server card with more valid local cards available, don't show prompt +// if max strikes reached. +TEST_F(LocalCardMigrationManagerTest, + MigrateServerCreditCard_MaxStrikesReached) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillLocalCardMigrationUsesStrikeSystemV2}, + // Disabled + {}); + + LocalCardMigrationStrikeDatabase local_card_migration_strike_database = + LocalCardMigrationStrikeDatabase(strike_database_); + local_card_migration_strike_database.AddStrikes(7); + + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 7); + + // Set the billing_customer_number Priority Preference to designate + // existence of a Payments account. + autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber, + 12345); + + // Add a masked server credit card whose |TypeAndLastFourDigits| matches what + // we will enter below. + CreditCard credit_card(CreditCard::MASKED_SERVER_CARD, "a123"); + test::SetCreditCardInfo(&credit_card, "Flo Master", "1111", "11", + test::NextYear().c_str(), "1"); + credit_card.SetNetworkForMaskedCard(kVisaCard); + personal_data_.AddServerCreditCard(credit_card); + // Add one valid local credit card, so it will trigger migration + AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11", + test::NextYear().c_str(), "1", "guid1"); + + // 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)); + + 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); + + // Local card migration not triggered since max strikes have been reached. + EXPECT_FALSE(local_card_migration_manager_->LocalCardMigrationWasTriggered()); + + // Verify that the correct histogram entry was logged. + histogram_tester.ExpectBucketCount( + "Autofill.StrikeDatabase.LocalCardMigrationNotOfferedDueToMaxStrikes", + AutofillMetrics::SaveTypeMetric::SERVER, 1); +} + +// When local card migration is attempted and some cards aren't selected, +// 3 strikes should be added. +TEST_F(LocalCardMigrationManagerTest, + MigrateCreditCard_StrikesAddedWhenSomeCardsNotSelected) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillLocalCardMigrationUsesStrikeSystemV2}, + // Disabled + {}); + + LocalCardMigrationStrikeDatabase local_card_migration_strike_database = + LocalCardMigrationStrikeDatabase(strike_database_); + // LocalCardMigrationStrikeDatabase should initially have no strikes. + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 0); + + AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11", + test::NextYear().c_str(), "1", "guid1"); + AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11", + test::NextYear().c_str(), "1", "guid2"); + autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber, + 12345); + local_card_migration_manager_->GetMigratableCreditCards(); + + // Only select one of the two cards. + autofill_client_.set_migration_card_selections( + std::vector<std::string>{"guid1"}); + local_card_migration_manager_->AttemptToOfferLocalCardMigration(true); + + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 3); +} + +// When local card migration is accepted, UMA metrics for LocalCardMigration +// strike count is logged. +TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_StrikeCountUMALogged) { + scoped_feature_list_.InitWithFeatures( + // Enabled + {features::kAutofillCreditCardLocalCardMigration, + features::kAutofillLocalCardMigrationUsesStrikeSystemV2}, + // Disabled + {}); + + AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11", + test::NextYear().c_str(), "1", "guid1"); + AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11", + test::NextYear().c_str(), "1", "guid2"); + autofill_client_.GetPrefs()->SetDouble(prefs::kAutofillBillingCustomerNumber, + 12345); + local_card_migration_manager_->GetMigratableCreditCards(); + + // Add 4 LocalCardMigration strikes. + LocalCardMigrationStrikeDatabase local_card_migration_strike_database = + LocalCardMigrationStrikeDatabase(strike_database_); + local_card_migration_strike_database.AddStrikes(4); + EXPECT_EQ(local_card_migration_strike_database.GetStrikes(), 4); + + base::HistogramTester histogram_tester; + + // Select the cards. + autofill_client_.set_migration_card_selections( + std::vector<std::string>{"guid1", "guid2"}); + local_card_migration_manager_->AttemptToOfferLocalCardMigration(true); + + // Verify that the strike count was logged when card migration accepted. + histogram_tester.ExpectBucketCount( + "Autofill.StrikeDatabase.StrikesPresentWhenLocalCardMigrationAccepted", 4, + 1); +} + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc b/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc index 6125d447a75..5c204950aa7 100644 --- a/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc +++ b/chromium/components/autofill/core/browser/local_card_migration_strike_database.cc @@ -8,6 +8,13 @@ namespace autofill { +const int LocalCardMigrationStrikeDatabase::kStrikesToRemoveWhenLocalCardAdded = + 2; +const int LocalCardMigrationStrikeDatabase::kStrikesToAddWhenBubbleClosed = 2; +const int LocalCardMigrationStrikeDatabase::kStrikesToAddWhenDialogClosed = 3; +const int LocalCardMigrationStrikeDatabase:: + kStrikesToAddWhenCardsDeselectedAtMigration = 3; + LocalCardMigrationStrikeDatabase::LocalCardMigrationStrikeDatabase( StrikeDatabase* strike_database) : StrikeDatabaseIntegratorBase(strike_database) { diff --git a/chromium/components/autofill/core/browser/local_card_migration_strike_database.h b/chromium/components/autofill/core/browser/local_card_migration_strike_database.h index ab25114d903..1124374313e 100644 --- a/chromium/components/autofill/core/browser/local_card_migration_strike_database.h +++ b/chromium/components/autofill/core/browser/local_card_migration_strike_database.h @@ -18,6 +18,16 @@ class LocalCardMigrationStrikeDatabase : public StrikeDatabaseIntegratorBase { LocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database); ~LocalCardMigrationStrikeDatabase() override; + // Strikes to remove when user adds new local card. + static const int kStrikesToRemoveWhenLocalCardAdded; + // Strikes to add when user closes LocalCardMigrationBubble. + static const int kStrikesToAddWhenBubbleClosed; + // Strikes to add when user closes LocalCardMigrationDialog. + static const int kStrikesToAddWhenDialogClosed; + // Number of strikes to add when user de-selected some local cards during + // migration. + static const int kStrikesToAddWhenCardsDeselectedAtMigration; + std::string GetProjectPrefix() override; int GetMaxStrikesLimit() override; long long GetExpiryTimeMicros() override; diff --git a/chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc b/chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc deleted file mode 100644 index c7d3ad022d5..00000000000 --- a/chromium/components/autofill/core/browser/local_card_migration_strike_database_unittest.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/core/browser/local_card_migration_strike_database.h" - -#include <utility> -#include <vector> - -#include "base/files/scoped_temp_dir.h" -#include "base/run_loop.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/autofill/core/browser/proto/strike_data.pb.h" -#include "components/autofill/core/browser/test_autofill_clock.h" -#include "components/autofill/core/browser/test_local_card_migration_strike_database.h" -#include "components/autofill/core/common/autofill_clock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace autofill { - -class LocalCardMigrationStrikeDatabaseTest : public ::testing::Test { - public: - LocalCardMigrationStrikeDatabaseTest() - : strike_database_(new StrikeDatabase(InitFilePath())) {} - - protected: - base::HistogramTester* GetHistogramTester() { return &histogram_tester_; } - base::test::ScopedTaskEnvironment scoped_task_environment_; - TestLocalCardMigrationStrikeDatabase strike_database_; - - private: - static const base::FilePath InitFilePath() { - base::ScopedTempDir temp_dir_; - EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); - const base::FilePath file_path = - temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest"); - return file_path; - } - - base::HistogramTester histogram_tester_; -}; - -TEST_F(LocalCardMigrationStrikeDatabaseTest, MaxStrikesLimitReachedTest) { - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); - // 3 strikes added. - strike_database_.AddStrikes(3); - EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); - // 4 strike added, total strike count is 7. - strike_database_.AddStrikes(4); - EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, - LocalCardMigrationNthStrikeAddedHistogram) { - // 2 strikes logged. - strike_database_.AddStrikes(2); - strike_database_.RemoveStrikes(2); - // 1 strike logged. - strike_database_.AddStrike(); - // 2 strikes logged. - strike_database_.AddStrike(); - std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( - "Autofill.StrikeDatabase.NthStrikeAdded.LocalCardMigration"); - // There should be two buckets, for strike counts of 1 and 2. - ASSERT_EQ(2U, buckets.size()); - // Bucket for 1 strike should have count of 1. - EXPECT_EQ(1, buckets[0].count); - // Bucket for 2 strikes should have count of 2. - EXPECT_EQ(2, buckets[1].count); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, - AddStrikeForZeroAndNonZeroStrikesTest) { - EXPECT_EQ(0, strike_database_.GetStrikes()); - strike_database_.AddStrike(); - EXPECT_EQ(1, strike_database_.GetStrikes()); - strike_database_.AddStrikes(2); - EXPECT_EQ(3, strike_database_.GetStrikes()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, - ClearStrikesForNonZeroStrikesTest) { - strike_database_.AddStrikes(3); - EXPECT_EQ(3, strike_database_.GetStrikes()); - strike_database_.ClearStrikes(); - EXPECT_EQ(0, strike_database_.GetStrikes()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, ClearStrikesForZeroStrikesTest) { - strike_database_.ClearStrikes(); - EXPECT_EQ(0, strike_database_.GetStrikes()); -} - -TEST_F(LocalCardMigrationStrikeDatabaseTest, RemoveExpiredStrikesTest) { - autofill::TestAutofillClock test_clock; - test_clock.SetNow(AutofillClock::Now()); - strike_database_.AddStrikes(2); - EXPECT_EQ(2, strike_database_.GetStrikes()); - - // Advance clock to past expiry time. - test_clock.Advance(base::TimeDelta::FromMicroseconds( - strike_database_.GetExpiryTimeMicros() + 1)); - - // One strike should be removed. - strike_database_.RemoveExpiredStrikes(); - EXPECT_EQ(1, strike_database_.GetStrikes()); -} - -} // namespace autofill diff --git a/chromium/components/autofill/core/browser/metrics/address_form_event_logger.cc b/chromium/components/autofill/core/browser/metrics/address_form_event_logger.cc new file mode 100644 index 00000000000..06674d12c2d --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/address_form_event_logger.cc @@ -0,0 +1,91 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/metrics/address_form_event_logger.h" + +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "components/autofill/core/browser/autofill_data_model.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/metrics/form_events.h" + +namespace autofill { + +AddressFormEventLogger::AddressFormEventLogger( + bool is_in_main_frame, + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) + : FormEventLoggerBase("Address", + is_in_main_frame, + form_interactions_ukm_logger) {} + +AddressFormEventLogger::~AddressFormEventLogger() = default; + +void AddressFormEventLogger::OnDidFillSuggestion( + const AutofillProfile& profile, + const FormStructure& form, + const AutofillField& field, + AutofillSyncSigninState sync_state) { + AutofillProfile::RecordType record_type = profile.record_type(); + sync_state_ = sync_state; + + form_interactions_ukm_logger_->LogDidFillSuggestion( + record_type, + /*is_for_for_credit_card=*/false, form, field); + + if (record_type == AutofillProfile::SERVER_PROFILE) { + Log(FORM_EVENT_SERVER_SUGGESTION_FILLED, form); + } else { + Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED, form); + } + + if (!has_logged_suggestion_filled_) { + has_logged_suggestion_filled_ = true; + logged_suggestion_filled_was_server_data_ = + record_type == AutofillProfile::SERVER_PROFILE; + Log(record_type == AutofillProfile::SERVER_PROFILE + ? FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE + : FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + form); + } + + base::RecordAction( + base::UserMetricsAction("Autofill_FilledProfileSuggestion")); +} + +void AddressFormEventLogger::OnDidSeeFillableDynamicForm( + AutofillSyncSigninState sync_state, + const FormStructure& form) { + sync_state_ = sync_state; + Log(FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, form); +} + +void AddressFormEventLogger::OnDidRefill(AutofillSyncSigninState sync_state, + const FormStructure& form) { + sync_state_ = sync_state; + Log(FORM_EVENT_DID_DYNAMIC_REFILL, form); +} + +void AddressFormEventLogger::OnSubsequentRefillAttempt( + AutofillSyncSigninState sync_state, + const FormStructure& form) { + sync_state_ = sync_state; + Log(FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, form); +} + +void AddressFormEventLogger::RecordPollSuggestions() { + base::RecordAction( + base::UserMetricsAction("Autofill_PolledProfileSuggestions")); +} + +void AddressFormEventLogger::RecordParseForm() { + base::RecordAction(base::UserMetricsAction("Autofill_ParsedProfileForm")); +} + +void AddressFormEventLogger::RecordShowSuggestions() { + base::RecordAction( + base::UserMetricsAction("Autofill_ShowedProfileSuggestions")); +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/metrics/address_form_event_logger.h b/chromium/components/autofill/core/browser/metrics/address_form_event_logger.h new file mode 100644 index 00000000000..a115ffbde83 --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/address_form_event_logger.h @@ -0,0 +1,45 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_ADDRESS_FORM_EVENT_LOGGER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_ADDRESS_FORM_EVENT_LOGGER_H_ + +#include "components/autofill/core/browser/autofill_data_model.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/metrics/form_event_logger_base.h" +#include "components/autofill/core/browser/metrics/form_events.h" + +namespace autofill { + +class AddressFormEventLogger : public FormEventLoggerBase { + public: + AddressFormEventLogger( + bool is_in_main_frame, + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger); + + ~AddressFormEventLogger() override; + + void OnDidFillSuggestion(const AutofillProfile& profile, + const FormStructure& form, + const AutofillField& field, + AutofillSyncSigninState sync_state); + + void OnDidSeeFillableDynamicForm(AutofillSyncSigninState sync_state, + const FormStructure& form); + + void OnDidRefill(AutofillSyncSigninState sync_state, + const FormStructure& form); + + void OnSubsequentRefillAttempt(AutofillSyncSigninState sync_state, + const FormStructure& form); + + protected: + void RecordPollSuggestions() override; + void RecordParseForm() override; + void RecordShowSuggestions() override; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_ADDRESS_FORM_EVENT_LOGGER_H_ diff --git a/chromium/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc b/chromium/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc new file mode 100644 index 00000000000..ea19e7317b9 --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc @@ -0,0 +1,194 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h" + +#include <string> + +#include "base/metrics/histogram_functions.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "components/autofill/core/browser/autofill_client.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/form_data_importer.h" +#include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/metrics/form_events.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/validation.h" + +namespace autofill { + +CreditCardFormEventLogger::CreditCardFormEventLogger( + bool is_in_main_frame, + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger, + PersonalDataManager* personal_data_manager, + AutofillClient* client) + : FormEventLoggerBase("CreditCard", + is_in_main_frame, + form_interactions_ukm_logger), + personal_data_manager_(personal_data_manager), + client_(client) {} + +CreditCardFormEventLogger::~CreditCardFormEventLogger() = default; + +void CreditCardFormEventLogger::OnDidSelectMaskedServerCardSuggestion( + const FormStructure& form, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; + + Log(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, form); + if (!has_logged_masked_server_card_suggestion_selected_) { + has_logged_masked_server_card_suggestion_selected_ = true; + Log(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, form); + } +} + +void CreditCardFormEventLogger::SetBankNameAvailable() { + has_logged_bank_name_available_ = true; +} + +void CreditCardFormEventLogger::OnDidFillSuggestion( + const CreditCard& credit_card, + const FormStructure& form, + const AutofillField& field, + AutofillSyncSigninState sync_state) { + CreditCard::RecordType record_type = credit_card.record_type(); + sync_state_ = sync_state; + + form_interactions_ukm_logger_->LogDidFillSuggestion( + record_type, + /*is_for_credit_card=*/true, form, field); + + if (record_type == CreditCard::MASKED_SERVER_CARD) + Log(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, form); + else if (record_type == CreditCard::FULL_SERVER_CARD) + Log(FORM_EVENT_SERVER_SUGGESTION_FILLED, form); + else + Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED, form); + + if (!has_logged_suggestion_filled_) { + has_logged_suggestion_filled_ = true; + logged_suggestion_filled_was_server_data_ = + record_type == CreditCard::MASKED_SERVER_CARD || + record_type == CreditCard::FULL_SERVER_CARD; + logged_suggestion_filled_was_masked_server_card_ = + record_type == CreditCard::MASKED_SERVER_CARD; + if (record_type == CreditCard::MASKED_SERVER_CARD) { + Log(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, form); + if (has_logged_bank_name_available_) { + Log(FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE); + } + } else if (record_type == CreditCard::FULL_SERVER_CARD) { + Log(FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, form); + if (has_logged_bank_name_available_) { + Log(FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE); + } + } else { + Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, form); + } + } + + base::RecordAction( + base::UserMetricsAction("Autofill_FilledCreditCardSuggestion")); +} + +void CreditCardFormEventLogger::RecordPollSuggestions() { + base::RecordAction( + base::UserMetricsAction("Autofill_PolledCreditCardSuggestions")); +} + +void CreditCardFormEventLogger::RecordParseForm() { + base::RecordAction(base::UserMetricsAction("Autofill_ParsedCreditCardForm")); +} + +void CreditCardFormEventLogger::RecordShowSuggestions() { + base::RecordAction( + base::UserMetricsAction("Autofill_ShowedCreditCardSuggestions")); +} + +void CreditCardFormEventLogger::LogWillSubmitForm(const FormStructure& form) { + if (!has_logged_suggestion_filled_) { + Log(FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, form); + } else if (logged_suggestion_filled_was_masked_server_card_) { + Log(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, form); + } else if (logged_suggestion_filled_was_server_data_) { + Log(FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, form); + } else { + Log(FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, form); + } +} + +void CreditCardFormEventLogger::LogFormSubmitted(const FormStructure& form) { + if (!has_logged_suggestion_filled_) { + Log(FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, form); + } else if (logged_suggestion_filled_was_masked_server_card_) { + Log(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, form); + } else if (logged_suggestion_filled_was_server_data_) { + Log(FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, form); + } else { + Log(FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, form); + } +} + +void CreditCardFormEventLogger::LogUkmInteractedWithForm( + FormSignature form_signature) { + form_interactions_ukm_logger_->LogInteractedWithForm( + /*is_for_credit_card=*/true, local_record_type_count_, + server_record_type_count_, form_signature); +} + +void CreditCardFormEventLogger::OnSuggestionsShownOnce() { + if (has_logged_bank_name_available_) { + Log(FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE); + } +} + +void CreditCardFormEventLogger::OnSuggestionsShownSubmittedOnce( + const FormStructure& form) { + if (!has_logged_suggestion_filled_) { + const CreditCard credit_card = + client_->GetFormDataImporter()->ExtractCreditCardFromForm(form); + Log(GetCardNumberStatusFormEvent(credit_card), form); + } +} + +void CreditCardFormEventLogger::OnLog(const std::string& name, + FormEvent event) const { + // Log in a different histogram for credit card forms on nonsecure pages so + // that form interactions on nonsecure pages can be analyzed on their own. + if (!is_context_secure_) { + base::UmaHistogramEnumeration(name + ".OnNonsecurePage", event, + NUM_FORM_EVENTS); + } +} + +void CreditCardFormEventLogger::Log(BankNameDisplayedFormEvent event) const { + DCHECK_LT(event, BANK_NAME_NUM_FORM_EVENTS); + const std::string name("Autofill.FormEvents.CreditCard.BankNameDisplayed"); + base::UmaHistogramEnumeration(name, event, BANK_NAME_NUM_FORM_EVENTS); +} + +FormEvent CreditCardFormEventLogger::GetCardNumberStatusFormEvent( + const CreditCard& credit_card) { + const base::string16 number = credit_card.number(); + FormEvent form_event = + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD; + + if (number.empty()) { + form_event = FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD; + } else if (!HasCorrectLength(number)) { + form_event = + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD; + } else if (!PassesLuhnCheck(number)) { + form_event = + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD; + } else if (personal_data_manager_->IsKnownCard(credit_card)) { + form_event = FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD; + } + + return form_event; +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/metrics/credit_card_form_event_logger.h b/chromium/components/autofill/core/browser/metrics/credit_card_form_event_logger.h new file mode 100644 index 00000000000..67a16324dae --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/credit_card_form_event_logger.h @@ -0,0 +1,91 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_CREDIT_CARD_FORM_EVENT_LOGGER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_CREDIT_CARD_FORM_EVENT_LOGGER_H_ + +#include <string> + +#include "components/autofill/core/browser/autofill_client.h" +#include "components/autofill/core/browser/autofill_data_model.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/metrics/form_event_logger_base.h" +#include "components/autofill/core/browser/metrics/form_events.h" +#include "components/autofill/core/browser/personal_data_manager.h" + +namespace autofill { + +class CreditCardFormEventLogger : public FormEventLoggerBase { + public: + // Form Events for autofill with bank name available for display. + enum BankNameDisplayedFormEvent { + // A dropdown with suggestions was shown and at least one suggestion has a + // bank name. Logged at most once per page load. + FORM_EVENT_SUGGESTIONS_SHOWN_WITH_BANK_NAME_AVAILABLE_ONCE = 0, + // A server suggestion was used to fill the form and at least one suggestion + // has a bank name. Logged at most once per page load. + FORM_EVENT_SERVER_SUGGESTION_FILLED_WITH_BANK_NAME_AVAILABLE_ONCE, + BANK_NAME_NUM_FORM_EVENTS, + }; + + CreditCardFormEventLogger( + bool is_in_main_frame, + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger, + PersonalDataManager* personal_data_manager, + AutofillClient* client); + + ~CreditCardFormEventLogger() override; + + inline void set_is_context_secure(bool is_context_secure) { + is_context_secure_ = is_context_secure; + } + + void OnDidSelectMaskedServerCardSuggestion( + const FormStructure& form, + AutofillSyncSigninState sync_state); + + void SetBankNameAvailable(); + + // In case of masked cards, caller must make sure this gets called before + // the card is upgraded to a full card. + void OnDidFillSuggestion(const CreditCard& credit_card, + const FormStructure& form, + const AutofillField& field, + AutofillSyncSigninState sync_state); + + protected: + // FormEventLoggerBase pure-virtual overrides. + void RecordPollSuggestions() override; + void RecordParseForm() override; + void RecordShowSuggestions() override; + + // FormEventLoggerBase virtual overrides. + void LogWillSubmitForm(const FormStructure& form) override; + void LogFormSubmitted(const FormStructure& form) override; + void LogUkmInteractedWithForm(FormSignature form_signature) override; + void OnSuggestionsShownOnce() override; + void OnSuggestionsShownSubmittedOnce(const FormStructure& form) override; + void OnLog(const std::string& name, FormEvent event) const override; + + // Bringing base class' Log function into scope to allow overloading. + using FormEventLoggerBase::Log; + + private: + void Log(BankNameDisplayedFormEvent event) const; + FormEvent GetCardNumberStatusFormEvent(const CreditCard& credit_card); + + bool is_context_secure_ = false; + bool has_logged_bank_name_available_ = false; + bool has_logged_masked_server_card_suggestion_selected_ = false; + bool logged_suggestion_filled_was_masked_server_card_ = false; + + // Weak references. + PersonalDataManager* personal_data_manager_; + AutofillClient* client_; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_CREDIT_CARD_FORM_EVENT_LOGGER_H_ diff --git a/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc new file mode 100644 index 00000000000..99025b5070b --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc @@ -0,0 +1,199 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/metrics/form_event_logger_base.h" + +#include <string> + +#include "base/metrics/histogram_functions.h" +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "base/time/time.h" +#include "components/autofill/core/browser/autofill_data_model.h" +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/metrics/form_events.h" +#include "components/autofill/core/browser/sync_utils.h" +#include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/signatures_util.h" + +namespace autofill { + +FormEventLoggerBase::FormEventLoggerBase( + const std::string& form_type_name, + bool is_in_main_frame, + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) + : form_type_name_(form_type_name), + is_in_main_frame_(is_in_main_frame), + form_interactions_ukm_logger_(form_interactions_ukm_logger) {} + +FormEventLoggerBase::~FormEventLoggerBase() = default; + +void FormEventLoggerBase::OnDidInteractWithAutofillableForm( + const FormStructure& form, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; + if (!has_logged_interacted_) { + has_logged_interacted_ = true; + LogUkmInteractedWithForm(form.form_signature()); + Log(FORM_EVENT_INTERACTED_ONCE, form); + } +} + +void FormEventLoggerBase::OnDidPollSuggestions( + const FormFieldData& field, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; + // Record only one poll user action for consecutive polls of the same field. + // This is to avoid recording too many poll actions (for example when a user + // types in a field, triggering multiple queries) to make the analysis more + // simple. + if (!field.SameFieldAs(last_polled_field_)) { + RecordPollSuggestions(); + last_polled_field_ = field; + } +} + +void FormEventLoggerBase::OnDidParseForm(const FormStructure& form) { + Log(FORM_EVENT_DID_PARSE_FORM, form); + RecordParseForm(); +} + +void FormEventLoggerBase::OnPopupSuppressed(const FormStructure& form, + const AutofillField& field) { + Log(FORM_EVENT_POPUP_SUPPRESSED, form); + if (!has_logged_popup_suppressed_) { + has_logged_popup_suppressed_ = true; + Log(FORM_EVENT_POPUP_SUPPRESSED_ONCE, form); + } +} + +void FormEventLoggerBase::OnDidShowSuggestions( + const FormStructure& form, + const AutofillField& field, + const base::TimeTicks& form_parsed_timestamp, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; + form_interactions_ukm_logger_->LogSuggestionsShown(form, field, + form_parsed_timestamp); + + Log(FORM_EVENT_SUGGESTIONS_SHOWN, form); + if (!has_logged_suggestions_shown_) { + has_logged_suggestions_shown_ = true; + Log(FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, form); + OnSuggestionsShownOnce(); + } + + RecordShowSuggestions(); +} + +void FormEventLoggerBase::OnWillSubmitForm(AutofillSyncSigninState sync_state, + const FormStructure& form) { + sync_state_ = sync_state; + // Not logging this kind of form if we haven't logged a user interaction. + if (!has_logged_interacted_) + return; + + // Not logging twice. + if (has_logged_will_submit_) + return; + has_logged_will_submit_ = true; + + LogWillSubmitForm(form); + + if (has_logged_suggestions_shown_) { + Log(FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, form); + } + + base::RecordAction(base::UserMetricsAction("Autofill_OnWillSubmitForm")); +} + +void FormEventLoggerBase::OnFormSubmitted(bool force_logging, + AutofillSyncSigninState sync_state, + const FormStructure& form) { + sync_state_ = sync_state; + // Not logging this kind of form if we haven't logged a user interaction. + if (!has_logged_interacted_) + return; + + // Not logging twice. + if (has_logged_submitted_) + return; + has_logged_submitted_ = true; + + LogFormSubmitted(form); + + if (has_logged_suggestions_shown_ || force_logging) { + Log(FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, form); + OnSuggestionsShownSubmittedOnce(form); + } +} + +void FormEventLoggerBase::Log(FormEvent event, + const FormStructure& form) const { + DCHECK_LT(event, NUM_FORM_EVENTS); + std::string name("Autofill.FormEvents." + form_type_name_); + base::UmaHistogramEnumeration(name, event, NUM_FORM_EVENTS); + + // Log UKM metrics for only autofillable form events. + if (form.IsAutofillable()) { + form_interactions_ukm_logger_->LogFormEvent(event, form.GetFormTypes(), + form.form_parsed_timestamp()); + } + + // Log again in a different histogram so that iframes can be analyzed on + // their own. + base::UmaHistogramEnumeration( + name + (is_in_main_frame_ ? ".IsInMainFrame" : ".IsInIFrame"), event, + NUM_FORM_EVENTS); + + // Allow specialized type of logging. + OnLog(name, event); + + // Logging again in a different histogram for segmentation purposes. + if (server_record_type_count_ == 0 && local_record_type_count_ == 0) + name += ".WithNoData"; + else if (server_record_type_count_ > 0 && local_record_type_count_ == 0) + name += ".WithOnlyServerData"; + else if (server_record_type_count_ == 0 && local_record_type_count_ > 0) + name += ".WithOnlyLocalData"; + else + name += ".WithBothServerAndLocalData"; + base::UmaHistogramEnumeration(name, event, NUM_FORM_EVENTS); + base::UmaHistogramEnumeration( + name + AutofillMetrics::GetMetricsSyncStateSuffix(sync_state_), event, + NUM_FORM_EVENTS); +} + +void FormEventLoggerBase::LogWillSubmitForm(const FormStructure& form) { + if (!has_logged_suggestion_filled_) { + Log(FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, form); + } else if (logged_suggestion_filled_was_server_data_) { + Log(FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, form); + } else { + Log(FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, form); + } +} + +void FormEventLoggerBase::LogFormSubmitted(const FormStructure& form) { + if (!has_logged_suggestion_filled_) { + Log(FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, form); + } else if (logged_suggestion_filled_was_server_data_) { + Log(FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, form); + } else { + Log(FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, form); + } +} + +void FormEventLoggerBase::LogUkmInteractedWithForm( + FormSignature form_signature) { + form_interactions_ukm_logger_->LogInteractedWithForm( + /*is_for_credit_card=*/false, local_record_type_count_, + server_record_type_count_, form_signature); +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h new file mode 100644 index 00000000000..173df3b0ddd --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h @@ -0,0 +1,107 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_FORM_EVENT_LOGGER_BASE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_FORM_EVENT_LOGGER_BASE_H_ + +#include <string> + +#include "components/autofill/core/browser/autofill_data_model.h" +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/metrics/form_events.h" +#include "components/autofill/core/browser/sync_utils.h" +#include "components/autofill/core/common/form_field_data.h" + +namespace autofill { + +// Utility to log autofill form events in the relevant histograms depending on +// the presence of server and/or local data. +class FormEventLoggerBase { + public: + FormEventLoggerBase( + const std::string& form_type_name, + bool is_in_main_frame, + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger); + + inline void set_server_record_type_count(size_t server_record_type_count) { + server_record_type_count_ = server_record_type_count; + } + + inline void set_local_record_type_count(size_t local_record_type_count) { + local_record_type_count_ = local_record_type_count; + } + + void OnDidInteractWithAutofillableForm(const FormStructure& form, + AutofillSyncSigninState sync_state); + + void OnDidPollSuggestions(const FormFieldData& field, + AutofillSyncSigninState sync_state); + + void OnDidParseForm(const FormStructure& form); + + void OnPopupSuppressed(const FormStructure& form, const AutofillField& field); + + void OnDidShowSuggestions(const FormStructure& form, + const AutofillField& field, + const base::TimeTicks& form_parsed_timestamp, + AutofillSyncSigninState sync_state); + + void OnWillSubmitForm(AutofillSyncSigninState sync_state, + const FormStructure& form); + + void OnFormSubmitted(bool force_logging, + AutofillSyncSigninState sync_state, + const FormStructure& form); + + protected: + virtual ~FormEventLoggerBase(); + + void Log(FormEvent event, const FormStructure& form) const; + + virtual void RecordPollSuggestions() = 0; + virtual void RecordParseForm() = 0; + virtual void RecordShowSuggestions() = 0; + + virtual void LogWillSubmitForm(const FormStructure& form); + virtual void LogFormSubmitted(const FormStructure& form); + + // Only used for UKM backward compatibility since it depends on IsCreditCard. + // TODO (crbug.com/925913): Remove IsCreditCard from UKM logs amd replace with + // |form_type_name_|. + virtual void LogUkmInteractedWithForm(FormSignature form_signature); + + virtual void OnSuggestionsShownOnce() {} + virtual void OnSuggestionsShownSubmittedOnce(const FormStructure& form) {} + virtual void OnLog(const std::string& name, FormEvent event) const {} + + // Constructor parameters. + std::string form_type_name_; + bool is_in_main_frame_; + + // State variables. + size_t server_record_type_count_ = 0; + size_t local_record_type_count_ = 0; + bool has_logged_interacted_ = false; + bool has_logged_popup_suppressed_ = false; + bool has_logged_suggestions_shown_ = false; + bool has_logged_suggestion_filled_ = false; + bool has_logged_will_submit_ = false; + bool has_logged_submitted_ = false; + bool logged_suggestion_filled_was_server_data_ = false; + + // The last field that was polled for suggestions. + FormFieldData last_polled_field_; + + // Weak reference. + AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger_; + + AutofillSyncSigninState sync_state_ = AutofillSyncSigninState::kNumSyncStates; +}; +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_FORM_EVENT_LOGGER_BASE_H_ diff --git a/chromium/components/autofill/core/browser/metrics/form_events.h b/chromium/components/autofill/core/browser/metrics/form_events.h new file mode 100644 index 00000000000..40cbbe0517d --- /dev/null +++ b/chromium/components/autofill/core/browser/metrics/form_events.h @@ -0,0 +1,97 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_FORM_EVENTS_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_FORM_EVENTS_H_ + +namespace autofill { + +// Form Events for autofill. +// These events are triggered separetly for address and credit card forms. +enum FormEvent { + // User interacted with a field of this kind of form. Logged only once per + // page load. + FORM_EVENT_INTERACTED_ONCE = 0, + // A dropdown with suggestions was shown. + FORM_EVENT_SUGGESTIONS_SHOWN, + // Same as above, but recoreded only once per page load. + FORM_EVENT_SUGGESTIONS_SHOWN_ONCE, + // A local suggestion was used to fill the form. + FORM_EVENT_LOCAL_SUGGESTION_FILLED, + // A server suggestion was used to fill the form. + // When dealing with credit cards, this means a full server card was used + // to fill. + FORM_EVENT_SERVER_SUGGESTION_FILLED, + // A masked server card suggestion was used to fill the form. + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, + // A suggestion was used to fill the form. The origin type (local or server + // or masked server card) of the first selected within a page load will + // determine which of the following two will be fired. + FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, + FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE, + // A form was submitted. Depending on the user filling a local, server, + // masked server card or no suggestion one of the following will be + // triggered. Only one of the following four will be triggered per page + // load. + FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, + FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE, + FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE, + // A masked server card suggestion was selected to fill the form. + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, + // Same as above but only triggered once per page load. + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE, + // An autofillable form is about to be submitted. If the submission is not + // interrupted by JavaScript, the "form submitted" events above will also be + // logged. Depending on the user filling a local, server, masked server card + // or no suggestion one of the following will be triggered, at most once per + // page load. + FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, + FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, + FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, + FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_WILL_SUBMIT_ONCE, + // A dropdown with suggestions was shown and a form was submitted after + // that. + FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, + // A dropdown with suggestions was shown and a form is about to be + // submitted. If the submission is not interrupted by JavaScript, the "form + // submitted" event above will also be logged. + FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, + // A dropdown with credit card suggestions was shown, but they were not used + // to fill the form. Depending on the user submitting a card known by the + // browser, submitting a card that the browser does not know about, + // submitting with an empty card number, submitting with a card number of + // wrong size or submitting with a card number that does not pass luhn + // check, one of the following will be triggered. At most one of the + // following five metrics will be triggered per submit. + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, + FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, + + // The form was changed dynamically. This value has been deprecated. + FORM_EVENT_DID_SEE_DYNAMIC_FORM, + // The form was changed dynamically and was fillable. + FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, + // There was a dynamic change of the form and it got re-filled + // automatically. + FORM_EVENT_DID_DYNAMIC_REFILL, + // The form dynamically changed another time after the refill. + FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, + // The popup was suppressed because the native view couldn't be created. + FORM_EVENT_POPUP_SUPPRESSED, + // Same as above, but recoreded only once per page load. + FORM_EVENT_POPUP_SUPPRESSED_ONCE, + + // The form was parsed. + FORM_EVENT_DID_PARSE_FORM, + + NUM_FORM_EVENTS, +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_FORM_EVENTS_H_
\ No newline at end of file diff --git a/chromium/components/autofill/core/browser/password_requirements_spec_fetcher_impl.cc b/chromium/components/autofill/core/browser/password_requirements_spec_fetcher_impl.cc index 2c065752666..ff4367110f0 100644 --- a/chromium/components/autofill/core/browser/password_requirements_spec_fetcher_impl.cc +++ b/chromium/components/autofill/core/browser/password_requirements_spec_fetcher_impl.cc @@ -4,6 +4,7 @@ #include "components/autofill/core/browser/password_requirements_spec_fetcher_impl.h" +#include "base/bind.h" #include "base/logging.h" #include "base/md5.h" #include "base/metrics/histogram_functions.h" diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc index ac4803ae4a3..3fda27d89e6 100644 --- a/chromium/components/autofill/core/browser/payments/payments_client.cc +++ b/chromium/components/autofill/core/browser/payments/payments_client.cc @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/command_line.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" @@ -342,7 +343,8 @@ class GetUploadDetailsRequest : public PaymentsRequest { const std::string& app_locale, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, - std::unique_ptr<base::Value>)> callback, + std::unique_ptr<base::Value>, + std::vector<std::pair<int, int>>)> callback, const int billable_service_number, PaymentsClient::UploadCardSource upload_card_source) : addresses_(addresses), @@ -441,6 +443,16 @@ class GetUploadDetailsRequest : public PaymentsRequest { base::Value* dictionary_value = response.FindKey("legal_message"); if (dictionary_value) legal_message_ = std::make_unique<base::Value>(dictionary_value->Clone()); + + base::Value* list_ptr = response.FindKey("supported_card_bin_ranges"); + if (list_ptr && list_ptr->is_list()) { + for (base::Value& result : list_ptr->GetList()) { + DCHECK(result.is_dict()); + base::Optional<int> start = response.FindIntKey("start"); + base::Optional<int> end = response.FindIntKey("end"); + supported_card_bin_ranges_.push_back(std::make_pair(*start, *end)); + } + } } bool IsResponseComplete() override { @@ -448,7 +460,8 @@ class GetUploadDetailsRequest : public PaymentsRequest { } void RespondToDelegate(AutofillClient::PaymentsRpcResult result) override { - std::move(callback_).Run(result, context_token_, std::move(legal_message_)); + std::move(callback_).Run(result, context_token_, std::move(legal_message_), + supported_card_bin_ranges_); } private: @@ -459,10 +472,12 @@ class GetUploadDetailsRequest : public PaymentsRequest { std::string app_locale_; base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, - std::unique_ptr<base::Value>)> + std::unique_ptr<base::Value>, + std::vector<std::pair<int, int>>)> callback_; base::string16 context_token_; std::unique_ptr<base::Value> legal_message_; + std::vector<std::pair<int, int>> supported_card_bin_ranges_; const int billable_service_number_; PaymentsClient::UploadCardSource upload_card_source_; }; @@ -770,7 +785,8 @@ void PaymentsClient::GetUploadDetails( const std::string& app_locale, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, - std::unique_ptr<base::Value>)> callback, + std::unique_ptr<base::Value>, + std::vector<std::pair<int, int>>)> callback, const int billable_service_number, UploadCardSource upload_card_source) { IssueRequest( @@ -845,11 +861,11 @@ void PaymentsClient::InitializeResourceRequest() { // Add Chrome experiment state to the request headers. net::HttpRequestHeaders headers; // User is always signed-in to be able to upload card to Google Payments. - variations::AppendVariationHeaders( + variations::AppendVariationsHeader( resource_request_->url, is_off_the_record_ ? variations::InIncognito::kYes : variations::InIncognito::kNo, - variations::SignedIn::kYes, &resource_request_->headers); + variations::SignedIn::kYes, resource_request_.get()); } } @@ -878,7 +894,8 @@ void PaymentsClient::OnSimpleLoaderCompleteInternal(int response_code, // Valid response. case net::HTTP_OK: { std::string error_code; - std::unique_ptr<base::Value> message_value = base::JSONReader::Read(data); + std::unique_ptr<base::Value> message_value = + base::JSONReader::ReadDeprecated(data); if (message_value.get() && message_value->is_dict()) { response_dict = base::Value::FromUniquePtrValue(std::move(message_value)); diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h index be0bc533999..ad6c075aa75 100644 --- a/chromium/components/autofill/core/browser/payments/payments_client.h +++ b/chromium/components/autofill/core/browser/payments/payments_client.h @@ -5,6 +5,8 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CLIENT_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CLIENT_H_ +#include <utility> + #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" @@ -178,7 +180,8 @@ class PaymentsClient { const std::string& app_locale, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, - std::unique_ptr<base::Value>)> callback, + std::unique_ptr<base::Value>, + std::vector<std::pair<int, int>>)> callback, const int billable_service_number, UploadCardSource upload_card_source = UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE); 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 1b733047735..6f9edcede0d 100644 --- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc +++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc @@ -5,6 +5,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/command_line.h" #include "base/macros.h" #include "base/strings/string_piece.h" @@ -24,6 +25,7 @@ #include "components/autofill/core/common/autofill_switches.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" +#include "components/variations/net/variations_http_headers.h" #include "components/variations/variations_associated_data.h" #include "components/variations/variations_http_header_provider.h" #include "services/identity/public/cpp/identity_test_environment.h" @@ -64,11 +66,13 @@ class PaymentsClientTest : public testing::Test { server_id_.clear(); real_pan_.clear(); legal_message_.reset(); + has_variations_header_ = false; factory()->SetInterceptor(base::BindLambdaForTesting( [&](const network::ResourceRequest& request) { intercepted_headers_ = request.headers; intercepted_body_ = network::GetUploadData(request); + has_variations_header_ = variations::HasVariationsHeader(request); })); test_shared_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( @@ -115,11 +119,14 @@ class PaymentsClientTest : public testing::Test { real_pan_ = real_pan; } - void OnDidGetUploadDetails(AutofillClient::PaymentsRpcResult result, - const base::string16& context_token, - std::unique_ptr<base::Value> legal_message) { + void OnDidGetUploadDetails( + AutofillClient::PaymentsRpcResult result, + const base::string16& context_token, + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_card_bin_ranges) { result_ = result; legal_message_ = std::move(legal_message); + supported_card_bin_ranges_ = supported_card_bin_ranges; } void OnDidUploadCard(AutofillClient::PaymentsRpcResult result, @@ -207,7 +214,7 @@ class PaymentsClientTest : public testing::Test { const std::string& GetUploadData() { return intercepted_body_; } - net::HttpRequestHeaders* GetRequestHeaders() { return &intercepted_headers_; } + bool HasVariationsHeader() { return has_variations_header_; } // Issues access token in response to any access token request. This will // start the Payments Request which requires the authentication. @@ -233,6 +240,7 @@ class PaymentsClientTest : public testing::Test { std::string server_id_; std::string real_pan_; std::unique_ptr<base::Value> legal_message_; + std::vector<std::pair<int, int>> supported_card_bin_ranges_; std::vector<MigratableCreditCard> migratable_credit_cards_; std::unique_ptr<std::unordered_map<std::string, std::string>> save_result_; std::string display_text_; @@ -245,6 +253,7 @@ class PaymentsClientTest : public testing::Test { identity::IdentityTestEnvironment identity_test_env_; net::HttpRequestHeaders intercepted_headers_; + bool has_variations_header_; std::string intercepted_body_; base::WeakPtrFactory<PaymentsClientTest> weak_ptr_factory_; @@ -536,10 +545,8 @@ TEST_F(PaymentsClientTest, GetUploadDetailsVariationsTest) { CreateFieldTrialWithId("AutofillTest", "Group", 369); StartGettingUploadDetails(); - 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()); + EXPECT_TRUE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -554,10 +561,8 @@ TEST_F(PaymentsClientTest, GetUploadDetailsVariationsTestExperimentFlagOff) { CreateFieldTrialWithId("AutofillTest", "Group", 369); StartGettingUploadDetails(); - 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()); + EXPECT_FALSE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -572,10 +577,8 @@ TEST_F(PaymentsClientTest, UploadCardVariationsTest) { StartUploading(/*include_cvc=*/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()); + EXPECT_TRUE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -590,10 +593,8 @@ TEST_F(PaymentsClientTest, UploadCardVariationsTestExperimentFlagOff) { CreateFieldTrialWithId("AutofillTest", "Group", 369); StartUploading(/*include_cvc=*/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()); + EXPECT_FALSE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -608,10 +609,8 @@ TEST_F(PaymentsClientTest, UnmaskCardVariationsTest) { StartUnmasking(); 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()); + EXPECT_TRUE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -626,10 +625,8 @@ TEST_F(PaymentsClientTest, UnmaskCardVariationsTestExperimentOff) { CreateFieldTrialWithId("AutofillTest", "Group", 369); StartUnmasking(); - 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()); + EXPECT_FALSE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -645,10 +642,8 @@ TEST_F(PaymentsClientTest, MigrateCardsVariationsTest) { StartMigrating(/*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()); + EXPECT_TRUE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } @@ -663,10 +658,8 @@ TEST_F(PaymentsClientTest, MigrateCardsVariationsTestExperimentFlagOff) { CreateFieldTrialWithId("AutofillTest", "Group", 369); StartMigrating(/*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()); + EXPECT_FALSE(HasVariationsHeader()); variations::VariationsHttpHeaderProvider::GetInstance()->ResetForTesting(); } 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 8bf0f86a13d..e58fe67248f 100644 --- a/chromium/components/autofill/core/browser/payments/test_payments_client.cc +++ b/chromium/components/autofill/core/browser/payments/test_payments_client.cc @@ -30,7 +30,8 @@ void TestPaymentsClient::GetUploadDetails( const std::string& app_locale, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, - std::unique_ptr<base::Value>)> callback, + std::unique_ptr<base::Value>, + std::vector<std::pair<int, int>>)> callback, const int billable_service_number, PaymentsClient::UploadCardSource upload_card_source) { upload_details_addresses_ = addresses; @@ -38,11 +39,11 @@ void TestPaymentsClient::GetUploadDetails( active_experiments_ = active_experiments; billable_service_number_ = billable_service_number; upload_card_source_ = upload_card_source; - std::move(callback).Run(app_locale == "en-US" - ? AutofillClient::SUCCESS - : AutofillClient::PERMANENT_FAILURE, - base::ASCIIToUTF16("this is a context token"), - std::unique_ptr<base::Value>(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::Value>(nullptr), supported_card_bin_ranges_); } void TestPaymentsClient::UploadCard( @@ -71,5 +72,10 @@ void TestPaymentsClient::SetSaveResultForCardsMigration( save_result_ = std::move(save_result); } +void TestPaymentsClient::SetSupportedBINRanges( + std::vector<std::pair<int, int>> bin_ranges) { + supported_card_bin_ranges_ = bin_ranges; +} + } // 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 01e9d008903..e7f6c928e48 100644 --- a/chromium/components/autofill/core/browser/payments/test_payments_client.h +++ b/chromium/components/autofill/core/browser/payments/test_payments_client.h @@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_TEST_PAYMENTS_CLIENT_H_ #include <string> +#include <utility> #include <vector> #include "components/autofill/core/browser/payments/payments_client.h" @@ -34,7 +35,8 @@ class TestPaymentsClient : public payments::PaymentsClient { const std::string& app_locale, base::OnceCallback<void(AutofillClient::PaymentsRpcResult, const base::string16&, - std::unique_ptr<base::Value>)> callback, + std::unique_ptr<base::Value>, + std::vector<std::pair<int, int>>)> callback, const int billable_service_number, UploadCardSource upload_card_source = UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE) override; @@ -55,6 +57,8 @@ class TestPaymentsClient : public payments::PaymentsClient { std::unique_ptr<std::unordered_map<std::string, std::string>> save_result); + void SetSupportedBINRanges(std::vector<std::pair<int, int>> bin_ranges); + int detected_values_in_upload_details() const { return detected_values_; } const std::vector<AutofillProfile>& addresses_in_upload_details() const { return upload_details_addresses_; @@ -74,6 +78,7 @@ class TestPaymentsClient : public payments::PaymentsClient { private: std::string server_id_; + std::vector<std::pair<int, int>> supported_card_bin_ranges_; std::vector<AutofillProfile> upload_details_addresses_; std::vector<AutofillProfile> upload_card_addresses_; int detected_values_; diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc index 7c66782f7a5..902884a4b06 100644 --- a/chromium/components/autofill/core/browser/personal_data_manager.cc +++ b/chromium/components/autofill/core/browser/personal_data_manager.cc @@ -13,6 +13,7 @@ #include <string> #include <utility> +#include "base/bind.h" #include "base/callback.h" #include "base/feature_list.h" #include "base/i18n/case_conversion.h" @@ -268,7 +269,6 @@ void PersonalDataManager::Init( identity::IdentityManager* identity_manager, AutofillProfileValidator* client_profile_validator, history::HistoryService* history_service, - GaiaCookieManagerService* cookie_manager_service, bool is_off_the_record) { CountryNames::SetLocaleString(app_locale_); database_helper_->Init(profile_database, account_database); @@ -287,12 +287,11 @@ void PersonalDataManager::Init( if (history_service_) history_service_->AddObserver(this); - // Listen for cookie deletion by the user. - cookie_manager_service_ = cookie_manager_service; - if (cookie_manager_service_) - cookie_manager_service_->AddObserver(this); - + // Listen for account cookie deletion by the user. identity_manager_ = identity_manager; + if (identity_manager_) + identity_manager_->AddObserver(this); + is_off_the_record_ = is_off_the_record; if (!is_off_the_record_) @@ -340,9 +339,9 @@ void PersonalDataManager::Shutdown() { history_service_->RemoveObserver(this); history_service_ = nullptr; - if (cookie_manager_service_) - cookie_manager_service_->RemoveObserver(this); - cookie_manager_service_ = nullptr; + if (identity_manager_) + identity_manager_->RemoveObserver(this); + identity_manager_ = nullptr; } void PersonalDataManager::OnSyncServiceInitialized( @@ -483,16 +482,12 @@ void PersonalDataManager::OnWebDataServiceRequestDone( } is_data_loaded_ = true; - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " refresh is done, notifying PersonalDataChanged"; NotifyPersonalDataChanged(); } } void PersonalDataManager::AutofillMultipleChanged() { has_synced_new_data_ = true; - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " has synced new data, refreshing"; Refresh(); } @@ -536,7 +531,7 @@ void PersonalDataManager::OnSyncShutdown(syncer::SyncService* sync_service) { sync_service_ = nullptr; } -AccountInfo PersonalDataManager::GetAccountInfoForPaymentsServer() const { +CoreAccountInfo 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. @@ -558,7 +553,7 @@ bool PersonalDataManager::IsSyncFeatureEnabled() const { !database_helper_->IsUsingAccountStorageForServerData(); } -void PersonalDataManager::OnGaiaCookieDeletedByUserAction() { +void PersonalDataManager::OnAccountsCookieDeletedByUserAction() { // Clear all the Sync Transport feature opt-ins. ::autofill::prefs::ClearSyncTransportOptIns(pref_service_); } @@ -630,19 +625,19 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) { AutofillProfile* profile = GetProfileByGUID(data_model.guid()); if (profile) { - if (profile->record_type() == AutofillProfile::LOCAL_PROFILE) { - // We can't make the change directly on the web_profiles_, the update - // should happen in the database first. - AutofillProfile updated_profile(*profile); - updated_profile.RecordAndLogUse(); - UpdateProfileInDB(updated_profile); - } else if (profile->record_type() == AutofillProfile::SERVER_PROFILE) { - profile->RecordAndLogUse(); - // TODO(crbug.com/864519): Update this once addresses support account - // storage, and also use the server database. - database_helper_->GetLocalDatabase()->UpdateServerAddressMetadata( - *profile); - Refresh(); + profile->RecordAndLogUse(); + + switch (profile->record_type()) { + case AutofillProfile::LOCAL_PROFILE: + UpdateProfileInDB(*profile, /*enforced=*/true); + break; + case AutofillProfile::SERVER_PROFILE: + DCHECK(database_helper_->GetServerDatabase()) + << "Recording use of server address without server storage."; + database_helper_->GetServerDatabase()->UpdateServerAddressMetadata( + *profile); + Refresh(); + break; } } } @@ -1006,19 +1001,45 @@ void PersonalDataManager::UpdateClientValidityStates( bool update_validation = pref_service_->GetInteger(prefs::kAutofillLastVersionValidated) < CHROME_VERSION_MAJOR; + + DVLOG(1) << "Autofill profile client validation " + << (update_validation ? "needs to be" : "has already been") + << " performed for this version"; + for (const auto* profile : profiles) { if (!profile->is_client_validity_states_updated() || update_validation) { + profile->set_is_client_validity_states_updated(false); + ongoing_profile_changes_[profile->guid()].push_back( + AutofillProfileDeepChange(AutofillProfileChange::UPDATE, *profile)); + ongoing_profile_changes_[profile->guid()].back().set_enforce_update(); client_profile_validator_->StartProfileValidation( profile, base::BindOnce(&PersonalDataManager::OnValidated, weak_factory_.GetWeakPtr())); } } + // Set the pref to the current major version if already not set. if (update_validation) pref_service_->SetInteger(prefs::kAutofillLastVersionValidated, CHROME_VERSION_MAJOR); } +bool PersonalDataManager::UpdateClientValidityStates( + const AutofillProfile& profile) { + if (!base::FeatureList::IsEnabled( + autofill::features::kAutofillProfileClientValidation) || + !client_profile_validator_ || + profile.is_client_validity_states_updated()) { + OnValidated(&profile); + return false; + } + + client_profile_validator_->StartProfileValidation( + &profile, base::BindOnce(&PersonalDataManager::OnValidated, + weak_factory_.GetWeakPtr())); + return true; +} + std::vector<AutofillProfile*> PersonalDataManager::GetServerProfiles() const { std::vector<AutofillProfile*> result; if (!IsAutofillProfileEnabled()) @@ -1078,55 +1099,30 @@ std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest() std::vector<AutofillProfile*> profiles = GetProfiles(); - // Rank the suggestions by frecency (see AutofillDataModel for details). + bool use_server_validation = base::FeatureList::IsEnabled( + autofill::features::kAutofillProfileServerValidation); + bool use_client_validation = base::FeatureList::IsEnabled( + autofill::features::kAutofillProfileClientValidation); + + // Rank the suggestions by frescocency (see AutofillDataModel for details). + // Frescocency is frecency + validity score. const base::Time comparison_time = AutofillClock::Now(); std::sort(profiles.begin(), profiles.end(), - [comparison_time](const AutofillDataModel* a, - const AutofillDataModel* b) { - return a->CompareFrecency(b, comparison_time); + [comparison_time, use_client_validation, use_server_validation]( + const AutofillProfile* a, const AutofillProfile* b) { + return a->HasGreaterFrescocencyThan(b, comparison_time, + use_client_validation, + use_server_validation); }); return profiles; } -// static -void PersonalDataManager::MaybeRemoveInvalidSuggestions( - const AutofillType& type, - std::vector<AutofillProfile*>* profiles) { - const bool suggest_invalid = base::FeatureList::IsEnabled( - features::kAutofillSuggestInvalidProfileData); - - for (size_t i = 0; i < profiles->size(); ++i) { - bool is_client_invalid = - (*profiles)[i]->GetValidityState(type.GetStorableType(), - AutofillProfile::CLIENT) == - AutofillProfile::INVALID; - - bool is_server_invalid = - (*profiles)[i]->GetValidityState(type.GetStorableType(), - AutofillProfile::SERVER) == - AutofillProfile::INVALID; - - if ((is_server_invalid || is_client_invalid) && !suggest_invalid) - (*profiles)[i] = nullptr; - if (is_server_invalid || is_client_invalid) - UMA_HISTOGRAM_BOOLEAN("Autofill.InvalidProfileData.UsedForSuggestion", - suggest_invalid); - } - - if (!suggest_invalid) { - profiles->erase( - std::stable_partition(profiles->begin(), profiles->end(), - [](AutofillProfile* p) { return p != nullptr; }), - profiles->end()); - } -} - std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( const AutofillType& type, const base::string16& field_contents, bool field_is_autofilled, - const std::vector<ServerFieldType>& other_field_types) { + const std::vector<ServerFieldType>& field_types) { if (IsInAutofillSuggestionsDisabledExperiment()) return std::vector<Suggestion>(); @@ -1134,6 +1130,11 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( base::string16 field_contents_canon = comparator.NormalizeForComparison(field_contents); + if (base::FeatureList::IsEnabled( + autofill::features::kAutofillProfileServerValidation)) { + UpdateProfilesServerValidityMapsIfNeeded(GetProfiles()); + } + // Get the profiles to suggest, which are already sorted. std::vector<AutofillProfile*> sorted_profiles = GetProfilesToSuggest(); @@ -1147,9 +1148,6 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( suggestion_selection::RemoveProfilesNotUsedSinceTimestamp( min_last_used, &sorted_profiles); } - // We need the updated information on the validity states of the profiles. - UpdateProfilesServerValidityMapsIfNeeded(sorted_profiles); - MaybeRemoveInvalidSuggestions(type, &sorted_profiles); } std::vector<AutofillProfile*> matched_profiles; @@ -1161,19 +1159,21 @@ std::vector<Suggestion> PersonalDataManager::GetProfileSuggestions( // Don't show two suggestions if one is a subset of the other. std::vector<AutofillProfile*> unique_matched_profiles; std::vector<Suggestion> unique_suggestions = - suggestion_selection::GetUniqueSuggestions(other_field_types, app_locale_, + suggestion_selection::GetUniqueSuggestions(field_types, app_locale_, matched_profiles, suggestions, &unique_matched_profiles); // Generate disambiguating labels based on the list of matches. std::vector<base::string16> labels; - AutofillProfile::CreateInferredLabels( - unique_matched_profiles, &other_field_types, type.GetStorableType(), 1, - app_locale_, &labels); + AutofillProfile::CreateInferredLabels(unique_matched_profiles, &field_types, + type.GetStorableType(), 1, app_locale_, + &labels); DCHECK_EQ(unique_suggestions.size(), labels.size()); for (size_t i = 0; i < labels.size(); i++) { + // A suggestion's label has one line of disambiguating information to show + // to the user. However, when the two-line suggestion display experiment is + // enabled on desktop, label is replaced by additional label. unique_suggestions[i].label = labels[i]; - // Used when two-line display is enabled. unique_suggestions[i].additional_label = labels[i]; } @@ -1212,7 +1212,7 @@ const std::vector<CreditCard*> PersonalDataManager::GetCreditCardsToSuggest( if (a_is_expired != b->IsExpired(comparison_time)) return !a_is_expired; - return a->CompareFrecency(b, comparison_time); + return a->HasGreaterFrecencyThan(b, comparison_time); }); return cards_to_suggest; @@ -1342,7 +1342,7 @@ void PersonalDataManager::ClearProfileNonSettingsOrigins() { for (AutofillProfile* profile : GetProfiles()) { if (profile->origin() != kSettingsOrigin && !profile->origin().empty()) { profile->set_origin(std::string()); - UpdateProfileInDB(*profile); + UpdateProfileInDB(*profile, /*enforced=*/true); } } @@ -1386,9 +1386,7 @@ void PersonalDataManager::MoveJapanCityToStreetAddress() { : street_address + line_separator + city; profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, street_address); profile->SetRawInfo(ADDRESS_HOME_CITY, base::string16()); - - // Make the update. - UpdateProfileInDB(*profile); + UpdateProfileInDB(*profile, /*enforced=*/true); } } @@ -1397,17 +1395,36 @@ void PersonalDataManager::MoveJapanCityToStreetAddress() { } void PersonalDataManager::OnValidated(const AutofillProfile* profile) { - // We always set a value for country validity state. - DCHECK(profile->GetValidityState(ServerFieldType::ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT) != - AutofillProfile::UNVALIDATED); + if (!profile) + return; + + if (!ProfileChangesAreOnGoing(profile->guid())) + return; // Set the validity states updated, only when the validation has occurred. If // the rules were not loaded for any reason, don't set the flag. - if (profile->GetValidityState(ServerFieldType::ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT) != - AutofillProfile::UNVALIDATED) - profile->set_is_client_validity_states_updated(true); + bool validity_updated = + (profile->GetValidityState(ServerFieldType::ADDRESS_HOME_COUNTRY, + AutofillProfile::CLIENT) != + AutofillProfile::UNVALIDATED); + + // For every relevant profile change on the ongoing_profile_changes_, mark the + // change to show that the validation is done, and set the validity of the + // profile if the validity was updated. + for (const auto& change : ongoing_profile_changes_[profile->guid()]) { + if (!profile->EqualsForClientValidationPurpose(*(change.profile()))) + continue; + + change.validation_effort_made(); + + if (validity_updated) { + change.profile()->set_is_client_validity_states_updated(true); + change.profile()->SetClientValidityFromBitfieldValue( + profile->GetClientValidityBitfieldValue()); + } + } + + HandleNextProfileChange(profile->guid()); } const ProfileValidityMap& PersonalDataManager::GetProfileValidityByGUID( @@ -1450,7 +1467,7 @@ std::string PersonalDataManager::MergeProfile( const std::unique_ptr<AutofillProfile>& b) { if (a->IsVerified() != b->IsVerified()) return !a->IsVerified(); - return a->CompareFrecency(b.get(), comparison_time); + return a->HasGreaterFrecencyThan(b.get(), comparison_time); }); // Set to true if |existing_profiles| already contains an equivalent profile. @@ -1954,10 +1971,8 @@ void PersonalDataManager::OnAutofillProfileChanged( const AutofillProfileDeepChange& change) { const auto& guid = change.key(); const auto& change_type = change.type(); - const auto& profile = change.profile(); - + const auto& profile = *(change.profile()); DCHECK(guid == profile.guid()); - // Happens only in tests. if (!ProfileChangesAreOnGoing(guid)) { DVLOG(1) << "Received an unexpected response from database."; @@ -1976,7 +1991,8 @@ void PersonalDataManager::OnAutofillProfileChanged( case AutofillProfileChange::UPDATE: profiles_server_validities_need_update_ = true; if (profile_exists && - !existing_profile->EqualsForUpdatePurposes(profile)) { + (change.enforce_update() || + !existing_profile->EqualsForUpdatePurposes(profile))) { web_profiles_.erase( FindElementByGUID<AutofillProfile>(web_profiles_, guid)); web_profiles_.push_back(std::make_unique<AutofillProfile>(profile)); @@ -2034,7 +2050,7 @@ std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards( Suggestion* suggestion = &suggestions.back(); suggestion->value = credit_card->GetInfo(type, app_locale_); - suggestion->icon = base::UTF8ToUTF16(credit_card->network()); + suggestion->icon = credit_card->network(); suggestion->backend_id = credit_card->guid(); suggestion->match = prefix_matched_suggestion ? Suggestion::PREFIX_MATCH @@ -2063,7 +2079,7 @@ std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards( suggestion->label = credit_card->NetworkOrBankNameAndLastFourDigits(); #else suggestion->label = credit_card->ObfuscatedLastFourDigits(); - // Ad the card number with expiry information in the additional + // Add the card number with expiry information in the additional // label portion so that we an show it when two-line display is // enabled. suggestion->additional_label = @@ -2177,7 +2193,7 @@ void PersonalDataManager::DedupeProfiles( const std::unique_ptr<AutofillProfile>& b) { if (a->IsVerified() != b->IsVerified()) return !a->IsVerified(); - return a->CompareFrecency(b.get(), comparison_time); + return a->HasGreaterFrecencyThan(b.get(), comparison_time); }); AutofillProfileComparator comparator(app_locale_); @@ -2321,9 +2337,6 @@ void PersonalDataManager::ConvertWalletAddressesAndUpdateWalletCards() { UpdateCardsBillingAddressReference(guids_merge_map); // Force a reload of the profiles and cards. - // TODO(crbug.com/915229): Remove once the investigation is over. - if (has_converted_addresses) - DLOG(WARNING) << this << " conversion of addresses done"; } } @@ -2334,11 +2347,6 @@ bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles( // If the full Sync feature isn't enabled, then do NOT convert any Wallet // addresses to local ones. if (!IsSyncFeatureEnabled()) { - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this - << " not converting as sync feature is not enabled, probably " - "due to sync_service_ being " - << sync_service_; return false; } @@ -2352,12 +2360,9 @@ bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles( if (!wallet_address->has_converted()) { // Try to merge the server address into a similar local profile, or create // a new local profile if no similar profile is found. - // TODO(crbug.com/864519): Use GetAccountInfoForPaymentsServer instead of - // going to IdentityManager directly. This will be necessary to properly - // support Wallet addresses with Butter. std::string address_guid = MergeServerAddressesIntoProfiles( *wallet_address, local_profiles, app_locale_, - identity_manager_->GetPrimaryAccountInfo().email); + GetAccountInfoForPaymentsServer().email); // Update the map to transfer the billing address relationship from the // server address to the converted/merged local profile. @@ -2365,8 +2370,6 @@ bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles( // Update the wallet addresses metadata to record the conversion. wallet_address->set_has_converted(true); - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " converting address " << *wallet_address; database_helper_->GetServerDatabase()->UpdateServerAddressMetadata( *wallet_address); @@ -2541,6 +2544,9 @@ bool PersonalDataManager::DeleteDisusedAddresses() { } void PersonalDataManager::ApplyAddressFixesAndCleanups() { + // Validate profiles once per major. + UpdateClientValidityStates(GetProfiles()); + // One-time fix, otherwise NOP. RemoveOrphanAutofillTableRows(); @@ -2579,7 +2585,6 @@ void PersonalDataManager::ResetProfileValidity() { } void PersonalDataManager::AddProfileToDB(const AutofillProfile& profile) { - // Add the new profile to the web database. if (profile.IsEmpty(app_locale_)) { NotifyPersonalDataChanged(); return; @@ -2591,26 +2596,30 @@ void PersonalDataManager::AddProfileToDB(const AutofillProfile& profile) { NotifyPersonalDataChanged(); return; } - database_helper_->GetLocalDatabase()->AddAutofillProfile(profile); } - ongoing_profile_changes_[profile.guid()].push( + ongoing_profile_changes_[profile.guid()].push_back( AutofillProfileDeepChange(AutofillProfileChange::ADD, profile)); + UpdateClientValidityStates(profile); } -void PersonalDataManager::UpdateProfileInDB(const AutofillProfile& profile) { - if (!ProfileChangesAreOnGoing(profile.guid())) { +void PersonalDataManager::UpdateProfileInDB(const AutofillProfile& profile, + bool enforced) { + // if the update is enforced, don't check if a similar profile already exists + // or not. Otherwise, check if updating the profile makes sense. + if (!enforced && !ProfileChangesAreOnGoing(profile.guid())) { const auto* existing_profile = GetProfileByGUID(profile.guid()); bool profile_exists = (existing_profile != nullptr); - if (profile_exists && !existing_profile->EqualsForUpdatePurposes(profile)) { - database_helper_->GetLocalDatabase()->UpdateAutofillProfile(profile); - } else { + if (!profile_exists || existing_profile->EqualsForUpdatePurposes(profile)) { NotifyPersonalDataChanged(); return; } } - ongoing_profile_changes_[profile.guid()].push( + ongoing_profile_changes_[profile.guid()].push_back( AutofillProfileDeepChange(AutofillProfileChange::UPDATE, profile)); + if (enforced) + ongoing_profile_changes_[profile.guid()].back().set_enforce_update(); + UpdateClientValidityStates(profile); } void PersonalDataManager::RemoveProfileFromDB(const std::string& guid) { @@ -2619,11 +2628,12 @@ void PersonalDataManager::RemoveProfileFromDB(const std::string& guid) { NotifyPersonalDataChanged(); return; } - - if (!ProfileChangesAreOnGoing(guid)) + AutofillProfileDeepChange change(AutofillProfileChange::REMOVE, guid); + if (!ProfileChangesAreOnGoing(guid)) { database_helper_->GetLocalDatabase()->RemoveAutofillProfile(guid); - ongoing_profile_changes_[guid].push( - AutofillProfileDeepChange(AutofillProfileChange::REMOVE, guid)); + change.set_is_ongoing_on_background(); + } + ongoing_profile_changes_[guid].push_back(std::move(change)); } void PersonalDataManager::HandleNextProfileChange(const std::string& guid) { @@ -2631,10 +2641,13 @@ void PersonalDataManager::HandleNextProfileChange(const std::string& guid) { return; const auto& change = ongoing_profile_changes_[guid].front(); + if (change.is_ongoing_on_background()) + return; + const auto& change_type = change.type(); const auto* existing_profile = GetProfileByGUID(guid); const bool profile_exists = (existing_profile != nullptr); - const auto& profile = ongoing_profile_changes_[guid].front().profile(); + const auto& profile = *(ongoing_profile_changes_[guid].front().profile()); DCHECK(guid == profile.guid()); @@ -2644,23 +2657,30 @@ void PersonalDataManager::HandleNextProfileChange(const std::string& guid) { return; } database_helper_->GetLocalDatabase()->RemoveAutofillProfile(guid); + change.set_is_ongoing_on_background(); return; } + if (!change.has_validation_effort_made()) + return; + if (change_type == AutofillProfileChange::ADD) { if (profile_exists || FindByContents(web_profiles_, profile)) { OnProfileChangeDone(guid); return; } database_helper_->GetLocalDatabase()->AddAutofillProfile(profile); + change.set_is_ongoing_on_background(); return; } - if (!profile_exists || existing_profile->EqualsForUpdatePurposes(profile)) { + if (profile_exists && (change.enforce_update() || + !existing_profile->EqualsForUpdatePurposes(profile))) { + database_helper_->GetLocalDatabase()->UpdateAutofillProfile(profile); + change.set_is_ongoing_on_background(); + } else { OnProfileChangeDone(guid); - return; } - database_helper_->GetLocalDatabase()->UpdateAutofillProfile(profile); } bool PersonalDataManager::ProfileChangesAreOnGoing(const std::string& guid) { @@ -2670,7 +2690,7 @@ bool PersonalDataManager::ProfileChangesAreOnGoing(const std::string& guid) { } bool PersonalDataManager::ProfileChangesAreOnGoing() { - for (auto task : ongoing_profile_changes_) { + for (const auto& task : ongoing_profile_changes_) { if (ProfileChangesAreOnGoing(task.first)) { return true; } @@ -2679,7 +2699,7 @@ bool PersonalDataManager::ProfileChangesAreOnGoing() { } void PersonalDataManager::OnProfileChangeDone(const std::string& guid) { - ongoing_profile_changes_[guid].pop(); + ongoing_profile_changes_[guid].pop_front(); if (!ProfileChangesAreOnGoing()) { Refresh(); diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h index 754305dd365..df97465f599 100644 --- a/chromium/components/autofill/core/browser/personal_data_manager.h +++ b/chromium/components/autofill/core/browser/personal_data_manager.h @@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PERSONAL_DATA_MANAGER_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_PERSONAL_DATA_MANAGER_H_ +#include <deque> #include <list> #include <memory> #include <set> @@ -36,9 +37,9 @@ #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_member.h" #include "components/signin/core/browser/account_info.h" -#include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/sync/driver/sync_service_observer.h" #include "components/webdata/common/web_data_service_consumer.h" +#include "services/identity/public/cpp/identity_manager.h" class Browser; class PrefService; @@ -56,10 +57,6 @@ void SetProfiles(int, std::vector<autofill::AutofillProfile>*); void SetCreditCards(int, std::vector<autofill::CreditCard>*); } // namespace autofill_helper -namespace identity { -class IdentityManager; -} - namespace syncer { class SyncService; } // namespace syncer @@ -74,7 +71,7 @@ class PersonalDataManager : public KeyedService, public AutofillWebDataServiceObserverOnUISequence, public history::HistoryServiceObserver, public syncer::SyncServiceObserver, - public GaiaCookieManagerService::Observer, + public identity::IdentityManager::Observer, public AccountInfoGetter { public: explicit PersonalDataManager(const std::string& app_locale); @@ -95,7 +92,6 @@ class PersonalDataManager : public KeyedService, identity::IdentityManager* identity_manager, AutofillProfileValidator* client_profile_validator, history::HistoryService* history_service, - GaiaCookieManagerService* cookie_manager_service, bool is_off_the_record); // KeyedService: @@ -123,14 +119,14 @@ class PersonalDataManager : public KeyedService, void OnSyncShutdown(syncer::SyncService* sync) override; // AccountInfoGetter: - AccountInfo GetAccountInfoForPaymentsServer() const override; + CoreAccountInfo GetAccountInfoForPaymentsServer() const override; bool IsSyncFeatureEnabled() const override; - // GaiaCookieManagerService::Observer: - void OnGaiaCookieDeletedByUserAction() override; + // identity::IdentityManager::Observer: + void OnAccountsCookieDeletedByUserAction() override; // Returns the current sync status. - AutofillSyncSigninState GetSyncSigninState() const; + virtual AutofillSyncSigninState GetSyncSigninState() const; // Adds a listener to be notified of PersonalDataManager events. virtual void AddObserver(PersonalDataManagerObserver* observer); @@ -167,8 +163,7 @@ class PersonalDataManager : public KeyedService, virtual void RemoveByGUID(const std::string& guid); // Returns the profile with the specified |guid|, or nullptr if there is no - // profile with the specified |guid|. Both web and auxiliary profiles may - // be returned. + // profile with the specified |guid|. virtual AutofillProfile* GetProfileByGUID(const std::string& guid); // Returns the profile with the specified |guid| from the given |profiles|, or @@ -255,11 +250,16 @@ class PersonalDataManager : public KeyedService, void UpdateProfilesServerValidityMapsIfNeeded( const std::vector<AutofillProfile*>& profiles); - // Updates the validity states of |profiles| according to client side - // validation API: |client_profile_validator_|. + // Requests an update for the validity states of the |profiles| according to + // client side validation API: |client_profile_validator_|. void UpdateClientValidityStates( const std::vector<AutofillProfile*>& profiles); + // Requests an update for the validity states of the |profile| according to + // the client side validation API: |client_profile_validator_|. Returns true + // if the validation was requested. + bool UpdateClientValidityStates(const AutofillProfile& profile); + // Returns the profiles to suggest to the user, ordered by frecency. std::vector<AutofillProfile*> GetProfilesToSuggest() const; @@ -269,15 +269,16 @@ class PersonalDataManager : public KeyedService, const AutofillType& type, std::vector<AutofillProfile*>* profiles); - // Loads profiles that can suggest data for |type|. |field_contents| is the - // part the user has already typed. |field_is_autofilled| is true if the field - // has already been autofilled. |other_field_types| represents the rest of - // form. + // Returns Suggestions corresponding to the focused field's |type| and + // |field_contents|, i.e. what the user has typed. |field_is_autofilled| is + // true if the field has already been autofilled, and |field_types| stores the + // types of all the form's input fields, including the field with which the + // user is interacting. std::vector<Suggestion> GetProfileSuggestions( const AutofillType& type, const base::string16& field_contents, bool field_is_autofilled, - const std::vector<ServerFieldType>& other_field_types); + const std::vector<ServerFieldType>& field_types); // Tries to delete disused addresses once per major version if the // feature is enabled. @@ -385,8 +386,10 @@ class PersonalDataManager : public KeyedService, // Records the sync transport consent if the user is in sync transport mode. virtual void OnUserAcceptedUpstreamOffer(); - // Triggered when a profile is added/updated/removed on db. - void OnAutofillProfileChanged(const AutofillProfileDeepChange& change); + void set_client_profile_validator_for_test( + AutofillProfileValidator* validator) { + client_profile_validator_ = validator; + } protected: // Only PersonalDataManagerFactory and certain tests can create instances of @@ -396,8 +399,6 @@ class PersonalDataManager : public KeyedService, FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, AddCreditCard_CrazyCharacters); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, AddCreditCard_Invalid); - FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, FirstMiddleLast); - FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, AutofillIsEnabledAtStartup); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, DedupeProfiles_ProfilesToDelete); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, @@ -442,8 +443,6 @@ class PersonalDataManager : public KeyedService, FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, DoNotConvertWalletAddressesInEphemeralStorage); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, - DeleteDisusedCreditCards_OncePerVersion); - FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, DeleteDisusedCreditCards_DoNothingWhenDisabled); FRIEND_TEST_ALL_PREFIXES( PersonalDataManagerTest, @@ -467,9 +466,10 @@ class PersonalDataManager : public KeyedService, ClearCreditCardNonSettingsOrigins); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, MoveJapanCityToStreetAddress); - FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, RequestProfileValidity); FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, - GetProfileSuggestions_InvalidDataBasedOnServer); + RequestProfileServerValidity); + FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest, + GetProfileSuggestions_Validity); friend class autofill::AutofillInteractiveTest; friend class autofill::PersonalDataManagerFactory; @@ -477,6 +477,8 @@ class PersonalDataManager : public KeyedService, friend class FormDataImporterTest; friend class PersonalDataManagerTest; friend class PersonalDataManagerTestBase; + friend class PersonalDataManagerHelper; + friend class PersonalDataManagerMockTest; friend class SaveImportedProfileTest; friend class ProfileSyncServiceAutofillTest; friend class ::RemoveAutofillTester; @@ -561,7 +563,8 @@ class PersonalDataManager : public KeyedService, // https://crbug.com/871301 void MoveJapanCityToStreetAddress(); - // Called when the |profile| is validated by the AutofillProfileValidator. + // Called when the |profile| is validated by the AutofillProfileValidator, + // updates the profiles on the |ongoing_profile_changes_| and the DB. virtual void OnValidated(const AutofillProfile* profile); // Get the profiles fields validity map by |guid|. @@ -578,15 +581,11 @@ class PersonalDataManager : public KeyedService, std::vector<std::unique_ptr<AutofillProfile>> web_profiles_; // Profiles read from the user's account stored on the server. - mutable std::vector<std::unique_ptr<AutofillProfile>> server_profiles_; + 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_; - // Cached versions of the local and server credit cards. std::vector<std::unique_ptr<CreditCard>> local_credit_cards_; std::vector<std::unique_ptr<CreditCard>> server_credit_cards_; @@ -722,11 +721,16 @@ class PersonalDataManager : public KeyedService, // Resets |synced_profile_validity_|. void ResetProfileValidity(); - // Add/Update/Remove profiles on DB. + // Add/Update/Remove |profile| on DB. void AddProfileToDB(const AutofillProfile& profile); - void UpdateProfileInDB(const AutofillProfile& profile); + // |enforced| is true when the update should happen regardless of an equal + // profile. (equal in the sense of AutofillProfile::EqualForUpdate) + void UpdateProfileInDB(const AutofillProfile& profile, bool enforced = false); void RemoveProfileFromDB(const std::string& guid); + // Triggered when a profile is added/updated/removed on db. + void OnAutofillProfileChanged(const AutofillProfileDeepChange& change); + // Look at the next profile change for profile with guid = |guid|, and handle // it. void HandleNextProfileChange(const std::string& guid); @@ -754,21 +758,16 @@ class PersonalDataManager : public KeyedService, // remove itself from the history service's observer list on shutdown. history::HistoryService* history_service_ = nullptr; - // The GaiaCookieManagerService to be observed by the personal data manager. - // Must outlive this instance. This unowned pointer is retained so the PDM can - // remove itself from the cookie manager service's observer list on shutdown. - GaiaCookieManagerService* cookie_manager_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. We need to set the - // |profile_validities_need_update| whenever this is changed. + // |profile_validities_need_update_| whenever this is changed. std::unique_ptr<UserProfileValidityMap> synced_profile_validity_; // A timely ordered list of on going changes for each profile. - std::unordered_map<std::string, std::queue<AutofillProfileDeepChange>> + std::unordered_map<std::string, std::deque<AutofillProfileDeepChange>> ongoing_profile_changes_; // The client side profile validator. 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 f06c16f345b..20fb473789c 100644 --- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc @@ -60,12 +60,16 @@ #include "components/webdata/common/web_database_service.h" #include "google_apis/gaia/google_service_auth_error.h" #include "services/identity/public/cpp/identity_test_environment.h" +#include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace autofill { namespace { +const char kPrimaryAccountEmail[] = "syncuser@example.com"; +const char kSyncTransportAccountEmail[] = "transport@example.com"; + enum UserMode { USER_MODE_NORMAL, USER_MODE_INCOGNITO }; const base::Time kArbitraryTime = base::Time::FromDoubleT(25); @@ -132,7 +136,8 @@ void ExpectSameElements(const std::vector<T*>& expectations, class PersonalDataManagerTestBase { protected: - PersonalDataManagerTestBase() { + PersonalDataManagerTestBase() + : identity_test_env_(&test_url_loader_factory_) { // Enable account storage by default, some tests will override this to be // false. scoped_features_.InitWithFeatures( @@ -176,13 +181,6 @@ class PersonalDataManagerTestBase { account_database_service_->Init(); test::DisableSystemServices(prefs_.get()); - ResetPersonalDataManager(USER_MODE_NORMAL); - - // Reset the deduping and profile validation prefs to their default value. - personal_data_->pref_service_->SetInteger( - prefs::kAutofillLastVersionDeduped, 0); - personal_data_->pref_service_->SetInteger( - prefs::kAutofillLastVersionValidated, CHROME_VERSION_MAJOR); } void TearDownTest() { @@ -193,11 +191,11 @@ class PersonalDataManagerTestBase { } void ResetPersonalDataManager(UserMode user_mode, - bool use_sync_transport_mode) { + bool use_sync_transport_mode, + PersonalDataManager* personal_data) { bool is_incognito = (user_mode == USER_MODE_INCOGNITO); - personal_data_.reset(new PersonalDataManagerMock("en")); - personal_data_->Init( + personal_data->Init( scoped_refptr<AutofillWebDataService>(profile_database_service_), base::FeatureList::IsEnabled( features::kAutofillEnableAccountWalletStorage) @@ -205,44 +203,147 @@ class PersonalDataManagerTestBase { : nullptr, prefs_.get(), identity_test_env_.identity_manager(), TestAutofillProfileValidator::GetInstance(), - /*history_service=*/nullptr, /*cookie_manager_sevice=*/nullptr, - is_incognito); + /*history_service=*/nullptr, is_incognito); - personal_data_->AddObserver(&personal_data_observer_); + personal_data->AddObserver(&personal_data_observer_); AccountInfo account_info; - account_info.email = "sync@account"; + account_info.email = use_sync_transport_mode ? kSyncTransportAccountEmail + : kPrimaryAccountEmail; sync_service_.SetAuthenticatedAccountInfo(account_info); sync_service_.SetIsAuthenticatedAccountPrimary(!use_sync_transport_mode); - personal_data_->OnSyncServiceInitialized(&sync_service_); - personal_data_->OnStateChanged(&sync_service_); + personal_data->OnSyncServiceInitialized(&sync_service_); + personal_data->OnStateChanged(&sync_service_); WaitForOnPersonalDataChangedRepeatedly(); } - void ResetPersonalDataManager(UserMode user_mode) { - ResetPersonalDataManager(user_mode, /*use_sync_transport_mode=*/false); - } - - void ResetProfiles() { - std::vector<AutofillProfile> empty_profiles; - personal_data_->SetProfiles(&empty_profiles); - WaitForOnPersonalDataChanged(); - } - - bool TurnOnSyncFeature() WARN_UNUSED_RESULT { + bool TurnOnSyncFeature(PersonalDataManager* personal_data) + WARN_UNUSED_RESULT { sync_service_.SetIsAuthenticatedAccountPrimary(true); if (!sync_service_.IsSyncFeatureEnabled()) return false; - personal_data_->OnStateChanged(&sync_service_); - return personal_data_->IsSyncFeatureEnabled(); + personal_data->OnStateChanged(&sync_service_); + + return personal_data->IsSyncFeatureEnabled(); } void EnableWalletCardImport() { - identity_test_env_.MakePrimaryAccountAvailable("syncuser@example.com"); + identity_test_env_.MakePrimaryAccountAvailable(kPrimaryAccountEmail); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableOfferStoreUnmaskedWalletCards); } + void RemoveByGUIDFromPersonalDataManager(const std::string& guid, + PersonalDataManager* personal_data) { + base::RunLoop run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillOnce(QuitMessageLoop(&run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(testing::AnyNumber()); + + personal_data->RemoveByGUID(guid); + run_loop.Run(); + } + + void SetServerCards(std::vector<CreditCard> server_cards) { + test::SetServerCreditCards(account_autofill_table_, server_cards); + } + + // Verify that the web database has been updated and the notification sent. + void WaitOnceForOnPersonalDataChanged() { + base::RunLoop run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillOnce(QuitMessageLoop(&run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); + run_loop.Run(); + } + + // Verifies that the web database has been updated and the notification sent. + void WaitForOnPersonalDataChanged() { + base::RunLoop run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillOnce(QuitMessageLoop(&run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(testing::AnyNumber()); + run_loop.Run(); + } + + // Verifies that the web database has been updated and the notification sent. + void WaitForOnPersonalDataChangedRepeatedly() { + base::RunLoop run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillRepeatedly(QuitMessageLoop(&run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(testing::AnyNumber()); + run_loop.Run(); + } + + AccountInfo SetActiveSecondaryAccount() { + AccountInfo account_info; + account_info.email = kSyncTransportAccountEmail; + account_info.account_id = "account_id"; + sync_service_.SetAuthenticatedAccountInfo(account_info); + sync_service_.SetIsAuthenticatedAccountPrimary(false); + return account_info; + } + + void MoveJapanCityToStreetAddress(PersonalDataManager* personal_data, + int move_times) { + base::RunLoop run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillRepeatedly(QuitMessageLoop(&run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(move_times); + personal_data->MoveJapanCityToStreetAddress(); + run_loop.Run(); + } + + // The temporary directory should be deleted at the end to ensure that + // files are not used anymore and deletion succeeds. + base::ScopedTempDir temp_dir_; + base::test::ScopedTaskEnvironment task_environment_{ + base::test::ScopedTaskEnvironment::MainThreadType::UI}; + std::unique_ptr<PrefService> prefs_; + network::TestURLLoaderFactory test_url_loader_factory_; + identity::IdentityTestEnvironment identity_test_env_; + syncer::TestSyncService sync_service_; + scoped_refptr<AutofillWebDataService> profile_database_service_; + scoped_refptr<AutofillWebDataService> account_database_service_; + scoped_refptr<WebDatabaseService> profile_web_database_; + scoped_refptr<WebDatabaseService> account_web_database_; + AutofillTable* profile_autofill_table_; // weak ref + AutofillTable* account_autofill_table_; // weak ref + PersonalDataLoadedObserverMock personal_data_observer_; + base::test::ScopedFeatureList scoped_features_; +}; + +class PersonalDataManagerHelper : public PersonalDataManagerTestBase { + protected: + virtual ~PersonalDataManagerHelper() { + if (personal_data_) + personal_data_->Shutdown(); + personal_data_.reset(); + } + + void ResetPersonalDataManager(UserMode user_mode, + bool use_account_server_storage = false) { + if (personal_data_) + personal_data_->Shutdown(); + personal_data_.reset(new PersonalDataManager("en")); + PersonalDataManagerTestBase::ResetPersonalDataManager( + user_mode, use_account_server_storage, personal_data_.get()); + } + + void ResetProfiles() { + std::vector<AutofillProfile> empty_profiles; + personal_data_->SetProfiles(&empty_profiles); + WaitForOnPersonalDataChanged(); + } + + bool TurnOnSyncFeature() { + return PersonalDataManagerTestBase::TurnOnSyncFeature(personal_data_.get()); + } + void EnableAutofillProfileCleanup() { personal_data_->is_autofill_profile_cleanup_pending_ = true; } @@ -400,14 +501,8 @@ class PersonalDataManagerTestBase { } void RemoveByGUIDFromPersonalDataManager(const std::string& guid) { - base::RunLoop run_loop; - EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) - .WillOnce(QuitMessageLoop(&run_loop)); - EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) - .Times(testing::AnyNumber()); - - personal_data_->RemoveByGUID(guid); - run_loop.Run(); + PersonalDataManagerTestBase::RemoveByGUIDFromPersonalDataManager( + guid, personal_data_.get()); } void SetServerCards(const std::vector<CreditCard>& server_cards) { @@ -423,7 +518,8 @@ class PersonalDataManagerTestBase { base::RunLoop run_loop; EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) .WillOnce(QuitMessageLoop(&run_loop)); - EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(testing::AnyNumber()); personal_data_->SaveImportedProfile(profile); run_loop.Run(); @@ -433,91 +529,147 @@ class PersonalDataManagerTestBase { base::RunLoop run_loop; EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) .WillOnce(QuitMessageLoop(&run_loop)); - EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(testing::AnyNumber()); personal_data_->ConvertWalletAddressesAndUpdateWalletCards(); run_loop.Run(); } - // Verifies that the web database has been updated and the notification sent. - void WaitForOnPersonalDataChanged() { + std::unique_ptr<PersonalDataManager> personal_data_; +}; + +class PersonalDataManagerTest : public PersonalDataManagerHelper, + public testing::Test { + protected: + void SetUp() override { + SetUpTest(); + ResetPersonalDataManager(USER_MODE_NORMAL); + } + void TearDown() override { TearDownTest(); } +}; + +class PersonalDataManagerMockTest : public PersonalDataManagerTestBase, + public testing::Test { + protected: + void SetUp() override { + SetUpTest(); + ResetPersonalDataManager(USER_MODE_NORMAL); + // Reset the deduping and profile validation prefs to their default value. + personal_data_->pref_service_->SetInteger( + prefs::kAutofillLastVersionDeduped, 0); + personal_data_->pref_service_->SetInteger( + prefs::kAutofillLastVersionValidated, + atoi(version_info::GetVersionNumber().c_str())); + personal_data_->is_autofill_profile_cleanup_pending_ = true; + } + + void TearDown() override { + if (personal_data_) + personal_data_->Shutdown(); + personal_data_.reset(); + TearDownTest(); + } + + void ResetPersonalDataManager(UserMode user_mode) { + if (personal_data_) + personal_data_->Shutdown(); + personal_data_.reset(new PersonalDataManagerMock("en")); + PersonalDataManagerTestBase::ResetPersonalDataManager( + user_mode, /*use_account_server_storage=*/true, personal_data_.get()); + } + + bool TurnOnSyncFeature() { + return PersonalDataManagerTestBase::TurnOnSyncFeature(personal_data_.get()); + } + + void StopTheDedupeProcess() { + personal_data_->pref_service_->SetInteger( + prefs::kAutofillLastVersionDeduped, + atoi(version_info::GetVersionNumber().c_str())); + } + + void ResetAutofillLastVersionValidated() { + ASSERT_TRUE(personal_data_); + personal_data_->pref_service_->SetInteger( + prefs::kAutofillLastVersionValidated, 0); + } + + void AddProfileToPersonalDataManager(const AutofillProfile& profile) { base::RunLoop run_loop; + + EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(1); + ON_CALL(*personal_data_, OnValidated(testing::_)) + .WillByDefault(testing::Invoke( + personal_data_.get(), &PersonalDataManagerMock::OnValidatedPDM)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) .WillOnce(QuitMessageLoop(&run_loop)); EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) .Times(testing::AnyNumber()); + + personal_data_->AddProfile(profile); + run_loop.Run(); } - void WaitOnceForOnPersonalDataChanged() { + void UpdateProfileOnPersonalDataManager(const AutofillProfile& profile) { base::RunLoop run_loop; + + EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(1); + ON_CALL(*personal_data_, OnValidated(testing::_)) + .WillByDefault(testing::Invoke( + personal_data_.get(), &PersonalDataManagerMock::OnValidatedPDM)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) .WillOnce(QuitMessageLoop(&run_loop)); - EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) + .Times(testing::AnyNumber()); + + personal_data_->UpdateProfile(profile); + run_loop.Run(); } - // Verifies that the web database has been updated and the notification sent. - void WaitForOnPersonalDataChangedRepeatedly() { + void RemoveByGUIDFromPersonalDataManager(const std::string& guid) { + PersonalDataManagerTestBase::RemoveByGUIDFromPersonalDataManager( + guid, personal_data_.get()); + } + + void UpdateClientValidityStatesOnPersonalDataManager( + const std::vector<AutofillProfile*>& profiles) { + int num_updates = 0; + if (GetLastVersionValidatedUpdate() < CHROME_VERSION_MAJOR) { + num_updates = profiles.size(); + } else { + for (auto* profile : profiles) { + if (!profile->is_client_validity_states_updated()) + num_updates++; + } + } + base::RunLoop run_loop; + + EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(num_updates); + ON_CALL(*personal_data_, OnValidated(testing::_)) + .WillByDefault(testing::Invoke( + personal_data_.get(), &PersonalDataManagerMock::OnValidatedPDM)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) .WillRepeatedly(QuitMessageLoop(&run_loop)); EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) .Times(testing::AnyNumber()); + // Validate the profiles through the client validation API. + personal_data_->UpdateClientValidityStates(profiles); run_loop.Run(); } - void ExpectOnValidated(AutofillProfile* profile) { - EXPECT_CALL(*personal_data_, OnValidated(profile)).Times(1); - ON_CALL(*personal_data_, OnValidated(profile)) - .WillByDefault(testing::Invoke( - personal_data_.get(), &PersonalDataManagerMock::OnValidatedPDM)); - } - - void ResetAutofillLastVersionValidated() { - ASSERT_TRUE(personal_data_); - personal_data_->pref_service_->SetInteger( - prefs::kAutofillLastVersionValidated, 0); - } - int GetLastVersionValidatedUpdate() { return personal_data_->pref_service_->GetInteger( prefs::kAutofillLastVersionValidated); } - AccountInfo SetActiveSecondaryAccount() { - AccountInfo account_info; - account_info.email = "signed_in_account@email.com"; - account_info.account_id = "account_id"; - sync_service_.SetAuthenticatedAccountInfo(account_info); - sync_service_.SetIsAuthenticatedAccountPrimary(false); - return account_info; - } - - // The temporary directory should be deleted at the end to ensure that - // files are not used anymore and deletion succeeds. - base::ScopedTempDir temp_dir_; - base::test::ScopedTaskEnvironment task_environment_{ - base::test::ScopedTaskEnvironment::MainThreadType::UI}; - std::unique_ptr<PrefService> prefs_; - identity::IdentityTestEnvironment identity_test_env_; - syncer::TestSyncService sync_service_; - scoped_refptr<AutofillWebDataService> profile_database_service_; - scoped_refptr<AutofillWebDataService> account_database_service_; - scoped_refptr<WebDatabaseService> profile_web_database_; - scoped_refptr<WebDatabaseService> account_web_database_; - AutofillTable* profile_autofill_table_ = nullptr; // weak ref - AutofillTable* account_autofill_table_ = nullptr; // weak ref - PersonalDataLoadedObserverMock personal_data_observer_; std::unique_ptr<PersonalDataManagerMock> personal_data_; - base::test::ScopedFeatureList scoped_features_; -}; - -class PersonalDataManagerTest : public PersonalDataManagerTestBase, - public testing::Test { - void SetUp() override { SetUpTest(); } - - void TearDown() override { TearDownTest(); } }; TEST_F(PersonalDataManagerTest, AddProfile) { @@ -572,6 +724,7 @@ TEST_F(PersonalDataManagerTest, AddRemoveUpdateProfileSequence) { personal_data_->AddProfile(profile); personal_data_->RemoveByGUID(profile.guid()); + personal_data_->UpdateProfile(profile); WaitForOnPersonalDataChanged(); auto profiles = personal_data_->GetProfiles(); @@ -581,20 +734,54 @@ TEST_F(PersonalDataManagerTest, AddRemoveUpdateProfileSequence) { personal_data_->RemoveByGUID(profile.guid()); personal_data_->RemoveByGUID(profile.guid()); WaitForOnPersonalDataChanged(); + profiles = personal_data_->GetProfiles(); ASSERT_EQ(0U, profiles.size()); personal_data_->AddProfile(profile); profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("new@email.com")); personal_data_->UpdateProfile(profile); + WaitForOnPersonalDataChanged(); + + profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + EXPECT_EQ(profiles[0]->GetRawInfo(EMAIL_ADDRESS), + base::ASCIIToUTF16("new@email.com")); + profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("newer@email.com")); personal_data_->UpdateProfile(profile); + profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("newest@email.com")); + personal_data_->UpdateProfile(profile); WaitForOnPersonalDataChanged(); profiles = personal_data_->GetProfiles(); ASSERT_EQ(1U, profiles.size()); EXPECT_EQ(profiles[0]->GetRawInfo(EMAIL_ADDRESS), - base::ASCIIToUTF16("newer@email.com")); + base::ASCIIToUTF16("newest@email.com")); +} + +// The changes should happen in the same order as requested. If the later change +// is validated before an earlier one, still we should process the earlier one +// first. +TEST_F(PersonalDataManagerTest, InconsistentValidationSequence) { + auto profile = test::GetFullProfile(); + // Slow validation. + personal_data_->set_client_profile_validator_for_test( + TestAutofillProfileValidator::GetDelayedInstance()); + personal_data_->AddProfile(profile); + + // No validator, zero delay for validation. + personal_data_->set_client_profile_validator_for_test(nullptr); + profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("new@email.com")); + personal_data_->UpdateProfile(profile); + + WaitForOnPersonalDataChanged(); + + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + EXPECT_EQ(profiles[0]->GetRawInfo(EMAIL_ADDRESS), + base::ASCIIToUTF16("new@email.com")); + EXPECT_FALSE(profiles[0]->is_client_validity_states_updated()); } // Test that a new profile has its basic information set. @@ -1453,7 +1640,6 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileWithVerifiedData) { "Hollywood", "CA", "91601", "US", "12345678910"); EXPECT_FALSE(profile.IsVerified()); - // Add the profile to the database. AddProfileToPersonalDataManager(profile); // Make sure everything is set up correctly. @@ -2104,66 +2290,57 @@ TEST_F(PersonalDataManagerTest, } // Tests that suggestions based on invalid data are handled correctly. -TEST_F(PersonalDataManagerTest, - GetProfileSuggestions_InvalidDataBasedOnClient) { - // Set up 2 different profiles. - AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin); - test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison", - "johnwayne@me.xyz", "Fox", - "123 Zoo St.\nSecond Line\nThird line", "unit 5", - "Hollywood", "CA", "91601", "US", "9876543210"); - profile1.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID, - AutofillProfile::CLIENT); - profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(20)); - AddProfileToPersonalDataManager(profile1); +TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Validity) { + // Set up 2 different profiles: one valid and one invalid. + AutofillProfile valid_profile(test::GetFullValidProfileForCanada()); + valid_profile.set_use_date(AutofillClock::Now() - + base::TimeDelta::FromDays(200)); + valid_profile.set_use_count(1); + AddProfileToPersonalDataManager(valid_profile); - AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin); - test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison", - "johnwayne@me.xyz", "Fox", - "456 Zoo St.\nSecond Line\nThird line", "unit 5", - "Hollywood", "CA", "91601", "US", "1234567890"); - AddProfileToPersonalDataManager(profile2); + AutofillProfile invalid_profile(base::GenerateGUID(), test::kEmptyOrigin); + test::SetProfileInfo(&invalid_profile, "Marion1", "Mitchell", "Morrison", + "invalid email", "Fox", + "123 Zoo St.\nSecond Line\nThird line", "unit 5", + "Hollywood", "CA", "91601", "US", "Invalid Phone"); + invalid_profile.set_use_date(AutofillClock::Now()); + invalid_profile.set_use_count(1000); + AddProfileToPersonalDataManager(invalid_profile); - ResetPersonalDataManager(USER_MODE_NORMAL); - { - base::HistogramTester histogram_tester; - base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndDisableFeature( - features::kAutofillSuggestInvalidProfileData); - std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions( - AutofillType(PHONE_HOME_WHOLE_NUMBER), base::string16(), false, - std::vector<ServerFieldType>()); - ASSERT_EQ(1U, suggestions.size()); - EXPECT_EQ(base::ASCIIToUTF16("1234567890"), suggestions[0].value); - histogram_tester.ExpectUniqueSample( - "Autofill.InvalidProfileData.UsedForSuggestion", false, 1); - } + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(2U, profiles.size()); + // Invalid based on client, and not invalid by server. Relying on both + // validity sources. { - base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillSuggestInvalidProfileData); - std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions( - AutofillType(PHONE_HOME_WHOLE_NUMBER), base::string16(), false, - std::vector<ServerFieldType>()); - ASSERT_EQ(2U, suggestions.size()); - EXPECT_EQ(base::ASCIIToUTF16("1234567890"), suggestions[0].value); - EXPECT_EQ(base::ASCIIToUTF16("9876543210"), suggestions[1].value); - histogram_tester.ExpectUniqueSample( - "Autofill.InvalidProfileData.UsedForSuggestion", true, 1); + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileServerValidation, + features::kAutofillProfileClientValidation}, + /*disabled_features=*/{features::kAutofillSuppressDisusedAddresses}); + std::vector<Suggestion> email_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS), + base::string16(), false, + std::vector<ServerFieldType>()); + + for (auto* profile : profiles) { + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByClient()); + ASSERT_TRUE(profile->IsValidByServer()); + } + ASSERT_EQ(1U, email_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), + email_suggestions[0].value); + + std::vector<Suggestion> name_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST), + base::string16(), false, + std::vector<ServerFieldType>()); + ASSERT_EQ(2U, name_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value); + EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value); } -} -// Tests that suggestions based on invalid data are handled correctly. -TEST_F(PersonalDataManagerTest, - GetProfileSuggestions_InvalidDataBasedOnServer) { - // Set up 2 different profiles. - AutofillProfile profile1(base::GenerateGUID(), test::kEmptyOrigin); - test::SetProfileInfo(&profile1, "Marion1", "Mitchell", "Morrison", - "johnwayne@me.xyz", "Fox", - "123 Zoo St.\nSecond Line\nThird line", "unit 5", - "Hollywood", "CA", "91601", "US", "9876543210"); // Set the validity state of ADDRESS_HOME_STATE to INVALID on the prefs. { ProfileValidityMap profile_validity_map; @@ -2171,9 +2348,11 @@ TEST_F(PersonalDataManagerTest, std::string autofill_profile_validity; personal_data_->pref_service_->SetString(prefs::kAutofillProfileValidity, autofill_profile_validity); - (*profile_validity_map.mutable_field_validity_states())[static_cast<int>( - ADDRESS_HOME_STATE)] = static_cast<int>(AutofillProfile::INVALID); - (*user_profile_validity_map.mutable_profile_validity())[profile1.guid()] = + (*profile_validity_map + .mutable_field_validity_states())[static_cast<int>(EMAIL_ADDRESS)] = + static_cast<int>(AutofillProfile::INVALID); + (*user_profile_validity_map + .mutable_profile_validity())[invalid_profile.guid()] = profile_validity_map; ASSERT_TRUE(user_profile_validity_map.SerializeToString( &autofill_profile_validity)); @@ -2181,44 +2360,98 @@ TEST_F(PersonalDataManagerTest, personal_data_->pref_service_->SetString(prefs::kAutofillProfileValidity, autofill_profile_validity); } - profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(20)); - AddProfileToPersonalDataManager(profile1); - - AutofillProfile profile2(base::GenerateGUID(), test::kEmptyOrigin); - test::SetProfileInfo(&profile2, "Marion2", "Mitchell", "Morrison", - "johnwayne@me.xyz", "Fox", - "456 Zoo St.\nSecond Line\nThird line", "unit 5", - "Hollywood", "NY", "91601", "US", "1234567890"); - AddProfileToPersonalDataManager(profile2); - - ResetPersonalDataManager(USER_MODE_NORMAL); + // Invalid based on client, and server. Relying on both validity sources. { - base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndDisableFeature( - features::kAutofillSuggestInvalidProfileData); - std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions( - AutofillType(ADDRESS_HOME_STATE), base::string16(), false, - std::vector<ServerFieldType>()); - ASSERT_EQ(1U, suggestions.size()); - EXPECT_EQ(base::ASCIIToUTF16("NY"), suggestions[0].value); - histogram_tester.ExpectUniqueSample( - "Autofill.InvalidProfileData.UsedForSuggestion", false, 1); + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileClientValidation, + features::kAutofillProfileServerValidation}, + /*disabled_features=*/{features::kAutofillSuppressDisusedAddresses}); + + std::vector<Suggestion> email_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS), + base::string16(), false, + std::vector<ServerFieldType>()); + + for (auto* profile : profiles) { + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByClient()); + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByServer()); + } + ASSERT_EQ(1U, email_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), + email_suggestions[0].value); + + std::vector<Suggestion> name_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST), + base::string16(), false, + std::vector<ServerFieldType>()); + ASSERT_EQ(2U, name_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value); + EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value); } - + // Invalid based on client, and server. Relying only on the client source. { - base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_features; - scoped_features.InitAndEnableFeature( - features::kAutofillSuggestInvalidProfileData); - std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions( - AutofillType(ADDRESS_HOME_STATE), base::string16(), false, - std::vector<ServerFieldType>()); - ASSERT_EQ(2U, suggestions.size()); - EXPECT_EQ(base::ASCIIToUTF16("CA"), suggestions[1].value); - EXPECT_EQ(base::ASCIIToUTF16("NY"), suggestions[0].value); - histogram_tester.ExpectUniqueSample( - "Autofill.InvalidProfileData.UsedForSuggestion", true, 1); + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileClientValidation}, + /*disabled_features=*/{features::kAutofillSuppressDisusedAddresses, + features::kAutofillProfileServerValidation}); + std::vector<Suggestion> email_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS), + base::string16(), false, + std::vector<ServerFieldType>()); + + for (auto* profile : profiles) { + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByClient()); + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByServer()); + } + ASSERT_EQ(1U, email_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), + email_suggestions[0].value); + + std::vector<Suggestion> name_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST), + base::string16(), false, + std::vector<ServerFieldType>()); + ASSERT_EQ(2U, name_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value); + EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value); + } + // Invalid based on client, and server. Relying on server as a validity + // source. + { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileServerValidation}, + /*disabled_features=*/{features::kAutofillProfileClientValidation, + features::kAutofillSuppressDisusedAddresses}); + LOG(ERROR) << __FUNCTION__; + std::vector<Suggestion> email_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS), + base::string16(), false, + std::vector<ServerFieldType>()); + + for (auto* profile : profiles) { + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByClient()); + ASSERT_EQ(profile->guid() == valid_profile.guid(), + profile->IsValidByServer()); + } + ASSERT_EQ(1U, email_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), + email_suggestions[0].value); + + std::vector<Suggestion> name_suggestions = + personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST), + base::string16(), false, + std::vector<ServerFieldType>()); + ASSERT_EQ(2U, name_suggestions.size()); + EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value); + EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value); } } @@ -2995,16 +3228,6 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) { base::TimeDelta::FromDays(15)); server_cards.back().SetNetworkForMaskedCard(kVisaCard); - // This server card is identical to a local card, but has a different - // card type. Not a dupe and therefore both should appear in the suggestions. - server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456")); - test::SetCreditCardInfo(&server_cards.back(), "Bonnie Parker", "5100", "12", - "2999", "1"); - server_cards.back().set_use_count(3); - server_cards.back().set_use_date(AutofillClock::Now() - - base::TimeDelta::FromDays(15)); - server_cards.back().SetNetworkForMaskedCard(kVisaCard); - // This unmasked server card is an exact dupe of a local card. Therefore only // this card should appear in the suggestions as full server cards have // precedence over local cards. @@ -3021,23 +3244,22 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) { // Make sure everything is set up correctly. personal_data_->Refresh(); WaitForOnPersonalDataChanged(); - EXPECT_EQ(6U, personal_data_->GetCreditCards().size()); + EXPECT_EQ(5U, personal_data_->GetCreditCards().size()); std::vector<Suggestion> suggestions = personal_data_->GetCreditCardSuggestions( AutofillType(CREDIT_CARD_NAME_FULL), /* field_contents= */ base::string16(), /*include_server_cards=*/true); - ASSERT_EQ(4U, suggestions.size()); + ASSERT_EQ(3U, suggestions.size()); EXPECT_EQ(base::ASCIIToUTF16("John Dillinger"), suggestions[0].value); EXPECT_EQ(base::ASCIIToUTF16("Clyde Barrow"), suggestions[1].value); EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[2].value); - EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[3].value); suggestions = personal_data_->GetCreditCardSuggestions( AutofillType(CREDIT_CARD_NUMBER), /* field_contents= */ base::string16(), /*include_server_cards=*/true); - ASSERT_EQ(4U, suggestions.size()); + ASSERT_EQ(3U, suggestions.size()); EXPECT_EQ(base::UTF8ToUTF16(std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456")), suggestions[0].value); @@ -3047,9 +3269,6 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) { EXPECT_EQ(base::UTF8ToUTF16(std::string("Mastercard ") + test::ObfuscatedCardDigitsAsUTF8("5100")), suggestions[2].value); - EXPECT_EQ(base::UTF8ToUTF16(std::string("Visa ") + - test::ObfuscatedCardDigitsAsUTF8("5100")), - suggestions[3].value); } // Tests that a full server card can be a dupe of more than one local card. @@ -3249,40 +3468,39 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_FullServerAndMasked) { EXPECT_EQ(2U, credit_cards.size()); } -// Tests that slightly different local, full server, and masked credit cards are -// not deduped. +// Tests that different local, masked, and full server credit cards are not +// deduped. TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) { std::list<CreditCard*> credit_cards; - CreditCard credit_card2("002149C1-EE28-4213-A3B9-DA243FFF021B", - test::kEmptyOrigin); - credit_card2.set_use_count(1); - credit_card2.set_use_date(AutofillClock::Now() - - base::TimeDelta::FromDays(1)); - test::SetCreditCardInfo(&credit_card2, "Homer Simpson", + CreditCard local_card("002149C1-EE28-4213-A3B9-DA243FFF021B", + test::kEmptyOrigin); + local_card.set_use_count(1); + local_card.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1)); + test::SetCreditCardInfo(&local_card, "Homer Simpson", "5105105105105100" /* Mastercard */, "", "", ""); - credit_cards.push_back(&credit_card2); + credit_cards.push_back(&local_card); - // Create a masked server card that is slightly different of the local card. - CreditCard credit_card4(CreditCard::MASKED_SERVER_CARD, "b456"); - test::SetCreditCardInfo(&credit_card4, "Homer Simpson", "5100", "12", "2999", + // Create a masked server card that is different from the local card. + CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "b456"); + test::SetCreditCardInfo(&masked_card, "Homer Simpson", "0005", "12", "2999", "1"); - credit_card4.set_use_count(3); - credit_card4.set_use_date(AutofillClock::Now() - - base::TimeDelta::FromDays(15)); - credit_card4.SetNetworkForMaskedCard(kVisaCard); - credit_cards.push_back(&credit_card4); + masked_card.set_use_count(3); + masked_card.set_use_date(AutofillClock::Now() - + base::TimeDelta::FromDays(15)); + // credit_card4.SetNetworkForMaskedCard(kVisaCard); + credit_cards.push_back(&masked_card); // Create a full server card that is slightly different of the two other // cards. - CreditCard credit_card5(CreditCard::FULL_SERVER_CARD, "c789"); - test::SetCreditCardInfo(&credit_card5, "Homer Simpson", + CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789"); + test::SetCreditCardInfo(&full_server_card, "Homer Simpson", "378282246310005" /* American Express */, "04", "2999", "1"); - credit_card5.set_use_count(1); - credit_card5.set_use_date(AutofillClock::Now() - - base::TimeDelta::FromDays(15)); - credit_cards.push_back(&credit_card5); + full_server_card.set_use_count(1); + full_server_card.set_use_date(AutofillClock::Now() - + base::TimeDelta::FromDays(15)); + credit_cards.push_back(&full_server_card); PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards); EXPECT_EQ(3U, credit_cards.size()); @@ -3535,13 +3753,16 @@ typedef struct { } SaveImportedProfileTestCase; class SaveImportedProfileTest - : public PersonalDataManagerTestBase, + : public PersonalDataManagerHelper, public testing::TestWithParam<SaveImportedProfileTestCase> { public: SaveImportedProfileTest() {} ~SaveImportedProfileTest() override {} - void SetUp() override { SetUpTest(); } + void SetUp() override { + SetUpTest(); + ResetPersonalDataManager(USER_MODE_NORMAL); + } void TearDown() override { TearDownTest(); } }; @@ -3605,7 +3826,7 @@ TEST_P(SaveImportedProfileTest, SaveImportedProfile) { ResetProfiles(); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( PersonalDataManagerTest, SaveImportedProfileTest, testing::Values( @@ -5207,7 +5428,7 @@ TEST_F(PersonalDataManagerTest, // Make sure that the added address has the email address of the currently // signed-in user. - EXPECT_EQ(base::UTF8ToUTF16("syncuser@example.com"), + EXPECT_EQ(base::UTF8ToUTF16(kPrimaryAccountEmail), profiles[0]->GetRawInfo(EMAIL_ADDRESS)); } @@ -5344,9 +5565,6 @@ TEST_F(PersonalDataManagerTest, /////////////////////////////////////////////////////////////////////// personal_data_->ConvertWalletAddressesAndUpdateWalletCards(); - /////////////////////////////////////////////////////////////////////// - // Validation. - /////////////////////////////////////////////////////////////////////// // Since there should be no change in data, OnPersonalDataChanged should not // have been called. EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(0); @@ -5418,6 +5636,7 @@ TEST_F( "2999", "1"); local_card.set_billing_address_id(kServerAddressId); personal_data_->AddCreditCard(local_card); + WaitForOnPersonalDataChanged(); std::vector<CreditCard> server_cards; server_cards.push_back( @@ -6213,6 +6432,10 @@ TEST_F(PersonalDataManagerTest, OnSyncServiceInitialized_NotActiveSyncService) { 1); histogram_tester.ExpectUniqueSample( "Autofill.ResetFullServerCards.NumberOfCardsReset", 1, 1); + + // Call OnSyncShutdown to ensure removing observer added by + // OnSyncServiceInitialized. + personal_data_->OnSyncShutdown(&sync_service); } #endif // !defined(OS_LINUX) || defined(OS_CHROMEOS) @@ -6465,6 +6688,9 @@ TEST_F(PersonalDataManagerTest, ClearCreditCardNonSettingsOrigins) { // Tests that all city fields in a Japan profile are moved to the street address // field. TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) { + // Turn on sync feature to avoid calling MoveJapanCityToStreetAddress on + // adding the profiles implicitly. + ASSERT_TRUE(TurnOnSyncFeature()); // A US profile with both street address and a city. std::string guid0 = base::GenerateGUID(); { @@ -6514,14 +6740,12 @@ TEST_F(PersonalDataManagerTest, MoveJapanCityToStreetAddress) { "JP", ""); AddProfileToPersonalDataManager(profile4); } + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(5U, profiles.size()); - base::RunLoop run_loop; - EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) - .WillRepeatedly(QuitMessageLoop(&run_loop)); - EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()) - .Times(2); // For the Japan profiles where the city is not empty. - personal_data_->MoveJapanCityToStreetAddress(); - run_loop.Run(); + MoveJapanCityToStreetAddress( + personal_data_.get(), + 2); // For the japan profiles where the city is not empty. { AutofillProfile* profile0 = personal_data_->GetProfileByGUID(guid0); @@ -6742,9 +6966,9 @@ 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) { +// Requests profiles fields validities according to the server: empty profiles, +// non-existent profiles, and normal ones. +TEST_F(PersonalDataManagerTest, RequestProfileServerValidity) { ResetPersonalDataManager(USER_MODE_NORMAL); ProfileValidityMap profile_validity_map; @@ -6767,10 +6991,10 @@ TEST_F(PersonalDataManagerTest, RequestProfileValidity) { 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}; + std::vector<AutofillDataModel::ValidityState> states = { + AutofillDataModel::UNSUPPORTED, AutofillDataModel::EMPTY, + AutofillDataModel::INVALID, AutofillDataModel::VALID, + AutofillDataModel::UNVALIDATED, AutofillDataModel::INVALID}; ASSERT_EQ(types.size(), states.size()); for (unsigned long i = 0; i < types.size(); ++i) { (*profile_validity_map @@ -6791,7 +7015,7 @@ TEST_F(PersonalDataManagerTest, RequestProfileValidity) { autofill_profile_validity.clear(); (*profile_validity_map .mutable_field_validity_states())[static_cast<int>(EMAIL_ADDRESS)] = - static_cast<int>(AutofillProfile::VALID); + static_cast<int>(AutofillDataModel::VALID); (*user_profile_validity_map.mutable_profile_validity())[guid] = profile_validity_map; ASSERT_TRUE( @@ -6818,130 +7042,54 @@ TEST_F(PersonalDataManagerTest, RequestProfileValidity) { validities = personal_data_->GetProfileValidityByGUID(guid).field_validity_states(); ASSERT_FALSE(validities.empty()); - EXPECT_EQ(validities.at(EMAIL_ADDRESS), AutofillProfile::VALID); + EXPECT_EQ(validities.at(EMAIL_ADDRESS), AutofillDataModel::VALID); } // Use the client side validation API to validate three PDM profiles. This one // doesn't test the upload process or saving to the database. -TEST_F(PersonalDataManagerTest, UpdateClientValidityStates) { - // Create three profiles and add them to personal_data_. - AutofillProfile valid_profile(test::GetFullValidProfileForCanada()); - valid_profile.set_use_date(AutofillClock::Now()); - valid_profile.set_guid("00000000-0000-0000-0000-000000000001"); - AddProfileToPersonalDataManager(valid_profile); - - AutofillProfile profile_invalid_phone_email( - test::GetFullValidProfileForChina()); - profile_invalid_phone_email.SetRawInfo( - PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("invalid phone number!")); - profile_invalid_phone_email.SetRawInfo(EMAIL_ADDRESS, - base::UTF8ToUTF16("invalid email!")); - profile_invalid_phone_email.set_use_date(AutofillClock::Now() - - base::TimeDelta::FromDays(10)); - profile_invalid_phone_email.set_guid("00000000-0000-0000-0000-000000000002"); - AddProfileToPersonalDataManager(profile_invalid_phone_email); - +TEST_F(PersonalDataManagerMockTest, UpdateClientValidityStates) { AutofillProfile profile_invalid_province(base::GenerateGUID(), test::kEmptyOrigin); test::SetProfileInfo(&profile_invalid_province, "Alice", "", "Munro", "alice@munro.ca", "Fox", "123 Zoo St", "unit 5", "Montreal", "CA", "H3C 2A3", "CA", "15142343254"); - profile_invalid_province.set_guid("00000000-0000-0000-0000-000000000003"); - profile_invalid_province.set_use_date(AutofillClock::Now() - - base::TimeDelta::FromDays(100)); AddProfileToPersonalDataManager(profile_invalid_province); - ASSERT_EQ(3U, personal_data_->GetProfiles().size()); - - // Validate the profiles through the client validation API. + ASSERT_EQ(1U, personal_data_->GetProfiles().size()); auto profiles = personal_data_->GetProfiles(); - for (auto* profile : profiles) { - ASSERT_FALSE(profile->is_client_validity_states_updated()); - // Expect OnValidated to be called for each profile. - ExpectOnValidated(profile); - } + profiles[0]->set_is_client_validity_states_updated(false); - personal_data_->UpdateClientValidityStates(profiles); + UpdateClientValidityStatesOnPersonalDataManager(profiles); + + profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); - ASSERT_EQ(3U, profiles.size()); - // The profiles are ordered according to their guid. - // valid_profile: - ASSERT_EQ(valid_profile.guid(), profiles[0]->guid()); EXPECT_TRUE(profiles[0]->is_client_validity_states_updated()); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::INVALID, profiles[0]->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, + AutofillDataModel::VALID, profiles[0]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profiles[0]->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, + EXPECT_EQ(AutofillDataModel::EMPTY, profiles[0]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillProfile::CLIENT)); EXPECT_EQ( - AutofillProfile::VALID, + AutofillDataModel::VALID, profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profiles[0]->GetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::CLIENT)); - - // profile_invalid_phone_email: - ASSERT_EQ(profile_invalid_phone_email.guid(), profiles[1]->guid()); - EXPECT_TRUE(profiles[1]->is_client_validity_states_updated()); - EXPECT_EQ(AutofillProfile::VALID, - profiles[1]->GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profiles[1]->GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profiles[1]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profiles[1]->GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profiles[1]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::INVALID, - profiles[1]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profiles[1]->GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); - - ASSERT_EQ(profile_invalid_province.guid(), profiles[2]->guid()); - EXPECT_TRUE(profiles[2]->is_client_validity_states_updated()); - EXPECT_EQ(AutofillProfile::VALID, - profiles[2]->GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profiles[2]->GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profiles[2]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, - profiles[2]->GetValidityState(ADDRESS_HOME_CITY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::EMPTY, - profiles[2]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, - AutofillProfile::CLIENT)); - EXPECT_EQ( - AutofillProfile::VALID, - profiles[2]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, - profiles[2]->GetValidityState(PHONE_HOME_WHOLE_NUMBER, - AutofillProfile::CLIENT)); } // Check the validity update status for AutofillProfiles. -TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_UpdatedFlag) { +TEST_F(PersonalDataManagerMockTest, UpdateClientValidityStates_UpdatedFlag) { // Create two profiles and add them to personal_data_. AutofillProfile profile1(test::GetFullValidProfileForCanada()); AddProfileToPersonalDataManager(profile1); @@ -6951,18 +7099,10 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_UpdatedFlag) { ASSERT_EQ(2U, personal_data_->GetProfiles().size()); - // Validate the profiles through the client validation API. + // The validities were set when the profiles were added. auto profiles = personal_data_->GetProfiles(); - ASSERT_FALSE(profiles[0]->is_client_validity_states_updated()); - ASSERT_FALSE(profiles[1]->is_client_validity_states_updated()); - - ExpectOnValidated(profiles[0]); - ExpectOnValidated(profiles[1]); - personal_data_->UpdateClientValidityStates(profiles); - - ASSERT_EQ(2U, profiles.size()); - EXPECT_TRUE(profiles[0]->is_client_validity_states_updated()); - EXPECT_TRUE(profiles[1]->is_client_validity_states_updated()); + ASSERT_TRUE(profiles[0]->is_client_validity_states_updated()); + ASSERT_TRUE(profiles[1]->is_client_validity_states_updated()); *profiles[1] = *profiles[0]; ASSERT_TRUE(profiles[0]->is_client_validity_states_updated()); @@ -6972,118 +7112,189 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_UpdatedFlag) { ASSERT_TRUE(profiles[0]->is_client_validity_states_updated()); ASSERT_FALSE(profiles[1]->is_client_validity_states_updated()); - ExpectOnValidated(profiles[1]); - personal_data_->UpdateClientValidityStates(profiles); + profiles[0]->SetRawInfo(NAME_FULL, base::UTF8ToUTF16("Goli Boli")); ASSERT_TRUE(profiles[0]->is_client_validity_states_updated()); - ASSERT_TRUE(profiles[1]->is_client_validity_states_updated()); +} + +// Check the validity update status for AutofillProfiles. +TEST_F(PersonalDataManagerMockTest, + UpdateClientValidityStates_UpdatedFlag_Merge) { + // Set the pref to the current major version. + StopTheDedupeProcess(); + + AutofillProfile profile1(test::GetFullValidProfileForCanada()); + AddProfileToPersonalDataManager(profile1); + + AutofillProfile profile2(test::GetFullValidProfileForCanada()); + profile2.set_guid("00000000-0000-0000-0000-000000002019"); + profile2.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("")); + AddProfileToPersonalDataManager(profile2); + + // The validities were set when the profiles were added. + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(2U, profiles.size()); profiles[1]->MergeDataFrom(*profiles[0], "en"); ASSERT_TRUE(profiles[0]->is_client_validity_states_updated()); ASSERT_FALSE(profiles[1]->is_client_validity_states_updated()); - - profiles[0]->SetRawInfo(NAME_FULL, base::UTF8ToUTF16("Goli Boli")); - ASSERT_TRUE(profiles[0]->is_client_validity_states_updated()); } // Check that the validity states are not updated when the validity flags are up // to date. -TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_AlreadyUpdated) { +TEST_F(PersonalDataManagerMockTest, UpdateClientValidityStates_AlreadyUpdated) { // Create two profiles and add them to personal_data_. AutofillProfile profile1(test::GetFullValidProfileForCanada()); profile1.SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("invalid email!")); AddProfileToPersonalDataManager(profile1); - AutofillProfile profile2(test::GetFullValidProfileForChina()); - profile2.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("invalid state!")); - AddProfileToPersonalDataManager(profile2); - - EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(0); - auto profiles = personal_data_->GetProfiles(); - ASSERT_EQ(2U, profiles.size()); + ASSERT_EQ(1U, profiles.size()); + // The validities were updated when the profile was added. + EXPECT_EQ( + AutofillDataModel::INVALID, + profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); + + // Change the email, the validity update would turn false. + profiles[0]->SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("alice@gmail.com")); + EXPECT_FALSE(profiles[0]->is_client_validity_states_updated()); // Pretend that the validity states are updated. profiles[0]->set_is_client_validity_states_updated(true); - profiles[1]->set_is_client_validity_states_updated(true); // Validating the profiles through the client validation API should not change // the validity states. personal_data_->UpdateClientValidityStates(profiles); + profiles = personal_data_->GetProfiles(); - ASSERT_EQ(2U, profiles.size()); - EXPECT_EQ(AutofillProfile::UNVALIDATED, - profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT)); + ASSERT_EQ(1U, profiles.size()); EXPECT_EQ( - AutofillProfile::UNVALIDATED, + AutofillDataModel::INVALID, profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNVALIDATED, - profiles[1]->GetValidityState(ADDRESS_HOME_COUNTRY, - AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::UNVALIDATED, - profiles[1]->GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::CLIENT)); + // Try with the flag as not updated. + profiles[0]->set_is_client_validity_states_updated(false); + + UpdateClientValidityStatesOnPersonalDataManager(profiles); + + profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + EXPECT_EQ( + AutofillDataModel::VALID, + profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); } // Verify that the fields are validated according to the version. -TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_Version) { +TEST_F(PersonalDataManagerMockTest, UpdateClientValidityStates_Version) { // Create two profiles and add them to personal_data_. Set the guids // explicitly to preserve the order. - AutofillProfile profile1(test::GetFullValidProfileForCanada()); - profile1.SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("invalid email!")); - profile1.set_guid("00000000-0000-0000-0000-000000000001"); - AddProfileToPersonalDataManager(profile1); - AutofillProfile profile2(test::GetFullValidProfileForChina()); profile2.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("invalid state!")); profile2.set_guid("00000000-0000-0000-0000-000000000002"); + profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(200)); AddProfileToPersonalDataManager(profile2); + AutofillProfile profile1(test::GetFullValidProfileForCanada()); + profile1.SetRawInfo(EMAIL_ADDRESS, base::UTF8ToUTF16("invalid email!")); + profile1.set_use_date(AutofillClock::Now()); + profile1.set_guid("00000000-0000-0000-0000-000000000001"); + AddProfileToPersonalDataManager(profile1); + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(2U, profiles.size()); - // Pretend that the validity states are updated. - profiles[0]->set_is_client_validity_states_updated(true); - profiles[1]->set_is_client_validity_states_updated(true); + EXPECT_TRUE(profiles[0]->is_client_validity_states_updated()); + EXPECT_TRUE(profiles[1]->is_client_validity_states_updated()); + EXPECT_EQ(CHROME_VERSION_MAJOR, GetLastVersionValidatedUpdate()); - // Should validate regardless of the validity update flag, because of the - // major version update. - ResetAutofillLastVersionValidated(); + // No validation as both validity update flags are true, and the validation + // version is set to this version. + base::RunLoop run_loop; + EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(0); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(0); + personal_data_->UpdateClientValidityStates(profiles); profiles = personal_data_->GetProfiles(); ASSERT_EQ(2U, profiles.size()); + ResetAutofillLastVersionValidated(); - ExpectOnValidated(profiles[0]); - ExpectOnValidated(profiles[1]); + EXPECT_EQ(0, GetLastVersionValidatedUpdate()); + EXPECT_TRUE(profiles[0]->is_client_validity_states_updated()); + EXPECT_TRUE(profiles[1]->is_client_validity_states_updated()); + + // Should validate regardless of the validity update flag, because of the + // major version update. + EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(2); + ON_CALL(*personal_data_, OnValidated(testing::_)) + .WillByDefault(testing::Invoke(personal_data_.get(), + &PersonalDataManagerMock::OnValidatedPDM)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillRepeatedly(QuitMessageLoop(&run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(2); + // Validate the profiles through the client validation API. personal_data_->UpdateClientValidityStates(profiles); + run_loop.Run(); - EXPECT_EQ(AutofillProfile::VALID, + profiles = personal_data_->GetProfiles(); + ASSERT_EQ(2U, profiles.size()); + ASSERT_EQ(profiles[0]->guid(), profile1.guid()); + + // Verify that the version of the last update is set to this version. + EXPECT_EQ(CHROME_VERSION_MAJOR, GetLastVersionValidatedUpdate()); + + EXPECT_EQ(AutofillDataModel::VALID, profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); EXPECT_EQ( - AutofillProfile::INVALID, + AutofillDataModel::INVALID, profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::VALID, + EXPECT_EQ(AutofillDataModel::VALID, profiles[1]->GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillProfile::INVALID, + EXPECT_EQ(AutofillDataModel::INVALID, profiles[1]->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT)); +} - // Verify that the version of the last update is set to this version. - EXPECT_EQ(CHROME_VERSION_MAJOR, GetLastVersionValidatedUpdate()); +// Verifies that the profiles are validated when added, updated. +TEST_F(PersonalDataManagerMockTest, UpdateProfilesValidityStates_AddUpdate) { + // Add + AutofillProfile profile1(test::GetFullValidProfileForCanada()); + AddProfileToPersonalDataManager(profile1); - // Update should not update any validity state, because both the validity - // state flag and the version are up to date. - // A fake change in the validity state of profile[1]. - profiles[1]->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID, - AutofillProfile::CLIENT); - EXPECT_CALL(*personal_data_, OnValidated(testing::_)).Times(0); - personal_data_->UpdateClientValidityStates(profiles); - EXPECT_EQ(AutofillProfile::VALID, - profiles[1]->GetValidityState(ADDRESS_HOME_STATE, - AutofillProfile::CLIENT)); + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + EXPECT_EQ(true, profiles[0]->is_client_validity_states_updated()); + + // Update + profile1.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("email!")); + UpdateProfileOnPersonalDataManager(profile1); + + profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + EXPECT_EQ(true, profiles[0]->is_client_validity_states_updated()); +} + +// Verify that slow delayed validation will still work. +TEST_F(PersonalDataManagerMockTest, UpdateClientValidityStates_Delayed) { + personal_data_->set_client_profile_validator_for_test( + TestAutofillProfileValidator::GetDelayedInstance()); + + AutofillProfile profile(test::GetFullProfile()); + AddProfileToPersonalDataManager(profile); + + auto profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + + profiles[0]->set_is_client_validity_states_updated(false); + + UpdateClientValidityStatesOnPersonalDataManager(profiles); + profiles[0] = + nullptr; // make sure the async task doesn't depend on the pointer. + + profiles = personal_data_->GetProfiles(); + ASSERT_EQ(1U, profiles.size()); + EXPECT_TRUE(profiles[0]->is_client_validity_states_updated()); } // The validation should not happen when the feature is disabled. @@ -7101,24 +7312,21 @@ TEST_F(PersonalDataManagerTest, UpdateClientValidityStates_Disabled) { personal_data_->UpdateClientValidityStates(profiles); EXPECT_FALSE(profiles[0]->is_client_validity_states_updated()); - EXPECT_EQ(AutofillProfile::UNVALIDATED, + EXPECT_EQ(AutofillDataModel::UNVALIDATED, profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT)); } TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) { - const std::string kIdentityManagerAccountEmail = "identity_account@email.com"; - const std::string kSyncServiceAccountEmail = "active_sync_account@email.com"; - // Make the IdentityManager return a non-empty AccountInfo when // GetPrimaryAccountInfo() is called. - identity_test_env_.SetPrimaryAccount(kIdentityManagerAccountEmail); + identity_test_env_.SetPrimaryAccount(kPrimaryAccountEmail); ResetPersonalDataManager(USER_MODE_NORMAL); // Make the sync service return a non-empty AccountInfo when // GetAuthenticatedAccountInfo() is called. AccountInfo active_info; - active_info.email = kSyncServiceAccountEmail; + active_info.email = kSyncTransportAccountEmail; sync_service_.SetAuthenticatedAccountInfo(active_info); // The IdentityManager's AccountInfo should be returned by default. @@ -7129,7 +7337,7 @@ TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) { /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage, features::kAutofillGetPaymentsIdentityFromSync}); - EXPECT_EQ(kIdentityManagerAccountEmail, + EXPECT_EQ(kPrimaryAccountEmail, personal_data_->GetAccountInfoForPaymentsServer().email); } @@ -7141,7 +7349,7 @@ TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) { /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage}, /*disabled_features=*/{features::kAutofillGetPaymentsIdentityFromSync}); - EXPECT_EQ(kSyncServiceAccountEmail, + EXPECT_EQ(kSyncTransportAccountEmail, personal_data_->GetAccountInfoForPaymentsServer().email); } @@ -7153,12 +7361,12 @@ TEST_F(PersonalDataManagerTest, GetAccountInfoForPaymentsServer) { /*enabled_features=*/{features::kAutofillGetPaymentsIdentityFromSync}, /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage}); - EXPECT_EQ(kSyncServiceAccountEmail, + EXPECT_EQ(kSyncTransportAccountEmail, personal_data_->GetAccountInfoForPaymentsServer().email); } } -TEST_F(PersonalDataManagerTest, OnGaiaCookieDeletedByUserAction) { +TEST_F(PersonalDataManagerTest, OnAccountsCookieDeletedByUserAction) { // Set up some sync transport opt-ins in the prefs. ::autofill::prefs::SetUserOptedInWalletSyncTransport(prefs_.get(), "account1", true); @@ -7166,7 +7374,7 @@ TEST_F(PersonalDataManagerTest, OnGaiaCookieDeletedByUserAction) { prefs_->GetDictionary(prefs::kAutofillSyncTransportOptIn)->DictEmpty()); // Simulate that the cookies get cleared by the user. - personal_data_->OnGaiaCookieDeletedByUserAction(); + personal_data_->OnAccountsCookieDeletedByUserAction(); // Make sure the pref is now empty. EXPECT_TRUE( @@ -7186,7 +7394,7 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) { // Set everything up so that the proposition should be shown. // Set an an active secondary account. AccountInfo active_info; - active_info.email = "signed_in_account@email.com"; + active_info.email = kPrimaryAccountEmail; active_info.account_id = "account_id"; sync_service_.SetAuthenticatedAccountInfo(active_info); sync_service_.SetIsAuthenticatedAccountPrimary(false); @@ -7258,7 +7466,7 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) { EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption()); // The metric should not be logged if the user had no server cards. histogram_tester.ExpectTotalCount(kHistogramName, 0); - }; + } // Re-set some server cards. Check that the function now returns true. SetServerCards(server_cards); @@ -7311,7 +7519,7 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) { // Set everything up so that the proposition should be shown on Desktop. // Set an an active secondary account. AccountInfo active_info; - active_info.email = "signed_in_account@email.com"; + active_info.email = kPrimaryAccountEmail; active_info.account_id = "account_id"; sync_service_.SetAuthenticatedAccountInfo(active_info); sync_service_.SetIsAuthenticatedAccountPrimary(false); @@ -7444,7 +7652,7 @@ TEST_F(PersonalDataManagerTest, GetSyncSigninState) { // Simulate that the user has enabled the sync feature. AccountInfo primary_account_info; - primary_account_info.email = "active_sync_account@email.com"; + primary_account_info.email = kPrimaryAccountEmail; sync_service_.SetAuthenticatedAccountInfo(primary_account_info); sync_service_.SetIsAuthenticatedAccountPrimary(true); // MakePrimaryAccountAvailable is not supported on CrOS. @@ -7477,10 +7685,9 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { /////////////////////////////////////////////////////////// // Make a non-primary account available with both a refresh token and cookie // to be in Sync Transport for Wallet mode. - AccountInfo active_info; - active_info.email = "test@gmail.com"; - active_info.account_id = "account_id"; - identity_test_env_.SetPrimaryAccount(active_info.email); + CoreAccountInfo active_info = + identity_test_env_.MakeAccountAvailable(kSyncTransportAccountEmail); + identity_test_env_.SetCookieAccounts({{active_info.email, active_info.gaia}}); sync_service_.SetAuthenticatedAccountInfo(active_info); sync_service_.SetIsAuthenticatedAccountPrimary(false); sync_service_.SetActiveDataTypes( @@ -7488,13 +7695,10 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { // Make sure there are no opt-ins recorded yet. ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(), active_info.account_id)); -// The kSignedInAndWalletSyncTransportEnabled state is not available on CrOS. -#if !defined(OS_CHROMEOS) { base::test::ScopedFeatureList scoped_features; - scoped_features.InitWithFeatures( - /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage}, - /*disabled_features=*/{}); + scoped_features.InitAndEnableFeature( + features::kAutofillEnableAccountWalletStorage); EXPECT_EQ(AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled, personal_data_->GetSyncSigninState()); @@ -7504,7 +7708,6 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { EXPECT_TRUE(prefs::IsUserOptedInWalletSyncTransport( prefs_.get(), active_info.account_id)); } -#endif // !defined(OS_CHROMEOS) // Clear the prefs. prefs::ClearSyncTransportOptIns(prefs_.get()); @@ -7515,10 +7718,11 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { // kSignedIn /////////////////////////////////////////////////////////// { + // Without AccountWalletStorage, kSignedInAndWalletSyncTransportEnabled + // shouldn't be available. base::test::ScopedFeatureList scoped_features; - scoped_features.InitWithFeatures( - /*enabled_features=*/{}, - /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage}); + scoped_features.InitAndDisableFeature( + features::kAutofillEnableAccountWalletStorage); EXPECT_EQ(AutofillSyncSigninState::kSignedIn, personal_data_->GetSyncSigninState()); @@ -7536,11 +7740,11 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { active_info.account_id)); /////////////////////////////////////////////////////////// - // kSignedInAndSyncFeature + // kSignedOut /////////////////////////////////////////////////////////// - sync_service_.SetIsAuthenticatedAccountPrimary(true); + identity_test_env_.RemoveRefreshTokenForAccount(active_info.account_id); { - EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeature, + EXPECT_EQ(AutofillSyncSigninState::kSignedOut, personal_data_->GetSyncSigninState()); // Make sure an opt-in does not get recorded even if the user accepted an @@ -7550,19 +7754,13 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { prefs_.get(), active_info.account_id)); } - // Clear the prefs. - prefs::ClearSyncTransportOptIns(prefs_.get()); - ASSERT_FALSE(prefs::IsUserOptedInWalletSyncTransport(prefs_.get(), - active_info.account_id)); - /////////////////////////////////////////////////////////// - // kSignedOut + // kSignedInAndSyncFeature /////////////////////////////////////////////////////////// -// ClearPrimaryAccount is not supported on CrOS. -#if !defined(OS_CHROMEOS) + identity_test_env_.SetPrimaryAccount(active_info.email); + sync_service_.SetIsAuthenticatedAccountPrimary(true); { - identity_test_env_.ClearPrimaryAccount(); - EXPECT_EQ(AutofillSyncSigninState::kSignedOut, + EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeature, personal_data_->GetSyncSigninState()); // Make sure an opt-in does not get recorded even if the user accepted an @@ -7571,7 +7769,6 @@ TEST_F(PersonalDataManagerTest, OnUserAcceptedUpstreamOffer) { EXPECT_FALSE(prefs::IsUserOptedInWalletSyncTransport( prefs_.get(), active_info.account_id)); } -#endif // !defined(OS_CHROMEOS) } } // namespace autofill diff --git a/chromium/components/autofill/core/browser/phone_number_i18n.cc b/chromium/components/autofill/core/browser/phone_number_i18n.cc index f4e7e3ba8fb..956eed000e7 100644 --- a/chromium/components/autofill/core/browser/phone_number_i18n.cc +++ b/chromium/components/autofill/core/browser/phone_number_i18n.cc @@ -214,7 +214,7 @@ bool ParsePhoneNumber(const base::string16& value, i18n_number->country_code_source() != ::i18n::phonenumbers::PhoneNumber::FROM_DEFAULT_COUNTRY) { *country_code = - base::UTF8ToUTF16(base::IntToString(i18n_number->country_code())); + base::UTF8ToUTF16(base::NumberToString(i18n_number->country_code())); } // The region might be different from what we started with. @@ -329,6 +329,15 @@ base::string16 GetFormattedPhoneNumberForDisplay(const AutofillProfile& profile, return base::UTF8ToUTF16(phone); } +std::string FormatPhoneNationallyForDisplay(const std::string& phone_number, + const std::string& country_code) { + if (IsValidPhoneNumber(phone_number, country_code)) { + return FormatPhoneNumber(phone_number, country_code, + PhoneNumberUtil::PhoneNumberFormat::NATIONAL); + } + return phone_number; +} + std::string FormatPhoneForDisplay(const std::string& phone_number, const std::string& country_code) { if (IsValidPhoneNumber(phone_number, country_code)) { diff --git a/chromium/components/autofill/core/browser/phone_number_i18n.h b/chromium/components/autofill/core/browser/phone_number_i18n.h index 5f6f7674e2d..8def9448679 100644 --- a/chromium/components/autofill/core/browser/phone_number_i18n.h +++ b/chromium/components/autofill/core/browser/phone_number_i18n.h @@ -90,12 +90,18 @@ bool PhoneNumbersMatch(const base::string16& number_a, const std::string& app_locale); // Returns the phone number from the given |profile| formatted for display. -// If it's valid number for the country of profile, or for the |locale| given -// as a fall back, return the number in internaional format; otherwise return +// If it's a valid number for the profile's country or for the |locale| given +// as a fallback, returns the number in international format; otherwise returns // the raw number string from profile. base::string16 GetFormattedPhoneNumberForDisplay(const AutofillProfile& profile, const std::string& locale); +// Returns |phone_number| in i18n::phonenumbers::PhoneNumberUtil:: +// PhoneNumberFormat::NATIONAL format if the number is valid for +// |country_code|. Otherwise, returns the given |phone_number|. +std::string FormatPhoneNationallyForDisplay(const std::string& phone_number, + const std::string& country_code); + // Formats the given number |phone_number| to // i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL format // by using i18n::phonenumbers::PhoneNumberUtil::Format. diff --git a/chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc b/chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc index 54103973681..a65481ec311 100644 --- a/chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc +++ b/chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc @@ -90,7 +90,7 @@ TEST_P(ParseNumberTest, ParsePhoneNumber) { EXPECT_EQ(test_case.deduced_region, deduced_region); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( PhoneNumberI18NTest, ParseNumberTest, testing::Values( @@ -272,6 +272,37 @@ TEST(PhoneNumberUtilTest, FormatPhoneForResponse) { i18n::FormatPhoneForResponse("(1) 515-123-1234", "US")); } +// Tests that phone numbers are correctly formatted in a national format. +TEST(PhoneNumberUtilTest, FormatPhoneNationallyForDisplay) { + // Invalid US and Brazilian numbers are not formatted. + EXPECT_EQ("1234567890", + i18n::FormatPhoneNationallyForDisplay("1234567890", "US")); + EXPECT_EQ("(11) 13333-4444", + i18n::FormatPhoneNationallyForDisplay("(11) 13333-4444", "BR")); + EXPECT_EQ("(11) 13333-4444", + i18n::FormatPhoneNationallyForDisplay("(11) 13333-4444", "IN")); + + // Valid US, Canadian, UK, and Brazilian numbers are nationally formatted. + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("2024440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("+1(202)4440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("12024440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("(202)4440000", "US")); + EXPECT_EQ("(202) 444-0000", + i18n::FormatPhoneNationallyForDisplay("202-444-0000", "US")); + EXPECT_EQ("(819) 555-9999", + i18n::FormatPhoneNationallyForDisplay("+1(819)555 9999", "CA")); + EXPECT_EQ("(819) 555-9999", + i18n::FormatPhoneNationallyForDisplay("18195559999", "CA")); + EXPECT_EQ("020 7601 4444", + i18n::FormatPhoneNationallyForDisplay("+4402076014444", "UK")); + EXPECT_EQ("(21) 3883-5600", + i18n::FormatPhoneNationallyForDisplay("2138835600", "BR")); +} + // Tests that the phone numbers are correctly formatted to display to the user. TEST(PhoneNumberUtilTest, FormatPhoneForDisplay) { // Invalid number is not formatted. @@ -314,7 +345,7 @@ TEST_P(GetFormattedPhoneNumberForDisplayTest, profile, GetParam().locale))); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( GetFormattedPhoneNumberForDisplay, GetFormattedPhoneNumberForDisplayTest, testing::Values( @@ -421,7 +452,7 @@ INSTANTIATE_TEST_CASE_P( // This number is not a valid US number, we won't try to format. PhoneNumberFormatCase("55 5342 8400", "US", "5553428400"))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( GetFormattedPhoneNumberForDisplay_EdgeCases, GetFormattedPhoneNumberForDisplayTest, testing::Values( diff --git a/chromium/components/autofill/core/browser/price_field.cc b/chromium/components/autofill/core/browser/price_field.cc new file mode 100644 index 00000000000..59cbca3b493 --- /dev/null +++ b/chromium/components/autofill/core/browser/price_field.cc @@ -0,0 +1,34 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/price_field.h" + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/autofill_scanner.h" +#include "components/autofill/core/common/autofill_regex_constants.h" + +namespace autofill { + +// static +std::unique_ptr<FormField> PriceField::Parse(AutofillScanner* scanner) { + AutofillField* field; + if (ParseFieldSpecifics( + scanner, base::UTF8ToUTF16(kPriceRe), + MATCH_DEFAULT | MATCH_NUMBER | MATCH_SELECT | MATCH_TEXT_AREA, + &field)) { + return std::make_unique<PriceField>(field); + } + + return nullptr; +} + +PriceField::PriceField(const AutofillField* field) : field_(field) {} + +void PriceField::AddClassifications( + FieldCandidatesMap* field_candidates) const { + AddClassification(field_, PRICE, kBasePriceParserScore, field_candidates); +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/price_field.h b/chromium/components/autofill/core/browser/price_field.h new file mode 100644 index 00000000000..65989b8ad10 --- /dev/null +++ b/chromium/components/autofill/core/browser/price_field.h @@ -0,0 +1,40 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PRICE_FIELD_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PRICE_FIELD_H_ + +#include <memory> + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "components/autofill/core/browser/form_field.h" + +namespace autofill { + +class AutofillField; +class AutofillScanner; + +// Price fields are not filled by autofill, but identifying them will help to +// reduce the number of false positives. +class PriceField : public FormField { + public: + static std::unique_ptr<FormField> Parse(AutofillScanner* scanner); + PriceField(const AutofillField* field); + + protected: + void AddClassifications(FieldCandidatesMap* field_candidates) const override; + + private: + FRIEND_TEST_ALL_PREFIXES(PriceFieldTest, ParsePrice); + FRIEND_TEST_ALL_PREFIXES(PriceFieldTest, ParseNonPrice); + + const AutofillField* field_; + + DISALLOW_COPY_AND_ASSIGN(PriceField); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PRICE_FIELD_H_ diff --git a/chromium/components/autofill/core/browser/price_field_unittest.cc b/chromium/components/autofill/core/browser/price_field_unittest.cc new file mode 100644 index 00000000000..626cac72591 --- /dev/null +++ b/chromium/components/autofill/core/browser/price_field_unittest.cc @@ -0,0 +1,78 @@ +// 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/price_field.h" + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_field.h" +#include "components/autofill/core/browser/autofill_scanner.h" +#include "components/autofill/core/common/form_field_data.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::ASCIIToUTF16; + +namespace autofill { + +class PriceFieldTest : public testing::Test { + public: + PriceFieldTest() {} + + protected: + std::vector<std::unique_ptr<AutofillField>> list_; + std::unique_ptr<PriceField> field_; + FieldCandidatesMap field_candidates_map_; + + // Downcast for tests. + static std::unique_ptr<PriceField> Parse(AutofillScanner* scanner) { + std::unique_ptr<FormField> field = PriceField::Parse(scanner); + return std::unique_ptr<PriceField>( + static_cast<PriceField*>(field.release())); + } + + private: + DISALLOW_COPY_AND_ASSIGN(PriceFieldTest); +}; + +TEST_F(PriceFieldTest, ParsePrice) { + FormFieldData price_field; + price_field.form_control_type = "text"; + + price_field.label = ASCIIToUTF16("name your price"); + price_field.name = ASCIIToUTF16("userPrice"); + + list_.push_back( + std::make_unique<AutofillField>(price_field, ASCIIToUTF16("price1"))); + + AutofillScanner scanner(list_); + field_ = Parse(&scanner); + ASSERT_NE(nullptr, field_.get()); + field_->AddClassifications(&field_candidates_map_); + ASSERT_TRUE(field_candidates_map_.find(ASCIIToUTF16("price1")) != + field_candidates_map_.end()); + EXPECT_EQ(PRICE, + field_candidates_map_[ASCIIToUTF16("price1")].BestHeuristicType()); +} + +TEST_F(PriceFieldTest, ParseNonPrice) { + FormFieldData address_field; + address_field.form_control_type = "text"; + + address_field.label = ASCIIToUTF16("Name"); + address_field.name = ASCIIToUTF16("firstName"); + + list_.push_back( + std::make_unique<AutofillField>(address_field, ASCIIToUTF16("name1"))); + + AutofillScanner scanner(list_); + field_ = Parse(&scanner); + ASSERT_EQ(nullptr, field_.get()); +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/proto/server.proto b/chromium/components/autofill/core/browser/proto/server.proto index 079c9449ffc..86bc91e222d 100644 --- a/chromium/components/autofill/core/browser/proto/server.proto +++ b/chromium/components/autofill/core/browser/proto/server.proto @@ -14,7 +14,7 @@ import "password_requirements.proto"; // Request to query field suggestions for forms in a page from legacy Autofill // API. -// Next available id: 14 +// Next available id: 15 message AutofillQueryContents { reserved 11; // Reserved for server use. required string client_version = 1; @@ -28,6 +28,7 @@ message AutofillQueryContents { optional AutofillRandomizedFieldMetadata field_metadata = 13; } } + repeated int64 experiments = 14; } // Response from Autofill query on the legacy API that gives field suggestions @@ -185,7 +186,7 @@ message AutofillRandomizedFieldMetadata { // This message contains information about the field types in a single form. // It is sent by the toolbar to contribute to the field type statistics. -// Next available id: 38 +// Next available id: 39 message AutofillUploadContents { required string client_version = 1; required fixed64 form_signature = 2; @@ -396,6 +397,9 @@ message AutofillUploadContents { // Whether the fields are enclosed by a <form> tag or are unowned elements. optional bool has_form_tag = 37; + + // Captures whether or not this upload was a candidate for throttling. + optional bool was_throttleable = 38; } // This proto contains information about the validity of each field in an diff --git a/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc b/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc index d034c86cae0..9819106c68c 100644 --- a/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc +++ b/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc @@ -160,9 +160,9 @@ TEST_P(RandomizedEncoderTest, EncodeLarge) { EXPECT_EQ(expected_result, actual_result); } -INSTANTIATE_TEST_CASE_P(All, - RandomizedEncoderTest, - ::testing::ValuesIn(kEncodeParams)); +INSTANTIATE_TEST_SUITE_P(All, + RandomizedEncoderTest, + ::testing::ValuesIn(kEncodeParams)); namespace { @@ -321,6 +321,6 @@ TEST_P(RandomizedDecoderTest, Decode) { } } -INSTANTIATE_TEST_CASE_P(All, - RandomizedDecoderTest, - ::testing::ValuesIn(kDecodeParams)); +INSTANTIATE_TEST_SUITE_P(All, + RandomizedDecoderTest, + ::testing::ValuesIn(kDecodeParams)); 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 698c425dda9..c54700b584f 100644 --- a/chromium/components/autofill/core/browser/region_data_loader_impl.cc +++ b/chromium/components/autofill/core/browser/region_data_loader_impl.cc @@ -4,6 +4,7 @@ #include "components/autofill/core/browser/region_data_loader_impl.h" +#include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/region_data.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/region_data_builder.h" diff --git a/chromium/components/autofill/core/browser/search_field.cc b/chromium/components/autofill/core/browser/search_field.cc index f2b19b9461d..f684baea1f1 100644 --- a/chromium/components/autofill/core/browser/search_field.cc +++ b/chromium/components/autofill/core/browser/search_field.cc @@ -5,6 +5,7 @@ #include "components/autofill/core/browser/search_field.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_scanner.h" #include "components/autofill/core/common/autofill_regex_constants.h" @@ -14,7 +15,8 @@ namespace autofill { std::unique_ptr<FormField> SearchField::Parse(AutofillScanner* scanner) { AutofillField* field; if (ParseFieldSpecifics(scanner, base::UTF8ToUTF16(kSearchTermRe), - MATCH_DEFAULT | MATCH_SEARCH, &field)) { + MATCH_DEFAULT | MATCH_SEARCH | MATCH_TEXT_AREA, + &field)) { return std::make_unique<SearchField>(field); } diff --git a/chromium/components/autofill/core/browser/search_field.h b/chromium/components/autofill/core/browser/search_field.h index 41d0c396d1d..bfbf77f71c3 100644 --- a/chromium/components/autofill/core/browser/search_field.h +++ b/chromium/components/autofill/core/browser/search_field.h @@ -13,6 +13,9 @@ namespace autofill { +class AutofillField; +class AutofillScanner; + // Search fields are not filled by autofill, but identifying them will help // to reduce the number of false positives. class SearchField : public FormField { diff --git a/chromium/components/autofill/core/browser/strike_database.cc b/chromium/components/autofill/core/browser/strike_database.cc index 0e247e7d2e3..41002501b2b 100644 --- a/chromium/components/autofill/core/browser/strike_database.cc +++ b/chromium/components/autofill/core/browser/strike_database.cc @@ -4,6 +4,7 @@ #include "components/autofill/core/browser/strike_database.h" +#include <algorithm> #include <string> #include <utility> #include <vector> @@ -39,7 +40,7 @@ StrikeDatabase::StrikeDatabase(const base::FilePath& database_dir) StrikeDatabase::~StrikeDatabase() {} -int StrikeDatabase::AddStrikes(int strikes_increase, const std::string key) { +int StrikeDatabase::AddStrikes(int strikes_increase, const std::string& key) { DCHECK(strikes_increase > 0); int num_strikes = strike_map_cache_.count(key) // Cache has entry for |key|. @@ -49,29 +50,41 @@ int StrikeDatabase::AddStrikes(int strikes_increase, const std::string key) { return num_strikes; } -int StrikeDatabase::RemoveStrikes(int strikes_decrease, const std::string key) { - DCHECK(strikes_decrease > 0); - DCHECK(strike_map_cache_.count(key)); - int num_strikes = strike_map_cache_[key].num_strikes() - strikes_decrease; - if (num_strikes < 1) { - ClearStrikes(key); - return 0; - } +int StrikeDatabase::RemoveStrikes(int strikes_decrease, + const std::string& key) { + int num_strikes = GetStrikes(key); + num_strikes = std::max(0, num_strikes - strikes_decrease); SetStrikeData(key, num_strikes); return num_strikes; } -int StrikeDatabase::GetStrikes(const std::string key) { - return strike_map_cache_.count(key) // Cache contains entry for |key|. - ? strike_map_cache_[key].num_strikes() - : 0; +int StrikeDatabase::GetStrikes(const std::string& key) { + auto iter = strike_map_cache_.find(key); + return (iter != strike_map_cache_.end()) ? iter->second.num_strikes() : 0; } -void StrikeDatabase::ClearStrikes(const std::string key) { +void StrikeDatabase::ClearStrikes(const std::string& key) { strike_map_cache_.erase(key); ClearAllProtoStrikesForKey(key, base::DoNothing()); } +void StrikeDatabase::ClearAllStrikesForProject( + const std::string& project_prefix) { + std::vector<std::string> keys_to_delete; + for (std::pair<std::string, StrikeData> entry : strike_map_cache_) { + if (entry.first.find(project_prefix) == 0) { + keys_to_delete.push_back(entry.first); + } + } + for (std::string key : keys_to_delete) + ClearStrikes(key); +} + +void StrikeDatabase::ClearAllStrikes() { + strike_map_cache_.clear(); + ClearAllProtoStrikes(base::DoNothing()); +} + StrikeDatabase::StrikeDatabase() : db_(nullptr), database_dir_(base::FilePath(nullptr)), @@ -106,7 +119,11 @@ void StrikeDatabase::OnDatabaseLoadKeysAndEntries( strike_map_cache_.insert(entries->begin(), entries->end()); } -void StrikeDatabase::SetStrikeData(const std::string key, int num_strikes) { +void StrikeDatabase::SetStrikeData(const std::string& key, int num_strikes) { + if (num_strikes == 0) { + ClearStrikes(key); + return; + } StrikeData data; data.set_num_strikes(num_strikes); data.set_last_update_timestamp( @@ -115,7 +132,7 @@ void StrikeDatabase::SetStrikeData(const std::string key, int num_strikes) { SetProtoStrikeData(key, data, base::DoNothing()); } -void StrikeDatabase::GetProtoStrikes(const std::string key, +void StrikeDatabase::GetProtoStrikes(const std::string& key, const StrikesCallback& outer_callback) { if (!database_initialized_) { outer_callback.Run(false); @@ -156,7 +173,7 @@ void StrikeDatabase::ClearAllProtoStrikesForKey( /*keys_to_remove=*/std::move(keys_to_remove), outer_callback); } -void StrikeDatabase::GetProtoStrikeData(const std::string key, +void StrikeDatabase::GetProtoStrikeData(const std::string& key, const GetValueCallback& callback) { if (!database_initialized_) { callback.Run(false, nullptr); @@ -200,4 +217,8 @@ void StrikeDatabase::UpdateCache(const std::string& key, strike_map_cache_[key] = data; } +std::string StrikeDatabase::GetPrefixFromKey(const std::string& key) { + return key.substr(0, key.find(kKeyDeliminator)); +} + } // namespace autofill diff --git a/chromium/components/autofill/core/browser/strike_database.h b/chromium/components/autofill/core/browser/strike_database.h index bea6da0aa80..8b8915df770 100644 --- a/chromium/components/autofill/core/browser/strike_database.h +++ b/chromium/components/autofill/core/browser/strike_database.h @@ -16,6 +16,11 @@ #include "components/leveldb_proto/public/proto_database.h" namespace autofill { + +namespace { +const char kKeyDeliminator[] = "__"; +} // namespace + class StrikeData; // Manages data on whether different Autofill opportunities should be offered to @@ -49,18 +54,26 @@ class StrikeDatabase : public KeyedService { // Increases in-memory cache by |strikes_increase| and updates underlying // ProtoDatabase. - int AddStrikes(int strikes_increase, const std::string key); + int AddStrikes(int strikes_increase, const std::string& key); // Removes |strikes_decrease| in-memory cache strikes, updates // last_update_timestamp, and updates underlying ProtoDatabase. - int RemoveStrikes(int strikes_decrease, const std::string key); + int RemoveStrikes(int strikes_decrease, const std::string& key); // Returns strike count from in-memory cache. - int GetStrikes(const std::string key); + int GetStrikes(const std::string& key); + + // Removes database entry for |key| from in-memory cache and underlying + // ProtoDatabase. + void ClearStrikes(const std::string& key); + + // Removes all database entries from in-memory cache and underlying + // ProtoDatabase for the whole project. + void ClearAllStrikesForProject(const std::string& project_prefix); // Removes all database entries from in-memory cache and underlying // ProtoDatabase. - void ClearStrikes(const std::string key); + void ClearAllStrikes(); protected: friend class StrikeDatabaseIntegratorBase; @@ -92,6 +105,7 @@ class StrikeDatabase : public KeyedService { GetIdForCreditCardSaveTest); FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, RemoveExpiredStrikesOnLoadTest); + friend class SaveCardInfobarEGTestHelper; friend class StrikeDatabaseTest; friend class StrikeDatabaseTester; @@ -102,13 +116,13 @@ class StrikeDatabase : public KeyedService { std::unique_ptr<std::map<std::string, StrikeData>> entries); // Updates the StrikeData for |key| in the cache and ProtoDatabase to have - // |num_stikes|, and the current time as timestamp. - void SetStrikeData(const std::string key, int num_strikes); + // |num_strikes|, and the current time as timestamp. + void SetStrikeData(const std::string& key, int num_strikes); // Passes the number of strikes for |key| to |outer_callback|. In the case // that the database fails to retrieve the strike update or if no entry is // found for |key|, 0 is passed. - virtual void GetProtoStrikes(const std::string key, + virtual void GetProtoStrikes(const std::string& key, const StrikesCallback& outer_callback); // Removes all database entries, which ensures there will be no saved strikes @@ -123,7 +137,7 @@ class StrikeDatabase : public KeyedService { const ClearStrikesCallback& outer_callback); // Passes success status and StrikeData entry for |key| to |inner_callback|. - void GetProtoStrikeData(const std::string key, + void GetProtoStrikeData(const std::string& key, const GetValueCallback& inner_callback); // Sets the entry for |key| to |strike_data|. Success status is passed to the @@ -143,6 +157,9 @@ class StrikeDatabase : public KeyedService { // Sets the entry for |key| in |strike_map_cache_| to |data|. void UpdateCache(const std::string& key, const StrikeData& data); + // Extracts per-project prefix from |key|. + std::string GetPrefixFromKey(const std::string& key); + base::WeakPtrFactory<StrikeDatabase> weak_ptr_factory_; }; diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_base.cc b/chromium/components/autofill/core/browser/strike_database_integrator_base.cc index f6438197ffd..5b0426188a7 100644 --- a/chromium/components/autofill/core/browser/strike_database_integrator_base.cc +++ b/chromium/components/autofill/core/browser/strike_database_integrator_base.cc @@ -4,6 +4,7 @@ #include "components/autofill/core/browser/strike_database_integrator_base.h" +#include <algorithm> #include <string> #include <utility> #include <vector> @@ -19,10 +20,6 @@ namespace autofill { -namespace { -const char kKeyDeliminator[] = "__"; -} // namespace - StrikeDatabaseIntegratorBase::StrikeDatabaseIntegratorBase( StrikeDatabase* strike_database) : strike_database_(strike_database) {} @@ -30,18 +27,18 @@ StrikeDatabaseIntegratorBase::StrikeDatabaseIntegratorBase( StrikeDatabaseIntegratorBase::~StrikeDatabaseIntegratorBase() {} bool StrikeDatabaseIntegratorBase::IsMaxStrikesLimitReached( - const std::string id) { + const std::string& id) { CheckIdUniqueness(id); return GetStrikes(id) >= GetMaxStrikesLimit(); } -int StrikeDatabaseIntegratorBase::AddStrike(const std::string id) { +int StrikeDatabaseIntegratorBase::AddStrike(const std::string& id) { CheckIdUniqueness(id); return AddStrikes(1, id); } int StrikeDatabaseIntegratorBase::AddStrikes(int strikes_increase, - const std::string id) { + const std::string& id) { CheckIdUniqueness(id); int num_strikes = strike_database_->AddStrikes(strikes_increase, GetKey(id)); base::UmaHistogramCounts1000( @@ -50,42 +47,58 @@ int StrikeDatabaseIntegratorBase::AddStrikes(int strikes_increase, return num_strikes; } -int StrikeDatabaseIntegratorBase::RemoveStrike(const std::string id) { +int StrikeDatabaseIntegratorBase::RemoveStrike(const std::string& id) { CheckIdUniqueness(id); return strike_database_->RemoveStrikes(1, GetKey(id)); } -int StrikeDatabaseIntegratorBase::RemoveStrikes(int strikes_decrease, - const std::string id) { +int StrikeDatabaseIntegratorBase::RemoveStrikes(int strike_decrease, + const std::string& id) { CheckIdUniqueness(id); - return strike_database_->RemoveStrikes(strikes_decrease, GetKey(id)); + return strike_database_->RemoveStrikes(strike_decrease, GetKey(id)); } -int StrikeDatabaseIntegratorBase::GetStrikes(const std::string id) { +int StrikeDatabaseIntegratorBase::GetStrikes(const std::string& id) { CheckIdUniqueness(id); return strike_database_->GetStrikes(GetKey(id)); } -void StrikeDatabaseIntegratorBase::ClearStrikes(const std::string id) { +void StrikeDatabaseIntegratorBase::ClearStrikes(const std::string& id) { CheckIdUniqueness(id); strike_database_->ClearStrikes(GetKey(id)); } +void StrikeDatabaseIntegratorBase::ClearAllStrikes() { + strike_database_->ClearAllStrikesForProject(GetProjectPrefix()); +} + void StrikeDatabaseIntegratorBase::RemoveExpiredStrikes() { std::vector<std::string> expired_keys; for (auto entry : strike_database_->strike_map_cache_) { if (AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds() - entry.second.last_update_timestamp() > GetExpiryTimeMicros()) { - if (strike_database_->GetStrikes(entry.first) > 0) + if (strike_database_->GetStrikes(entry.first) > 0) { expired_keys.push_back(entry.first); + base::UmaHistogramCounts1000( + "Autofill.StrikeDatabase.StrikesPresentWhenStrikeExpired." + + strike_database_->GetPrefixFromKey(entry.first), + strike_database_->GetStrikes(entry.first)); + } } } - for (std::string key : expired_keys) - strike_database_->RemoveStrikes(1, key); + for (std::string key : expired_keys) { + int strikes_to_remove = 1; + // If the key is already over the limit, remove additional strikes to + // emulate setting it back to the limit. These are done together to avoid + // multiple calls to the file system ProtoDatabase. + strikes_to_remove += + std::max(0, strike_database_->GetStrikes(key) - GetMaxStrikesLimit()); + strike_database_->RemoveStrikes(strikes_to_remove, key); + } } -std::string StrikeDatabaseIntegratorBase::GetKey(const std::string id) { +std::string StrikeDatabaseIntegratorBase::GetKey(const std::string& id) { return GetProjectPrefix() + kKeyDeliminator + id; } diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_base.h b/chromium/components/autofill/core/browser/strike_database_integrator_base.h index 9f207da9d94..3e1bf565d8a 100644 --- a/chromium/components/autofill/core/browser/strike_database_integrator_base.h +++ b/chromium/components/autofill/core/browser/strike_database_integrator_base.h @@ -24,29 +24,33 @@ class StrikeDatabaseIntegratorBase { // Returns whether or not strike count for |id| has reached the strike limit // set by GetMaxStrikesLimit(). - bool IsMaxStrikesLimitReached(const std::string id = kSharedId); + bool IsMaxStrikesLimitReached(const std::string& id = kSharedId); // Increments in-memory cache and updates underlying ProtoDatabase. - int AddStrike(const std::string id = kSharedId); + int AddStrike(const std::string& id = kSharedId); // Increases in-memory cache by |strikes_increase| and updates underlying // ProtoDatabase. - int AddStrikes(int strikes_increase, const std::string id = kSharedId); + int AddStrikes(int strikes_increase, const std::string& id = kSharedId); // Removes an in-memory cache strike, updates last_update_timestamp, and // updates underlying ProtoDatabase. - int RemoveStrike(const std::string id = kSharedId); + int RemoveStrike(const std::string& id = kSharedId); // Removes |strikes_decrease| in-memory cache strikes, updates // |last_update_timestamp|, and updates underlying ProtoDatabase. - int RemoveStrikes(int strikes_decrease, const std::string id = kSharedId); + int RemoveStrikes(int strikes_decrease, const std::string& id = kSharedId); // Returns strike count from in-memory cache. - int GetStrikes(const std::string id = kSharedId); + int GetStrikes(const std::string& id = kSharedId); // Removes all database entries from in-memory cache and underlying // ProtoDatabase. - void ClearStrikes(const std::string id = kSharedId); + void ClearStrikes(const std::string& id = kSharedId); + + // Removes all database entries from in-memory cache and underlying + // ProtoDatabase for the whole project. + void ClearAllStrikes(); protected: // Removes all strikes in which it has been longer than GetExpiryTimeMicros() @@ -56,14 +60,15 @@ class StrikeDatabaseIntegratorBase { private: FRIEND_TEST_ALL_PREFIXES(ChromeBrowsingDataRemoverDelegateTest, StrikeDatabaseEmptyOnAutofillRemoveEverything); - FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, - GetKeyForCreditCardSaveTest); - FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, - GetIdForCreditCardSaveTest); - FRIEND_TEST_ALL_PREFIXES(CreditCardSaveStrikeDatabaseTest, - RemoveExpiredStrikesTest); - FRIEND_TEST_ALL_PREFIXES(LocalCardMigrationStrikeDatabaseTest, + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, RemoveExpiredStrikesTest); + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + GetKeyForStrikeDatabaseIntegratorUniqueIdTest); + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesUniqueIdTest); + FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesTestLogsUMA); + friend class SaveCardInfobarEGTestHelper; friend class StrikeDatabaseTest; friend class StrikeDatabaseTester; @@ -79,7 +84,7 @@ class StrikeDatabaseIntegratorBase { } // Generates key based on project-specific string identifier. - std::string GetKey(const std::string id); + std::string GetKey(const std::string& id); // Returns a prefix unique to each project, which will be used to create // database key. diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc new file mode 100644 index 00000000000..c5be5139c42 --- /dev/null +++ b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc @@ -0,0 +1,46 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h" + +#include "components/autofill/core/browser/proto/strike_data.pb.h" + +namespace autofill { + +const char kProjectPrefix[] = "StrikeDatabaseIntegratorTest"; +const int kMaxStrikesLimit = 6; +// Expiry time is 1 year. +const long long kExpiryTimeMicros = (long long)1000000 * 60 * 60 * 24 * 365; + +StrikeDatabaseIntegratorTestStrikeDatabase:: + StrikeDatabaseIntegratorTestStrikeDatabase(StrikeDatabase* strike_database) + : StrikeDatabaseIntegratorBase(strike_database) { + RemoveExpiredStrikes(); +} + +StrikeDatabaseIntegratorTestStrikeDatabase:: + ~StrikeDatabaseIntegratorTestStrikeDatabase() {} + +std::string StrikeDatabaseIntegratorTestStrikeDatabase::GetProjectPrefix() { + return kProjectPrefix; +} + +int StrikeDatabaseIntegratorTestStrikeDatabase::GetMaxStrikesLimit() { + return kMaxStrikesLimit; +} + +long long StrikeDatabaseIntegratorTestStrikeDatabase::GetExpiryTimeMicros() { + return kExpiryTimeMicros; +} + +bool StrikeDatabaseIntegratorTestStrikeDatabase::UniqueIdsRequired() { + return unique_ids_required_; +} + +void StrikeDatabaseIntegratorTestStrikeDatabase::SetUniqueIdsRequired( + bool unique_ids_required) { + unique_ids_required_ = unique_ids_required; +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h new file mode 100644 index 00000000000..3a50f6e75f5 --- /dev/null +++ b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h @@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_ + +#include <string> + +#include "components/autofill/core/browser/strike_database.h" +#include "components/autofill/core/browser/strike_database_integrator_base.h" + +namespace autofill { + +// Mock per-project implementation of StrikeDatabase to test the functions in +// StrikeDatabaseIntegrator. +class StrikeDatabaseIntegratorTestStrikeDatabase + : public StrikeDatabaseIntegratorBase { + public: + StrikeDatabaseIntegratorTestStrikeDatabase(StrikeDatabase* strike_database); + ~StrikeDatabaseIntegratorTestStrikeDatabase() override; + + std::string GetProjectPrefix() override; + int GetMaxStrikesLimit() override; + long long GetExpiryTimeMicros() override; + bool UniqueIdsRequired() override; + + void SetUniqueIdsRequired(bool unique_ids_required); + + private: + bool unique_ids_required_ = false; +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_ diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc new file mode 100644 index 00000000000..a6e961b7fde --- /dev/null +++ b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc @@ -0,0 +1,289 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h" + +#include <utility> +#include <vector> + +#include "base/files/scoped_temp_dir.h" +#include "base/run_loop.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/autofill/core/browser/proto/strike_data.pb.h" +#include "components/autofill/core/browser/test_autofill_clock.h" +#include "components/autofill/core/common/autofill_clock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill { + +class StrikeDatabaseIntegratorTestStrikeDatabaseTest : public ::testing::Test { + public: + StrikeDatabaseIntegratorTestStrikeDatabaseTest() + : strike_database_(new StrikeDatabase(InitFilePath())) {} + + protected: + base::HistogramTester* GetHistogramTester() { return &histogram_tester_; } + base::test::ScopedTaskEnvironment scoped_task_environment_; + StrikeDatabaseIntegratorTestStrikeDatabase strike_database_; + + private: + static const base::FilePath InitFilePath() { + base::ScopedTempDir temp_dir_; + EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); + const base::FilePath file_path = + temp_dir_.GetPath().AppendASCII("StrikeDatabaseTest"); + return file_path; + } + + base::HistogramTester histogram_tester_; +}; + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + MaxStrikesLimitReachedTest) { + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); + // 3 strikes added. + strike_database_.AddStrikes(3); + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached()); + // 4 strike added, total strike count is 7. + strike_database_.AddStrikes(4); + EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + StrikeDatabaseIntegratorTestNthStrikeAddedHistogram) { + // 2 strikes logged. + strike_database_.AddStrikes(2); + strike_database_.RemoveStrikes(2); + // 1 strike logged. + strike_database_.AddStrike(); + // 2 strikes logged. + strike_database_.AddStrike(); + std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( + "Autofill.StrikeDatabase.NthStrikeAdded.StrikeDatabaseIntegratorTest"); + // There should be two buckets, for strike counts of 1 and 2. + ASSERT_EQ(2U, buckets.size()); + // Bucket for 1 strike should have count of 1. + EXPECT_EQ(1, buckets[0].count); + // Bucket for 2 strikes should have count of 2. + EXPECT_EQ(2, buckets[1].count); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + AddStrikeForZeroAndNonZeroStrikesTest) { + EXPECT_EQ(0, strike_database_.GetStrikes()); + strike_database_.AddStrike(); + EXPECT_EQ(1, strike_database_.GetStrikes()); + strike_database_.AddStrikes(2); + EXPECT_EQ(3, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForNonZeroStrikesTest) { + strike_database_.AddStrikes(3); + EXPECT_EQ(3, strike_database_.GetStrikes()); + strike_database_.ClearStrikes(); + EXPECT_EQ(0, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForZeroStrikesTest) { + strike_database_.ClearStrikes(); + EXPECT_EQ(0, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesTest) { + autofill::TestAutofillClock test_clock; + test_clock.SetNow(AutofillClock::Now()); + strike_database_.AddStrikes(2); + EXPECT_EQ(2, strike_database_.GetStrikes()); + + // Advance clock to past expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + // One strike should be removed. + strike_database_.RemoveExpiredStrikes(); + EXPECT_EQ(1, strike_database_.GetStrikes()); + + // Strike count is past the max limit. + strike_database_.AddStrikes(10); + EXPECT_EQ(11, strike_database_.GetStrikes()); + + // Advance clock to past expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + // Strike count should be one less than the max limit. + strike_database_.RemoveExpiredStrikes(); + EXPECT_EQ(5, strike_database_.GetStrikes()); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesTestLogsUMA) { + autofill::TestAutofillClock test_clock; + test_clock.SetNow(AutofillClock::Now()); + strike_database_.AddStrikes(2); + EXPECT_EQ(2, strike_database_.GetStrikes()); + + // Advance clock to past expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + // One strike should be removed. + strike_database_.RemoveExpiredStrikes(); + EXPECT_EQ(1, strike_database_.GetStrikes()); + + // Strike count is past the max limit. + strike_database_.AddStrikes(10); + EXPECT_EQ(11, strike_database_.GetStrikes()); + + // Advance clock to past expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + // Strike count should be one less than the max limit. + strike_database_.RemoveExpiredStrikes(); + EXPECT_EQ(5, strike_database_.GetStrikes()); + + std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( + "Autofill.StrikeDatabase.StrikesPresentWhenStrikeExpired." + "StrikeDatabaseIntegratorTest"); + // There should be two buckets, for strike counts of 2 and 11. + ASSERT_EQ(2U, buckets.size()); + // Bucket for 2 strikes should have count of 1. + GetHistogramTester()->ExpectBucketCount( + "Autofill.StrikeDatabase.StrikesPresentWhenStrikeExpired." + "StrikeDatabaseIntegratorTest", + 2, 1); + // Bucket for 11 strikes should have count of 1. + GetHistogramTester()->ExpectBucketCount( + "Autofill.StrikeDatabase.StrikesPresentWhenStrikeExpired." + "StrikeDatabaseIntegratorTest", + 11, 1); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + GetKeyForStrikeDatabaseIntegratorUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + EXPECT_EQ("StrikeDatabaseIntegratorTest__1234", + strike_database_.GetKey(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + MaxStrikesLimitReachedUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(unique_id)); + // 1 strike added for |unique_id|. + strike_database_.AddStrike(unique_id); + EXPECT_EQ(false, strike_database_.IsMaxStrikesLimitReached(unique_id)); + // 6 strikes added for |unique_id|. + strike_database_.AddStrikes(6, unique_id); + EXPECT_EQ(true, strike_database_.IsMaxStrikesLimitReached(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + StrikeDatabaseIntegratorUniqueIdTestNthStrikeAddedHistogram) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id_1 = "1234"; + const std::string unique_id_2 = "9876"; + // 1st strike added for |unique_id_1|. + strike_database_.AddStrike(unique_id_1); + // 2nd strike added for |unique_id_1|. + strike_database_.AddStrike(unique_id_1); + // 1st strike added for |unique_id_2|. + strike_database_.AddStrike(unique_id_2); + std::vector<base::Bucket> buckets = GetHistogramTester()->GetAllSamples( + "Autofill.StrikeDatabase.NthStrikeAdded." + "StrikeDatabaseIntegratorTest"); + // There should be two buckets, one for 1st strike, one for 2nd strike count. + ASSERT_EQ(2U, buckets.size()); + // Both |unique_id_1| and |unique_id_2| have 1st strikes recorded. + EXPECT_EQ(2, buckets[0].count); + // Only |unique_id_1| has 2nd strike recorded. + EXPECT_EQ(1, buckets[1].count); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + StrikeDatabaseIntegratorUniqueIdTestClearAllStrikes) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id_1 = "1234"; + const std::string unique_id_2 = "9876"; + // 1 strike added for |unique_id_1|. + strike_database_.AddStrike(unique_id_1); + // 3 strikes added for |unique_id_2|. + strike_database_.AddStrikes(3, unique_id_2); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id_1)); + EXPECT_EQ(3, strike_database_.GetStrikes(unique_id_2)); + strike_database_.ClearAllStrikes(); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_1)); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_2)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + AddStrikeForZeroAndNonZeroStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id)); + strike_database_.AddStrike(unique_id); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id)); + strike_database_.AddStrike(unique_id); + EXPECT_EQ(2, strike_database_.GetStrikes(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForNonZeroStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + strike_database_.AddStrike(unique_id); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id)); + strike_database_.ClearStrikes(unique_id); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + ClearStrikesForZeroStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + const std::string unique_id = "1234"; + strike_database_.ClearStrikes(unique_id); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id)); +} + +TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, + RemoveExpiredStrikesUniqueIdTest) { + strike_database_.SetUniqueIdsRequired(true); + autofill::TestAutofillClock test_clock; + test_clock.SetNow(AutofillClock::Now()); + const std::string unique_id_1 = "1234"; + const std::string unique_id_2 = "9876"; + strike_database_.AddStrike(unique_id_1); + + // Advance clock to past the entry for |unique_id_1|'s expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + strike_database_.AddStrike(unique_id_2); + strike_database_.RemoveExpiredStrikes(); + + // |unique_id_1|'s entry should have its most recent strike expire, but + // |unique_id_2|'s should not. + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_1)); + EXPECT_EQ(1, strike_database_.GetStrikes(unique_id_2)); + + // Advance clock to past |unique_id_2|'s expiry time. + test_clock.Advance(base::TimeDelta::FromMicroseconds( + strike_database_.GetExpiryTimeMicros() + 1)); + + strike_database_.RemoveExpiredStrikes(); + + // |unique_id_1| and |unique_id_2| should have no more unexpired strikes. + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_1)); + EXPECT_EQ(0, strike_database_.GetStrikes(unique_id_2)); +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/strike_database_unittest.cc b/chromium/components/autofill/core/browser/strike_database_unittest.cc index 57075bb0bac..88a5edeed45 100644 --- a/chromium/components/autofill/core/browser/strike_database_unittest.cc +++ b/chromium/components/autofill/core/browser/strike_database_unittest.cc @@ -7,6 +7,7 @@ #include <utility> #include <vector> +#include "base/bind.h" #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" diff --git a/chromium/components/autofill/core/browser/suggestion.cc b/chromium/components/autofill/core/browser/suggestion.cc index c98e0cab5ec..9182bd12337 100644 --- a/chromium/components/autofill/core/browser/suggestion.cc +++ b/chromium/components/autofill/core/browser/suggestion.cc @@ -35,7 +35,7 @@ Suggestion::Suggestion(const std::string& v, : frontend_id(fid), value(base::UTF8ToUTF16(v)), label(base::UTF8ToUTF16(l)), - icon(base::UTF8ToUTF16(i)), + icon(i), match(PREFIX_MATCH), is_value_secondary(false) {} diff --git a/chromium/components/autofill/core/browser/suggestion.h b/chromium/components/autofill/core/browser/suggestion.h index bef99f87e62..0df9efe674b 100644 --- a/chromium/components/autofill/core/browser/suggestion.h +++ b/chromium/components/autofill/core/browser/suggestion.h @@ -53,7 +53,7 @@ struct Suggestion { // Contains an image to display for the suggestion. gfx::Image custom_icon; // If |custom_icon| is empty, the name of the fallback built-in icon. - base::string16 icon; + std::string icon; MatchMode match; bool is_value_secondary; // |value| should be displayed as secondary text. }; diff --git a/chromium/components/autofill/core/browser/suggestion_selection.cc b/chromium/components/autofill/core/browser/suggestion_selection.cc index 354c174d5b0..0a8d6c04a10 100644 --- a/chromium/components/autofill/core/browser/suggestion_selection.cc +++ b/chromium/components/autofill/core/browser/suggestion_selection.cc @@ -69,6 +69,10 @@ std::vector<Suggestion> GetPrefixMatchedSuggestions( matched_profiles->size() < kMaxSuggestedProfilesCount; i++) { AutofillProfile* profile = profiles[i]; + + if (profile->ShouldSkipFillingOrSuggesting(type.GetStorableType())) + continue; + base::string16 value = GetInfoInOneLine(profile, type, comparator.app_locale()); if (value.empty()) @@ -100,7 +104,7 @@ std::vector<Suggestion> GetPrefixMatchedSuggestions( } std::vector<Suggestion> GetUniqueSuggestions( - const std::vector<ServerFieldType>& other_field_types, + const std::vector<ServerFieldType>& field_types, const std::string app_locale, const std::vector<AutofillProfile*> matched_profiles, const std::vector<Suggestion>& suggestions, @@ -109,7 +113,7 @@ std::vector<Suggestion> GetUniqueSuggestions( // Limit number of unique profiles as having too many makes the browser hang // due to drawing calculations (and is also not very useful for the user). - ServerFieldTypeSet types(other_field_types.begin(), other_field_types.end()); + ServerFieldTypeSet types(field_types.begin(), field_types.end()); for (size_t i = 0; i < matched_profiles.size() && unique_suggestions.size() < kMaxUniqueSuggestionsCount; ++i) { diff --git a/chromium/components/autofill/core/browser/suggestion_selection.h b/chromium/components/autofill/core/browser/suggestion_selection.h index 09c64924182..0e6909e4c51 100644 --- a/chromium/components/autofill/core/browser/suggestion_selection.h +++ b/chromium/components/autofill/core/browser/suggestion_selection.h @@ -34,8 +34,10 @@ std::vector<Suggestion> GetPrefixMatchedSuggestions( // Dedupes given suggestions based on if one is a subset of the other. // Returns unique_suggestions, and adds the corresponding profiles to // |unique_matched_profiles|. At most |kMaxUniqueSuggestionsCount| are returned. +// |field_types| stores all of the form's ServerFieldTypes, including that of +// the field on which the user is currently focused. std::vector<Suggestion> GetUniqueSuggestions( - const std::vector<ServerFieldType>& other_field_types, + const std::vector<ServerFieldType>& field_types, const std::string app_locale, const std::vector<AutofillProfile*> matched_profiles, const std::vector<Suggestion>& suggestions, diff --git a/chromium/components/autofill/core/browser/suggestion_selection_unittest.cc b/chromium/components/autofill/core/browser/suggestion_selection_unittest.cc index 5ee5174898e..cb36a7d90d5 100644 --- a/chromium/components/autofill/core/browser/suggestion_selection_unittest.cc +++ b/chromium/components/autofill/core/browser/suggestion_selection_unittest.cc @@ -11,10 +11,12 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_profile_comparator.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/common/autofill_clock.h" +#include "components/autofill/core/common/autofill_features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,8 +31,40 @@ using testing::ResultOf; namespace { const std::string TEST_APP_LOCALE = "en-US"; + +template <typename T> +bool CompareElements(T* a, T* b) { + return a->Compare(*b) < 0; +} + +template <typename T> +bool ElementsEqual(T* a, T* b) { + return a->Compare(*b) == 0; } +// Verifies that two vectors have the same elements (according to T::Compare) +// while ignoring order. This is useful because multiple profiles or credit +// cards that are added to the SQLite DB within the same second will be returned +// in GUID (aka random) order. +template <typename T> +void ExpectSameElements(const std::vector<T*>& expectations, + const std::vector<T*>& results) { + ASSERT_EQ(expectations.size(), results.size()); + + std::vector<T*> expectations_copy = expectations; + std::sort(expectations_copy.begin(), expectations_copy.end(), + CompareElements<T>); + std::vector<T*> results_copy = results; + std::sort(results_copy.begin(), results_copy.end(), CompareElements<T>); + + EXPECT_EQ(std::mismatch(results_copy.begin(), results_copy.end(), + expectations_copy.begin(), ElementsEqual<T>) + .first, + results_copy.end()); +} + +} // anonymous namespace + class SuggestionSelectionTest : public testing::Test { public: SuggestionSelectionTest() @@ -150,6 +184,52 @@ TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_LimitProfiles) { Not(base::ASCIIToUTF16("Marie"))))); } +TEST_F(SuggestionSelectionTest, GetPrefixMatchedSuggestions_SkipInvalid) { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillProfileServerValidation, + features::kAutofillProfileClientValidation}, + /*disabled_features=*/{}); + + const std::unique_ptr<AutofillProfile> profile_server_invalid = + CreateProfileUniquePtr("Marion"); + const std::unique_ptr<AutofillProfile> profile_client_invalid = + CreateProfileUniquePtr("Bob"); + const std::unique_ptr<AutofillProfile> profile_valid = + CreateProfileUniquePtr("Rose"); + const std::unique_ptr<AutofillProfile> profile_client_invalid_country_empty = + CreateProfileUniquePtr("Lost"); + + profile_server_invalid->SetValidityState( + ADDRESS_HOME_STATE, AutofillProfile::INVALID, AutofillProfile::SERVER); + profile_client_invalid->SetValidityState( + ADDRESS_HOME_STATE, AutofillProfile::INVALID, AutofillProfile::CLIENT); + profile_client_invalid_country_empty->SetValidityState( + ADDRESS_HOME_STATE, AutofillProfile::INVALID, AutofillProfile::CLIENT); + profile_client_invalid_country_empty->SetRawInfo(ADDRESS_HOME_COUNTRY, + base::ASCIIToUTF16("")); + + const std::vector<AutofillProfile*> profiles_data = { + profile_server_invalid.get(), profile_client_invalid.get(), + profile_valid.get(), profile_client_invalid_country_empty.get()}; + + std::vector<AutofillProfile*> matched_profiles; + auto suggestions = GetPrefixMatchedSuggestions( + AutofillType(ADDRESS_HOME_STATE), GetCanonicalUtf16Content("C"), + comparator_, profiles_data, &matched_profiles); + + ASSERT_EQ(2U, suggestions.size()); + ASSERT_EQ(2U, matched_profiles.size()); + EXPECT_THAT(suggestions, + ElementsAre(Field(&Suggestion::value, base::ASCIIToUTF16("CA")), + Field(&Suggestion::value, base::ASCIIToUTF16("CA")))); + + std::vector<AutofillProfile*> expected_result; + expected_result.push_back(profile_valid.get()); + expected_result.push_back(profile_client_invalid_country_empty.get()); + ExpectSameElements(matched_profiles, expected_result); +} + TEST_F(SuggestionSelectionTest, GetUniqueSuggestions_SingleDedupe) { // Give two suggestions with the same name, and no other field to compare. // Expect only one unique suggestion. diff --git a/chromium/components/autofill/core/browser/suggestion_test_helpers.h b/chromium/components/autofill/core/browser/suggestion_test_helpers.h index a5262c052fd..60084bc45a3 100644 --- a/chromium/components/autofill/core/browser/suggestion_test_helpers.h +++ b/chromium/components/autofill/core/browser/suggestion_test_helpers.h @@ -5,6 +5,8 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_SUGGESTION_TEST_HELPERS_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_SUGGESTION_TEST_HELPERS_H_ +#include <string> + #include "components/autofill/core/browser/suggestion.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -85,8 +87,8 @@ template <class EltsAreMatcher> inline testing::Matcher<const std::vector<Suggestion>&> SuggestionVectorIconsAre(const EltsAreMatcher& elts_are_matcher) { return testing::MakeMatcher( - new SuggestionVectorMembersAreMatcher<base::string16>(elts_are_matcher, - &Suggestion::icon)); + new SuggestionVectorMembersAreMatcher<std::string>(elts_are_matcher, + &Suggestion::icon)); } } // namespace autofill diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc index b26056019a3..dadbbd1dfed 100644 --- a/chromium/components/autofill/core/browser/test_autofill_client.cc +++ b/chromium/components/autofill/core/browser/test_autofill_client.cc @@ -6,6 +6,7 @@ #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/local_card_migration_manager.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" @@ -121,10 +122,10 @@ void TestAutofillClient::ConfirmSaveAutofillProfile( void TestAutofillClient::ConfirmSaveCreditCardLocally( const CreditCard& card, - bool show_prompt, + SaveCreditCardOptions options, LocalSaveCardPromptCallback callback) { confirm_save_credit_card_locally_called_ = true; - offer_to_save_credit_card_bubble_was_shown_ = show_prompt; + offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt; std::move(callback).Run(AutofillClient::ACCEPTED); } @@ -134,16 +135,24 @@ void TestAutofillClient::ConfirmAccountNameFixFlow( credit_card_name_fix_flow_bubble_was_shown_ = true; std::move(callback).Run(base::string16(base::ASCIIToUTF16("Gaia Name"))); } + +void TestAutofillClient::ConfirmExpirationDateFixFlow( + const CreditCard& card, + base::OnceCallback<void(const base::string16&, const base::string16&)> + callback) { + credit_card_name_fix_flow_bubble_was_shown_ = true; + std::move(callback).Run( + base::string16(base::ASCIIToUTF16("03")), + base::string16(base::ASCIIToUTF16(test::NextYear().c_str()))); +} #endif // defined(OS_ANDROID) void TestAutofillClient::ConfirmSaveCreditCardToCloud( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, - bool should_request_name_from_user, - bool should_request_expiration_date_from_user, - bool show_prompt, + SaveCreditCardOptions options, UploadSaveCardPromptCallback callback) { - offer_to_save_credit_card_bubble_was_shown_ = show_prompt; + offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt; std::move(callback).Run(AutofillClient::ACCEPTED, {}); } diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h index c2237b15534..71baad73db0 100644 --- a/chromium/components/autofill/core/browser/test_autofill_client.h +++ b/chromium/components/autofill/core/browser/test_autofill_client.h @@ -69,18 +69,20 @@ class TestAutofillClient : public AutofillClient { base::OnceClosure callback) override; void ConfirmSaveCreditCardLocally( const CreditCard& card, - bool show_prompt, + SaveCreditCardOptions options, LocalSaveCardPromptCallback callback) override; #if defined(OS_ANDROID) void ConfirmAccountNameFixFlow( base::OnceCallback<void(const base::string16&)> callback) override; + void ConfirmExpirationDateFixFlow( + const CreditCard& card, + base::OnceCallback<void(const base::string16&, const base::string16&)> + callback) override; #endif // defined(OS_ANDROID) void ConfirmSaveCreditCardToCloud( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, - bool should_request_name_from_user, - bool should_request_expiration_date_from_user, - bool show_prompt, + SaveCreditCardOptions options, UploadSaveCardPromptCallback callback) override; void ConfirmCreditCardFillAssist(const CreditCard& card, base::OnceClosure callback) override; diff --git a/chromium/components/autofill/core/browser/test_autofill_profile_validator.cc b/chromium/components/autofill/core/browser/test_autofill_profile_validator.cc index d3eba5d0ee7..8828311186a 100644 --- a/chromium/components/autofill/core/browser/test_autofill_profile_validator.cc +++ b/chromium/components/autofill/core/browser/test_autofill_profile_validator.cc @@ -49,8 +49,18 @@ AutofillProfileValidator* TestAutofillProfileValidator::GetInstance() { return &(instance.Get().autofill_profile_validator_); } +// static +TestAutofillProfileValidatorDelayed* +TestAutofillProfileValidator::GetDelayedInstance() { + static base::LazyInstance<TestAutofillProfileValidator>::DestructorAtExit + instance = LAZY_INSTANCE_INITIALIZER; + return &(instance.Get().autofill_profile_validator_delayed_); +} + TestAutofillProfileValidator::TestAutofillProfileValidator() - : autofill_profile_validator_(GetInputSource(), GetInputStorage()) {} + : autofill_profile_validator_(GetInputSource(), GetInputStorage()), + autofill_profile_validator_delayed_(GetInputSource(), GetInputStorage()) { +} TestAutofillProfileValidator::~TestAutofillProfileValidator() {} diff --git a/chromium/components/autofill/core/browser/test_autofill_profile_validator.h b/chromium/components/autofill/core/browser/test_autofill_profile_validator.h index 93b7eeee17f..6fa2fbb04a2 100644 --- a/chromium/components/autofill/core/browser/test_autofill_profile_validator.h +++ b/chromium/components/autofill/core/browser/test_autofill_profile_validator.h @@ -8,6 +8,7 @@ #include "base/lazy_instance.h" #include "base/macros.h" #include "components/autofill/core/browser/autofill_profile_validator.h" +#include "components/autofill/core/browser/test_autofill_profile_validator_delayed.h" namespace autofill { @@ -15,6 +16,7 @@ namespace autofill { class TestAutofillProfileValidator { public: static AutofillProfileValidator* GetInstance(); + static TestAutofillProfileValidatorDelayed* GetDelayedInstance(); private: friend struct base::LazyInstanceTraitsBase<TestAutofillProfileValidator>; @@ -22,8 +24,9 @@ class TestAutofillProfileValidator { TestAutofillProfileValidator(); ~TestAutofillProfileValidator(); - // The only instance that exists. + // The only instance that exists of normal and delayed validators. AutofillProfileValidator autofill_profile_validator_; + TestAutofillProfileValidatorDelayed autofill_profile_validator_delayed_; DISALLOW_COPY_AND_ASSIGN(TestAutofillProfileValidator); }; diff --git a/chromium/components/autofill/core/browser/test_autofill_profile_validator_delayed.cc b/chromium/components/autofill/core/browser/test_autofill_profile_validator_delayed.cc new file mode 100644 index 00000000000..ed92eae2fcf --- /dev/null +++ b/chromium/components/autofill/core/browser/test_autofill_profile_validator_delayed.cc @@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/test_autofill_profile_validator_delayed.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/cancelable_callback.h" +#include "base/threading/sequenced_task_runner_handle.h" + +namespace autofill { +namespace { + +const int kRulesDelayedLoadingTimeSeconds = 3; + +} // namespace + +TestAutofillProfileValidatorDelayed::TestAutofillProfileValidatorDelayed( + std::unique_ptr<::i18n::addressinput::Source> source, + std::unique_ptr<::i18n::addressinput::Storage> storage) + : AutofillProfileValidator(std::move(source), std::move(storage)) {} + +TestAutofillProfileValidatorDelayed::~TestAutofillProfileValidatorDelayed() {} + +void TestAutofillProfileValidatorDelayed::LoadRulesInstantly( + const std::string& region_code) { + address_validator_.LoadRules(region_code); +} + +void TestAutofillProfileValidatorDelayed::LoadRulesForRegion( + const std::string& region_code) { + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TestAutofillProfileValidatorDelayed::LoadRulesInstantly, + base::Unretained(this), region_code), + base::TimeDelta::FromSeconds(kRulesDelayedLoadingTimeSeconds)); +} +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/test_autofill_profile_validator_delayed.h b/chromium/components/autofill/core/browser/test_autofill_profile_validator_delayed.h new file mode 100644 index 00000000000..846c249ee79 --- /dev/null +++ b/chromium/components/autofill/core/browser/test_autofill_profile_validator_delayed.h @@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROFILE_VALIDATOR_DELAYED_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROFILE_VALIDATOR_DELAYED_H_ + +#include <memory> +#include <string> + +#include "components/autofill/core/browser/autofill_profile_validator.h" +#include "third_party/libaddressinput/chromium/chrome_address_validator.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h" + +namespace autofill { + +// Singleton that owns a single AutofillProfileValidator instance. It's a +// delayed validator used in tests, to make sure that the system can handle +// possible delays in the real world. +class TestAutofillProfileValidatorDelayed : public AutofillProfileValidator { + public: + // Takes ownership of |source| and |storage|. + TestAutofillProfileValidatorDelayed( + std::unique_ptr<::i18n::addressinput::Source> source, + std::unique_ptr<::i18n::addressinput::Storage> storage); + + ~TestAutofillProfileValidatorDelayed() override; + + // Starts loading the rules for the specified |region_code|. + void LoadRulesForRegion(const std::string& region_code) override; + + private: + void LoadRulesInstantly(const std::string& region_code); + + DISALLOW_COPY_AND_ASSIGN(TestAutofillProfileValidatorDelayed); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROFILE_VALIDATOR_DELAYED_H_ diff --git a/chromium/components/autofill/core/browser/test_autofill_provider.h b/chromium/components/autofill/core/browser/test_autofill_provider.h index 8c69b47e99e..ef533d89c24 100644 --- a/chromium/components/autofill/core/browser/test_autofill_provider.h +++ b/chromium/components/autofill/core/browser/test_autofill_provider.h @@ -11,7 +11,7 @@ namespace autofill { class TestAutofillProvider : public AutofillProvider { public: - ~TestAutofillProvider() override{}; + ~TestAutofillProvider() override {} // AutofillProvider: void OnQueryFormFieldAutofill(AutofillHandlerProxy* handler, 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 cc72aed5cf6..b9808476079 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 @@ -8,7 +8,6 @@ #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 { @@ -16,11 +15,12 @@ TestLocalCardMigrationManager::TestLocalCardMigrationManager( AutofillDriver* driver, AutofillClient* client, payments::TestPaymentsClient* payments_client, - PersonalDataManager* personal_data_manager) + TestPersonalDataManager* personal_data_manager) : LocalCardMigrationManager(client, payments_client, "en-US", - personal_data_manager) {} + personal_data_manager), + personal_data_manager_(personal_data_manager) {} TestLocalCardMigrationManager::~TestLocalCardMigrationManager() {} @@ -28,10 +28,19 @@ bool TestLocalCardMigrationManager::IsCreditCardMigrationEnabled() { bool migration_experiment_enabled = features::GetLocalCardMigrationExperimentalFlag() != features::LocalCardMigrationExperimentalFlag::kMigrationDisabled; + bool has_google_payments_account = (static_cast<int64_t>(payments_client_->GetPrefService()->GetDouble( prefs::kAutofillBillingCustomerNumber)) != 0); - return migration_experiment_enabled && has_google_payments_account; + + bool sync_feature_enabled = + (personal_data_manager_->GetSyncSigninState() == + AutofillSyncSigninState::kSignedInAndSyncFeature); + + return migration_experiment_enabled && has_google_payments_account && + (sync_feature_enabled || + base::FeatureList::IsEnabled( + features::kAutofillEnableLocalCardMigrationForNonSyncUser)); } bool TestLocalCardMigrationManager::LocalCardMigrationWasTriggered() { @@ -58,15 +67,22 @@ void TestLocalCardMigrationManager::OnUserAcceptedMainMigrationDialog( LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog(selected_cards); } +void TestLocalCardMigrationManager::ResetSyncState( + AutofillSyncSigninState sync_state) { + personal_data_manager_->SetSyncAndSignInState(sync_state); +} + void TestLocalCardMigrationManager::OnDidGetUploadDetails( bool is_from_settings_page, AutofillClient::PaymentsRpcResult result, const base::string16& context_token, - std::unique_ptr<base::Value> legal_message) { + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_bin_ranges) { if (result == AutofillClient::SUCCESS) { local_card_migration_was_triggered_ = true; LocalCardMigrationManager::OnDidGetUploadDetails( - is_from_settings_page, result, context_token, std::move(legal_message)); + is_from_settings_page, result, context_token, std::move(legal_message), + supported_bin_ranges); } } 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 97e4518eb15..722d366dd20 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 @@ -5,9 +5,14 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_MANAGER_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_MANAGER_H_ +#include <memory> #include <string> +#include <utility> +#include <vector> #include "components/autofill/core/browser/local_card_migration_manager.h" +#include "components/autofill/core/browser/sync_utils.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" namespace autofill { @@ -17,14 +22,13 @@ class TestPaymentsClient; class AutofillClient; class AutofillDriver; -class PersonalDataManager; class TestLocalCardMigrationManager : public LocalCardMigrationManager { public: TestLocalCardMigrationManager(AutofillDriver* driver, AutofillClient* client, payments::TestPaymentsClient* payments_client, - PersonalDataManager* personal_data_manager); + TestPersonalDataManager* personal_data_manager); ~TestLocalCardMigrationManager() override; // Override the base function. Checks the existnece of billing customer number @@ -50,12 +54,17 @@ class TestLocalCardMigrationManager : public LocalCardMigrationManager { void OnUserAcceptedMainMigrationDialog( const std::vector<std::string>& selected_cards) override; + // Mock the Chrome Sync state in the LocalCardMigrationManager. If not set, + // default to AutofillSyncSigninState::kSignedInAndSyncFeature. + void ResetSyncState(AutofillSyncSigninState sync_state); + private: void OnDidGetUploadDetails( bool is_from_settings_page, AutofillClient::PaymentsRpcResult result, const base::string16& context_token, - std::unique_ptr<base::Value> legal_message) override; + std::unique_ptr<base::Value> legal_message, + std::vector<std::pair<int, int>> supported_bin_ranges) override; bool local_card_migration_was_triggered_ = false; @@ -63,6 +72,8 @@ class TestLocalCardMigrationManager : public LocalCardMigrationManager { bool main_prompt_was_shown_ = false; + TestPersonalDataManager* personal_data_manager_; + DISALLOW_COPY_AND_ASSIGN(TestLocalCardMigrationManager); }; diff --git a/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc b/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc deleted file mode 100644 index cc212712538..00000000000 --- a/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.cc +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/core/browser/test_local_card_migration_strike_database.h" - -namespace autofill { - -TestLocalCardMigrationStrikeDatabase::TestLocalCardMigrationStrikeDatabase( - StrikeDatabase* strike_database) - : LocalCardMigrationStrikeDatabase(strike_database) {} - -} // namespace autofill diff --git a/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h b/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h deleted file mode 100644 index c1cac181ceb..00000000000 --- a/chromium/components/autofill/core/browser/test_local_card_migration_strike_database.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_ - -#include "components/autofill/core/browser/local_card_migration_strike_database.h" - -namespace autofill { - -class TestLocalCardMigrationStrikeDatabase - : public LocalCardMigrationStrikeDatabase { - public: - TestLocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database); -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_LOCAL_CARD_MIGRATION_STRIKE_DATABASE_H_ diff --git a/chromium/components/autofill/core/browser/test_personal_data_manager.cc b/chromium/components/autofill/core/browser/test_personal_data_manager.cc index 9a6e5c35765..209cf497334 100644 --- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc +++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc @@ -19,6 +19,10 @@ void TestPersonalDataManager::OnSyncServiceInitialized( sync_service_initialized_ = true; } +AutofillSyncSigninState TestPersonalDataManager::GetSyncSigninState() const { + return sync_and_signin_state_; +} + void TestPersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) { CreditCard* credit_card = GetCreditCardWithGUID(data_model.guid().c_str()); if (credit_card) @@ -248,7 +252,8 @@ bool TestPersonalDataManager::IsSyncFeatureEnabled() const { return sync_feature_enabled_; } -AccountInfo TestPersonalDataManager::GetAccountInfoForPaymentsServer() const { +CoreAccountInfo TestPersonalDataManager::GetAccountInfoForPaymentsServer() + const { return account_info_; } 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 ae3a7cdb449..8aedd182f36 100644 --- a/chromium/components/autofill/core/browser/test_personal_data_manager.h +++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h @@ -28,6 +28,7 @@ class TestPersonalDataManager : public PersonalDataManager { // for various tests, whether to skip calls to uncreated databases/services, // or to make things easier in general to toggle. void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + AutofillSyncSigninState GetSyncSigninState() const override; void RecordUseOf(const AutofillDataModel& data_model) override; std::string SaveImportedProfile( const AutofillProfile& imported_profile) override; @@ -55,7 +56,7 @@ class TestPersonalDataManager : public PersonalDataManager { CreditCard* GetCreditCardByNumber(const std::string& number) override; bool IsDataLoaded() const override; bool IsSyncFeatureEnabled() const override; - AccountInfo GetAccountInfoForPaymentsServer() const override; + CoreAccountInfo GetAccountInfoForPaymentsServer() const override; // Unique to TestPersonalDataManager: @@ -115,7 +116,11 @@ class TestPersonalDataManager : public PersonalDataManager { void SetSyncFeatureEnabled(bool enabled) { sync_feature_enabled_ = enabled; } - void SetAccountInfoForPayments(const AccountInfo& account_info) { + void SetSyncAndSignInState(AutofillSyncSigninState sync_and_signin_state) { + sync_and_signin_state_ = sync_and_signin_state; + } + + void SetAccountInfoForPayments(const CoreAccountInfo& account_info) { account_info_ = account_info; } @@ -129,8 +134,10 @@ class TestPersonalDataManager : public PersonalDataManager { base::Optional<bool> autofill_credit_card_enabled_; base::Optional<bool> autofill_wallet_import_enabled_; bool sync_feature_enabled_ = false; + AutofillSyncSigninState sync_and_signin_state_ = + AutofillSyncSigninState::kSignedInAndSyncFeature; bool sync_service_initialized_ = false; - AccountInfo account_info_; + CoreAccountInfo account_info_; DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager); }; diff --git a/chromium/components/autofill/core/browser/test_strike_database.cc b/chromium/components/autofill/core/browser/test_strike_database.cc index bb242f48306..4aee9cb4746 100644 --- a/chromium/components/autofill/core/browser/test_strike_database.cc +++ b/chromium/components/autofill/core/browser/test_strike_database.cc @@ -13,7 +13,7 @@ TestStrikeDatabase::TestStrikeDatabase() {} TestStrikeDatabase::~TestStrikeDatabase() {} void TestStrikeDatabase::GetProtoStrikes( - const std::string key, + const std::string& key, const StrikesCallback& outer_callback) { outer_callback.Run(GetStrikesForTesting(key)); } diff --git a/chromium/components/autofill/core/browser/test_strike_database.h b/chromium/components/autofill/core/browser/test_strike_database.h index ebe7731cb1f..d46be27bc4b 100644 --- a/chromium/components/autofill/core/browser/test_strike_database.h +++ b/chromium/components/autofill/core/browser/test_strike_database.h @@ -22,7 +22,7 @@ class TestStrikeDatabase : public StrikeDatabase { ~TestStrikeDatabase() override; // StrikeDatabase: - void GetProtoStrikes(const std::string key, + void GetProtoStrikes(const std::string& key, const StrikesCallback& outer_callback) override; void ClearAllProtoStrikes( const ClearStrikesCallback& outer_callback) override; diff --git a/chromium/components/autofill/core/browser/travel_field.cc b/chromium/components/autofill/core/browser/travel_field.cc new file mode 100644 index 00000000000..cee6b3491c7 --- /dev/null +++ b/chromium/components/autofill/core/browser/travel_field.cc @@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/travel_field.h" + +#include <memory> +#include <utility> + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/common/autofill_regex_constants.h" + +namespace autofill { + +TravelField::~TravelField() = default; + +// static +std::unique_ptr<FormField> TravelField::Parse(AutofillScanner* scanner) { + if (!scanner || scanner->IsEnd()) { + return nullptr; + } + + auto travel_field = std::make_unique<TravelField>(); + if (ParseField(scanner, base::UTF8ToUTF16(kPassportRe), + &travel_field->passport_) || + ParseField(scanner, base::UTF8ToUTF16(kTravelOriginRe), + &travel_field->origin_) || + ParseField(scanner, base::UTF8ToUTF16(kTravelDestinationRe), + &travel_field->destination_) || + ParseField(scanner, base::UTF8ToUTF16(kFlightRe), + &travel_field->flight_)) { + // If any regex matches, then we found a travel field. + return std::move(travel_field); + } + + return nullptr; +} + +void TravelField::AddClassifications( + FieldCandidatesMap* field_candidates) const { + // Simply tag all the fields as unknown types. Travel is currently used as + // filter. + AddClassification(passport_, UNKNOWN_TYPE, kBaseTravelParserScore, + field_candidates); + AddClassification(origin_, UNKNOWN_TYPE, kBaseTravelParserScore, + field_candidates); + AddClassification(destination_, UNKNOWN_TYPE, kBaseTravelParserScore, + field_candidates); + AddClassification(flight_, UNKNOWN_TYPE, kBaseTravelParserScore, + field_candidates); +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/travel_field.h b/chromium/components/autofill/core/browser/travel_field.h new file mode 100644 index 00000000000..0608d26c450 --- /dev/null +++ b/chromium/components/autofill/core/browser/travel_field.h @@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TRAVEL_FIELD_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_TRAVEL_FIELD_H_ + +#include <memory> + +#include "components/autofill/core/browser/autofill_scanner.h" +#include "components/autofill/core/browser/form_field.h" + +namespace autofill { + +class TravelField : public FormField { + public: + ~TravelField() override; + + static std::unique_ptr<FormField> Parse(AutofillScanner* scanner); + + protected: + void AddClassifications(FieldCandidatesMap* field_candidates) const override; + + private: + // All of the following fields are optional. + AutofillField* passport_; + AutofillField* origin_; + AutofillField* destination_; + AutofillField* flight_; +}; +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TRAVEL_FIELD_H_ diff --git a/chromium/components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.cc b/chromium/components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.cc new file mode 100644 index 00000000000..812c157cc11 --- /dev/null +++ b/chromium/components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.cc @@ -0,0 +1,77 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.h" + +#include <utility> + +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/grit/components_scaled_resources.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill { + +CardExpirationDateFixFlowViewDelegateMobile:: + CardExpirationDateFixFlowViewDelegateMobile( + const CreditCard& card, + base::OnceCallback<void(const base::string16&, const base::string16&)> + upload_save_card_callback) + : upload_save_card_callback_(std::move(upload_save_card_callback)), + shown_(false), + had_user_interaction_(false), + card_label_(card.NetworkAndLastFourDigits()) { + DCHECK(!upload_save_card_callback_.is_null()); +} + +CardExpirationDateFixFlowViewDelegateMobile:: + ~CardExpirationDateFixFlowViewDelegateMobile() { + if (shown_ && !had_user_interaction_) + AutofillMetrics::LogExpirationDateFixFlowPromptEvent( + AutofillMetrics::ExpirationDateFixFlowPromptEvent:: + EXPIRATION_DATE_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION); +} + +int CardExpirationDateFixFlowViewDelegateMobile::GetIconId() const { + return IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER; +} + +base::string16 CardExpirationDateFixFlowViewDelegateMobile::GetTitleText() + const { + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_CARD_UPDATE_EXPIRATION_DATE_TITLE); +} + +base::string16 CardExpirationDateFixFlowViewDelegateMobile::GetSaveButtonLabel() + const { + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_FIX_FLOW_PROMPT_SAVE_CARD_LABEL); +} + +void CardExpirationDateFixFlowViewDelegateMobile::Accept( + const base::string16& month, + const base::string16& year) { + std::move(upload_save_card_callback_).Run(month, year); + AutofillMetrics::LogExpirationDateFixFlowPromptEvent( + AutofillMetrics::ExpirationDateFixFlowPromptEvent:: + EXPIRATION_DATE_FIX_FLOW_PROMPT_ACCEPTED); + had_user_interaction_ = true; +} + +void CardExpirationDateFixFlowViewDelegateMobile::Dismissed() { + AutofillMetrics::LogExpirationDateFixFlowPromptEvent( + AutofillMetrics::ExpirationDateFixFlowPromptEvent:: + EXPIRATION_DATE_FIX_FLOW_PROMPT_DISMISSED); + had_user_interaction_ = true; +} + +void CardExpirationDateFixFlowViewDelegateMobile::Shown() { + AutofillMetrics::LogExpirationDateFixFlowPromptShown(); + shown_ = true; +} + +} // namespace autofill diff --git a/chromium/components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.h b/chromium/components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.h new file mode 100644 index 00000000000..d749b79ad1f --- /dev/null +++ b/chromium/components/autofill/core/browser/ui/card_expiration_date_fix_flow_view_delegate_mobile.h @@ -0,0 +1,60 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_CARD_EXPIRATION_DATE_FIX_FLOW_VIEW_DELEGATE_MOBILE_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_CARD_EXPIRATION_DATE_FIX_FLOW_VIEW_DELEGATE_MOBILE_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/strings/string16.h" +#include "components/autofill/core/browser/autofill_metrics.h" +#include "components/autofill/core/browser/credit_card.h" + +namespace autofill { + +// Enables the user to accept or deny expiration date fix flow prompt. +// Only used on mobile. This class is responsible for its destruction. +// Destruction is achieved by calling delete when the prompt is +// dismissed. +class CardExpirationDateFixFlowViewDelegateMobile { + public: + CardExpirationDateFixFlowViewDelegateMobile( + const CreditCard& card, + base::OnceCallback<void(const base::string16&, const base::string16&)> + upload_save_card_callback); + + ~CardExpirationDateFixFlowViewDelegateMobile(); + + const base::string16& card_label() const { return card_label_; } + + int GetIconId() const; + base::string16 GetTitleText() const; + base::string16 GetSaveButtonLabel() const; + void Accept(const base::string16& month, const base::string16& year); + void Dismissed(); + void Shown(); + + private: + // The callback to save the credit card to Google Payments once user accepts + // fix flow. + base::OnceCallback<void(const base::string16&, const base::string16&)> + upload_save_card_callback_; + + // Whether the prompt was shown to the user. + bool shown_; + + // Did the user ever explicitly accept or dismiss this prompt? + bool had_user_interaction_; + + // Label of the card describing the network and the last four digits. + base::string16 card_label_; + + DISALLOW_COPY_AND_ASSIGN(CardExpirationDateFixFlowViewDelegateMobile); +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_CARD_EXPIRATION_DATE_FIX_FLOW_VIEW_DELEGATE_MOBILE_H_ diff --git a/chromium/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc b/chromium/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc index 61ef3737f53..c5d3b1f8980 100644 --- a/chromium/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc +++ b/chromium/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc @@ -49,7 +49,8 @@ base::string16 CardNameFixFlowViewDelegateMobile::GetInferredCardHolderName() } base::string16 CardNameFixFlowViewDelegateMobile::GetSaveButtonLabel() const { - return l10n_util::GetStringUTF16(IDS_AUTOFILL_NAME_FIX_FLOW_PROMPT_SAVE_CARD); + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_FIX_FLOW_PROMPT_SAVE_CARD_LABEL); } void CardNameFixFlowViewDelegateMobile::Accept(const base::string16& name) { 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 529554614e0..9012160a9b2 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 @@ -500,12 +500,12 @@ TEST_P(CvcInputValidationTest, CvcInputValidation) { delegate_->response().cvc); } -INSTANTIATE_TEST_CASE_P(CardUnmaskPromptControllerImplTest, - CvcInputValidationTest, - testing::Values(CvcCase{"123", true, "123"}, - CvcCase{"123 ", true, "123"}, - CvcCase{" 1234 ", false}, - CvcCase{"IOU", false})); +INSTANTIATE_TEST_SUITE_P(CardUnmaskPromptControllerImplTest, + CvcInputValidationTest, + testing::Values(CvcCase{"123", true, "123"}, + CvcCase{"123 ", true, "123"}, + CvcCase{" 1234 ", false}, + CvcCase{"IOU", false})); class CvcInputAmexValidationTest : public CardUnmaskPromptControllerImplGenericTest, @@ -541,14 +541,14 @@ TEST_P(CvcInputAmexValidationTest, CvcInputValidation) { delegate_->response().cvc); } -INSTANTIATE_TEST_CASE_P(CardUnmaskPromptControllerImplTest, - CvcInputAmexValidationTest, - testing::Values(CvcCase{"123", false}, - CvcCase{"123 ", false}, - CvcCase{"1234", true, "1234"}, - CvcCase{"\t1234 ", true, "1234"}, - CvcCase{" 1234", true, "1234"}, - CvcCase{"IOU$", false})); +INSTANTIATE_TEST_SUITE_P(CardUnmaskPromptControllerImplTest, + CvcInputAmexValidationTest, + testing::Values(CvcCase{"123", false}, + CvcCase{"123 ", false}, + CvcCase{"1234", true, "1234"}, + CvcCase{"\t1234 ", true, "1234"}, + CvcCase{" 1234", true, "1234"}, + CvcCase{"IOU$", false})); struct ExpirationDateTestCase { const char* input_month; @@ -584,7 +584,7 @@ TEST_P(ExpirationDateValidationTest, ExpirationDateValidation) { ASCIIToUTF16(exp_case.input_year))); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CardUnmaskPromptControllerImplTest, ExpirationDateValidationTest, testing::Values(ExpirationDateTestCase{"01", "2040", true}, diff --git a/chromium/components/autofill/core/browser/validation.cc b/chromium/components/autofill/core/browser/validation.cc index bce4371b0de..3b4bf965681 100644 --- a/chromium/components/autofill/core/browser/validation.cc +++ b/chromium/components/autofill/core/browser/validation.cc @@ -51,7 +51,7 @@ bool IsValidCreditCardExpirationYear(int year, const base::Time& now) { } bool IsValidCreditCardNumber(const base::string16& text) { - base::string16 number = CreditCard::StripSeparators(text); + const base::string16 number = CreditCard::StripSeparators(text); if (!HasCorrectLength(number)) return false; @@ -92,12 +92,13 @@ bool HasCorrectLength(const base::string16& number) { return true; } -bool PassesLuhnCheck(base::string16& number) { +// TODO (crbug.com/927767): Add unit tests for this function. +bool PassesLuhnCheck(const base::string16& number) { // Use the Luhn formula [3] to validate the number. // [3] http://en.wikipedia.org/wiki/Luhn_algorithm int sum = 0; bool odd = false; - for (base::string16::reverse_iterator iter = number.rbegin(); + for (base::string16::const_reverse_iterator iter = number.rbegin(); iter != number.rend(); ++iter) { if (!base::IsAsciiDigit(*iter)) return false; diff --git a/chromium/components/autofill/core/browser/validation.h b/chromium/components/autofill/core/browser/validation.h index 5c7dccf1a65..470d07556a0 100644 --- a/chromium/components/autofill/core/browser/validation.h +++ b/chromium/components/autofill/core/browser/validation.h @@ -52,7 +52,7 @@ bool IsValidCreditCardNumber(const base::string16& text); bool HasCorrectLength(const base::string16& number); // Returns true if |number| passes the validation by Luhn formula. -bool PassesLuhnCheck(base::string16& number); +bool PassesLuhnCheck(const base::string16& number); // Returns true if |code| looks like a valid credit card security code // for the given credit card type. diff --git a/chromium/components/autofill/core/browser/validation_unittest.cc b/chromium/components/autofill/core/browser/validation_unittest.cc index b9a9808d306..2604226c1a6 100644 --- a/chromium/components/autofill/core/browser/validation_unittest.cc +++ b/chromium/components/autofill/core/browser/validation_unittest.cc @@ -188,7 +188,7 @@ TEST_P(AutofillTypeValidationTest, IsValidForType) { } } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardExpDate, AutofillTypeValidationTest, testing::Values( @@ -231,7 +231,7 @@ INSTANTIATE_TEST_CASE_P( false, IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardMonth, AutofillTypeValidationTest, testing::Values( @@ -254,7 +254,7 @@ INSTANTIATE_TEST_CASE_P( false, IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH))); -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardYear, AutofillTypeValidationTest, testing::Values( @@ -351,7 +351,7 @@ const static std::set<std::string> kAllBasicCardNetworks{ "amex", "discover", "diners", "elo", "jcb", "mastercard", "mir", "unionpay", "visa"}; -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardNumber, AutofillCCNumberValidationTest, testing::Values( @@ -433,7 +433,7 @@ TEST_P(AutofillGetCvcLengthForCardType, GetCvcLengthForCardType) { GetCvcLengthForCardType(GetParam().card_type)); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( CreditCardCvcLength, AutofillGetCvcLengthForCardType, testing::Values( @@ -465,33 +465,33 @@ TEST_P(AutofillIsUPIVirtualPaymentAddress, IsUPIVirtualPaymentAddress) { IsUPIVirtualPaymentAddress(ASCIIToUTF16("user@" + GetParam() + ".com"))); } -INSTANTIATE_TEST_CASE_P(UPIVirtualPaymentAddress, - AutofillIsUPIVirtualPaymentAddress, - testing::Values("upi", - "allbank", - "andb", - "axisbank", - "barodampay", - "mahb", - "cnrb", - "csbpay", - "dcb", - "federal", - "hdfcbank", - "pockets", - "icici", - "idfcbank", - "indus", - "kbl", - "kaypay", - "pnb", - "sib", - "sbi", - "tjsb", - "uco", - "unionbank", - "united", - "vijb", - "ybl")); +INSTANTIATE_TEST_SUITE_P(UPIVirtualPaymentAddress, + AutofillIsUPIVirtualPaymentAddress, + testing::Values("upi", + "allbank", + "andb", + "axisbank", + "barodampay", + "mahb", + "cnrb", + "csbpay", + "dcb", + "federal", + "hdfcbank", + "pockets", + "icici", + "idfcbank", + "indus", + "kbl", + "kaypay", + "pnb", + "sib", + "sbi", + "tjsb", + "uco", + "unionbank", + "united", + "vijb", + "ybl")); } // namespace autofill diff --git a/chromium/components/autofill/core/browser/webdata/autofill_change.h b/chromium/components/autofill/core/browser/webdata/autofill_change.h index 16c6290fa60..9605de1e35b 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_change.h +++ b/chromium/components/autofill/core/browser/webdata/autofill_change.h @@ -97,10 +97,33 @@ class AutofillProfileDeepChange : public AutofillProfileChange { ~AutofillProfileDeepChange() override {} - AutofillProfile profile() const { return profile_; } + const AutofillProfile* profile() const { return &profile_; } + bool is_ongoing_on_background() const { return is_ongoing_on_background_; } + void set_is_ongoing_on_background() const { + is_ongoing_on_background_ = true; + } + + void validation_effort_made() const { validation_effort_made_ = true; } + bool has_validation_effort_made() const { return validation_effort_made_; } + + void set_enforce_update() { enforce_update_ = true; } + bool enforce_update() const { return enforce_update_; } private: AutofillProfile profile_; + // Is true when the change is taking place on the database side on the + // background. + mutable bool is_ongoing_on_background_ = false; + // Is true when the |profile_| has gone through the validation process. + // Note: This could be different from the + // profile_.is_client_validity_states_updated. |validation_effort_made_| shows + // that the effort has been made, but not necessarily successful, and profile + // validity may or may not be updated. + mutable bool validation_effort_made_ = false; + + // Is true when the update should happen regardless of an equal profile. + // (equal in the sense of AutofillProfile::EqualForUpdate) + mutable bool enforce_update_ = false; }; } // namespace autofill 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 f05cd1227fd..bd2bff78a16 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 @@ -27,6 +27,7 @@ AutofillProfileDataTypeController::AutofillProfileDataTypeController( const base::Closure& dump_stack, syncer::SyncService* sync_service, syncer::SyncClient* sync_client, + const PersonalDataManagerProvider& pdm_provider, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service) : AsyncDirectoryTypeController(syncer::AUTOFILL_PROFILE, dump_stack, @@ -34,6 +35,7 @@ AutofillProfileDataTypeController::AutofillProfileDataTypeController( sync_client, syncer::GROUP_DB, std::move(db_thread)), + pdm_provider_(pdm_provider), web_data_service_(web_data_service), callback_registered_(false), currently_enabled_(IsEnabled()) { @@ -53,7 +55,7 @@ void AutofillProfileDataTypeController::OnPersonalDataChanged() { DCHECK(CalledOnValidThread()); DCHECK_EQ(state(), MODEL_STARTING); - sync_client()->GetPersonalDataManager()->RemoveObserver(this); + pdm_provider_.Run()->RemoveObserver(this); if (!web_data_service_) return; @@ -78,8 +80,7 @@ bool AutofillProfileDataTypeController::StartModels() { DisableForPolicy(); return false; } - autofill::PersonalDataManager* personal_data = - sync_client()->GetPersonalDataManager(); + autofill::PersonalDataManager* personal_data = pdm_provider_.Run(); // Make sure PDM has the sync service. This is needed because in the account // wallet data mode, PDM uses the service to determine whether to use the @@ -118,7 +119,7 @@ bool AutofillProfileDataTypeController::StartModels() { void AutofillProfileDataTypeController::StopModels() { DCHECK(CalledOnValidThread()); - sync_client()->GetPersonalDataManager()->RemoveObserver(this); + pdm_provider_.Run()->RemoveObserver(this); } bool AutofillProfileDataTypeController::ReadyForStart() const { diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h index b2886eea632..4641b0d223d 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h +++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h @@ -5,6 +5,7 @@ #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_ #define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_ +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -16,6 +17,7 @@ namespace autofill { class AutofillWebDataService; +class PersonalDataManager; } // namespace autofill namespace syncer { @@ -30,12 +32,16 @@ class AutofillProfileDataTypeController : public syncer::AsyncDirectoryTypeController, public autofill::PersonalDataManagerObserver { public: + using PersonalDataManagerProvider = + base::RepeatingCallback<autofill::PersonalDataManager*()>; + // |dump_stack| is called when an unrecoverable error occurs. AutofillProfileDataTypeController( scoped_refptr<base::SingleThreadTaskRunner> db_thread, const base::Closure& dump_stack, syncer::SyncService* sync_service, syncer::SyncClient* sync_client, + const PersonalDataManagerProvider& pdm_provider, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service); ~AutofillProfileDataTypeController() override; @@ -61,6 +67,9 @@ class AutofillProfileDataTypeController // Report an error (which will stop the datatype asynchronously). void DisableForPolicy(); + // Callback that allows accessing PersonalDataManager lazily. + const PersonalDataManagerProvider pdm_provider_; + // A reference to the AutofillWebDataService for this controller. scoped_refptr<autofill::AutofillWebDataService> web_data_service_; diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc index 4ee20ea6814..a5047b4ae5b 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc @@ -124,8 +124,9 @@ Optional<syncer::ModelError> AutofillProfileSyncBridge::MergeSyncData( RETURN_IF_ERROR( initial_sync_tracker.MergeSimilarEntriesForInitialSync(app_locale_)); - RETURN_IF_ERROR( - FlushSyncTracker(std::move(metadata_change_list), &initial_sync_tracker)); + RETURN_IF_ERROR(FlushSyncTracker(std::move(metadata_change_list), + &initial_sync_tracker, + AutofillProfileSyncChangeOrigin::kInitial)); web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL_PROFILE); return base::nullopt; @@ -156,7 +157,8 @@ Optional<ModelError> AutofillProfileSyncBridge::ApplySyncChanges( } } - return FlushSyncTracker(std::move(metadata_change_list), &tracker); + return FlushSyncTracker(std::move(metadata_change_list), &tracker, + AutofillProfileSyncChangeOrigin::kIncrementalRemote); } void AutofillProfileSyncBridge::GetData(StorageKeyList storage_keys, @@ -215,6 +217,21 @@ void AutofillProfileSyncBridge::ActOnLocalChange( std::make_unique<syncer::SyncMetadataStoreChangeList>( GetAutofillTable(), syncer::AUTOFILL_PROFILE); + // TODO(crbug.com/904390): Remove when the investigation is over. + bool is_converted_from_server = false; + if (change.type() == AutofillProfileChange::REMOVE) { + // The profile is not available any more so we cannot compare its value, + // instead we use a rougher test based on the id - whether it is a local + // GUID or a server id. As a result, it has a different semantics compared + // to AddOrUpdate. + is_converted_from_server = !base::IsValidGUID(change.key()); + } else { + std::vector<std::unique_ptr<AutofillProfile>> server_profiles; + GetAutofillTable()->GetServerProfiles(&server_profiles); + is_converted_from_server = IsLocalProfileEqualToServerProfile( + server_profiles, *change.data_model(), app_locale_); + } + switch (change.type()) { case AutofillProfileChange::ADD: case AutofillProfileChange::UPDATE: @@ -222,6 +239,12 @@ void AutofillProfileSyncBridge::ActOnLocalChange( change.key(), CreateEntityDataFromAutofillProfile(*change.data_model()), metadata_change_list.get()); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileAddOrUpdateOrigin( + is_converted_from_server + ? AutofillProfileSyncChangeOrigin::kConvertedLocal + : AutofillProfileSyncChangeOrigin::kTrulyLocal); break; case AutofillProfileChange::REMOVE: // Removals have no data_model() so this change can still be for a @@ -231,6 +254,12 @@ void AutofillProfileSyncBridge::ActOnLocalChange( // TODO(jkrcal): implement a hash map of known storage_keys and use it // here. change_processor()->Delete(change.key(), metadata_change_list.get()); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileDeleteOrigin( + is_converted_from_server + ? AutofillProfileSyncChangeOrigin::kConvertedLocal + : AutofillProfileSyncChangeOrigin::kTrulyLocal); break; case AutofillProfileChange::EXPIRE: // EXPIRE changes are not being issued for profiles. @@ -245,7 +274,8 @@ void AutofillProfileSyncBridge::ActOnLocalChange( base::Optional<syncer::ModelError> AutofillProfileSyncBridge::FlushSyncTracker( std::unique_ptr<MetadataChangeList> metadata_change_list, - AutofillProfileSyncDifferenceTracker* tracker) { + AutofillProfileSyncDifferenceTracker* tracker, + AutofillProfileSyncChangeOrigin origin) { DCHECK(tracker); RETURN_IF_ERROR(tracker->FlushToLocal( @@ -259,6 +289,9 @@ base::Optional<syncer::ModelError> AutofillProfileSyncBridge::FlushSyncTracker( change_processor()->Put(GetStorageKeyFromAutofillProfile(*entry), CreateEntityDataFromAutofillProfile(*entry), metadata_change_list.get()); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileAddOrUpdateOrigin(origin); } return static_cast<syncer::SyncMetadataStoreChangeList*>( diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h index a6e50098fe8..9b449f47d66 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h +++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h @@ -29,6 +29,7 @@ class AutofillProfileSyncDifferenceTracker; class AutofillTable; class AutofillWebDataBackend; class AutofillWebDataService; +enum class AutofillProfileSyncChangeOrigin; // Sync bridge implementation for AUTOFILL_PROFILE model type. Takes care of // propagating local autofill profiles to other clients as well as incorporating @@ -90,7 +91,9 @@ class AutofillProfileSyncBridge // Flushes changes accumulated within |tracker| both to local and to sync. base::Optional<syncer::ModelError> FlushSyncTracker( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, - AutofillProfileSyncDifferenceTracker* tracker); + AutofillProfileSyncDifferenceTracker* tracker, + // TODO(crbug.com/904390): Remove |origin| when the investigation is over. + AutofillProfileSyncChangeOrigin origin); // Synchronously load sync metadata from the autofill table and pass it to the // processor so that it can start tracking changes. diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc index 552c2dabef6..08e50b60dfa 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc @@ -1208,7 +1208,7 @@ TEST_P(AutofillProfileSyncBridgeUpdatesUsageStatsTest, UpdatesUsageStats) { EXPECT_THAT(GetAllLocalData(), ElementsAre(WithUsageStats(merged))); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillProfileSyncBridgeTest, AutofillProfileSyncBridgeUpdatesUsageStatsTest, testing::Values( 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 51d3cb7ee83..8022c6abd15 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 @@ -17,6 +17,8 @@ #include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_profile_comparator.h" +// TODO(crbug.com/904390): Remove when the investigation is over. +#include "components/autofill/core/browser/autofill_profile_sync_util.h" #include "components/autofill/core/browser/country_names.h" #include "components/autofill/core/browser/form_group.h" #include "components/autofill/core/browser/webdata/autofill_table.h" @@ -184,6 +186,10 @@ AutofillProfileSyncableService::MergeDataAndStartSyncing( syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, CreateData(*(it.second)))); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileAddOrUpdateOrigin( + AutofillProfileSyncChangeOrigin::kInitial); profiles_map_[it.first] = it.second; } @@ -192,6 +198,10 @@ AutofillProfileSyncableService::MergeDataAndStartSyncing( syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, CreateData(*(bundle.profiles_to_sync_back[i])))); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileAddOrUpdateOrigin( + AutofillProfileSyncChangeOrigin::kInitial); } if (!new_changes.empty()) { @@ -603,6 +613,24 @@ void AutofillProfileSyncableService::ActOnChange( return; } + // TODO(crbug.com/904390): Remove when the investigation is over. + bool is_converted_from_server = false; + if (change.type() == AutofillProfileChange::REMOVE) { + // The profile is not available any more so we cannot compare its value, + // instead we use a rougher test based on the id - whether it is a local + // GUID or a server id. As a result, it has a different semantics compared + // to AddOrUpdate. + is_converted_from_server = !base::IsValidGUID(change.key()); + } else { + // |webdata_backend_|, used by GetAutofillTable() may be null in unit-tests. + if (webdata_backend_ != nullptr) { + std::vector<std::unique_ptr<AutofillProfile>> server_profiles; + GetAutofillTable()->GetServerProfiles(&server_profiles); + is_converted_from_server = IsLocalProfileEqualToServerProfile( + server_profiles, *change.data_model(), app_locale_); + } + } + syncer::SyncChangeList new_changes; DataBundle bundle; switch (change.type()) { @@ -616,6 +644,12 @@ void AutofillProfileSyncableService::ActOnChange( profiles_.push_back( std::make_unique<AutofillProfile>(*(change.data_model()))); profiles_map_[change.data_model()->guid()] = profiles_.back().get(); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileAddOrUpdateOrigin( + is_converted_from_server + ? AutofillProfileSyncChangeOrigin::kConvertedLocal + : AutofillProfileSyncChangeOrigin::kTrulyLocal); break; case AutofillProfileChange::UPDATE: { auto it = profiles_map_.find(change.data_model()->guid()); @@ -625,6 +659,12 @@ void AutofillProfileSyncableService::ActOnChange( syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, CreateData(*(change.data_model())))); + + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileAddOrUpdateOrigin( + is_converted_from_server + ? AutofillProfileSyncChangeOrigin::kConvertedLocal + : AutofillProfileSyncChangeOrigin::kTrulyLocal); break; } case AutofillProfileChange::REMOVE: { @@ -636,6 +676,11 @@ void AutofillProfileSyncableService::ActOnChange( syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_DELETE, CreateData(empty_profile))); profiles_map_.erase(change.key()); + // TODO(crbug.com/904390): Remove when the investigation is over. + ReportAutofillProfileDeleteOrigin( + is_converted_from_server + ? AutofillProfileSyncChangeOrigin::kConvertedLocal + : AutofillProfileSyncChangeOrigin::kTrulyLocal); } break; } diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc index b4dc3f5db51..1b605e9446b 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc @@ -1557,7 +1557,7 @@ TEST_P(SyncUpdatesUsageStatsTest, SyncUpdatesUsageStats) { autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillProfileSyncableServiceTest, SyncUpdatesUsageStatsTest, testing::Values( 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 index 593ce4bc14c..5a9777ebc0d 100644 --- 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 @@ -58,4 +58,4 @@ CreateAutofillWalletSpecificsForPaymentsCustomerData( return wallet_specifics; } -} // namespace autofill
\ No newline at end of file +} // namespace autofill 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 14d9f4ec53d..5ca2d3bd78a 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc @@ -2797,9 +2797,8 @@ class GetFormValuesTest : public testing::TestWithParam<GetFormValuesTestCase> { }; TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) { - // Token matching is currently behind a flag. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableSuggestionsWithSubstringMatch); + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching); auto test_case = GetParam(); SCOPED_TRACE(testing::Message() @@ -2831,7 +2830,7 @@ TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) { table_->RemoveFormElementsAddedBetween(t1, Time(), &changes); } -INSTANTIATE_TEST_CASE_P( +INSTANTIATE_TEST_SUITE_P( AutofillTableTest, GetFormValuesTest, testing::Values(GetFormValuesTestCase{{"user.test", "test_user"}, @@ -2979,10 +2978,10 @@ TEST_P(AutofillTableTestPerModelType, AutofillCorruptModelTypeState) { EXPECT_FALSE(table_->GetAllSyncMetadata(model_type, &metadata_batch)); } -INSTANTIATE_TEST_CASE_P(AutofillTableTest, - AutofillTableTestPerModelType, - testing::Values(syncer::AUTOFILL, - syncer::AUTOFILL_PROFILE)); +INSTANTIATE_TEST_SUITE_P(AutofillTableTest, + AutofillTableTestPerModelType, + testing::Values(syncer::AUTOFILL, + syncer::AUTOFILL_PROFILE)); TEST_F(AutofillTableTest, RemoveOrphanAutofillTableRows) { // Populate the different tables. diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc index 98721d9d598..5f511af4a6c 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc @@ -320,7 +320,9 @@ AutofillWalletMetadataSyncBridge::AutofillWalletMetadataSyncBridge( LoadDataCacheAndMetadata(); } -AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() {} +AutofillWalletMetadataSyncBridge::~AutofillWalletMetadataSyncBridge() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} void AutofillWalletMetadataSyncBridge::OnWalletDataTrackingStateChanged( bool is_tracking) { @@ -338,6 +340,7 @@ base::Optional<syncer::ModelError> AutofillWalletMetadataSyncBridge::MergeSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // First upload local entities that are not mentioned in |entity_data|. UploadInitialLocalData(metadata_change_list.get(), entity_data); @@ -349,6 +352,7 @@ base::Optional<syncer::ModelError> AutofillWalletMetadataSyncBridge::ApplySyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return MergeRemoteChanges(std::move(metadata_change_list), std::move(entity_data)); } @@ -369,6 +373,7 @@ void AutofillWalletMetadataSyncBridge::GetAllDataForDebugging( std::string AutofillWalletMetadataSyncBridge::GetClientTag( const syncer::EntityData& entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const WalletMetadataSpecifics& remote_metadata = entity_data.specifics.wallet_metadata(); return GetClientTagForSpecificsId(remote_metadata.type(), @@ -377,6 +382,7 @@ std::string AutofillWalletMetadataSyncBridge::GetClientTag( std::string AutofillWalletMetadataSyncBridge::GetStorageKey( const syncer::EntityData& entity_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return GetStorageKeyForWalletMetadataTypeAndSpecificsId( entity_data.specifics.wallet_metadata().type(), entity_data.specifics.wallet_metadata().id()); diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc index 4306ae52280..a9322372bcb 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc @@ -81,6 +81,9 @@ const std::string kCard1StorageKey = const char kAddr1SyncTag[] = "address-YWRkcjHvv74="; const char kCard1SyncTag[] = "card-Y2FyZDHvv74="; +const char kLocalAddr1ServerId[] = "e171e3ed-858a-4dd5-9bf3-8517f14ba5fc"; +const char kLocalAddr2ServerId[] = "fa232b9a-f248-4e5a-8d76-d46f821c0c5f"; + const char kLocaleString[] = "en-US"; const base::Time kJune2017 = base::Time::FromDoubleT(1497552271); @@ -103,17 +106,18 @@ std::string GetCardStorageKey(const std::string& specifics_id) { WalletMetadataSpecifics::CARD, specifics_id); } -WalletMetadataSpecifics CreateWalletMetadataSpecificsForAddressWithUseStats( +WalletMetadataSpecifics CreateWalletMetadataSpecificsForAddressWithDetails( const std::string& specifics_id, size_t use_count, - int64_t use_date) { + int64_t use_date, + bool has_converted = false) { 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); + // False is the default value according to the constructor of AutofillProfile. + specifics.set_address_has_converted(has_converted); return specifics; } @@ -121,22 +125,24 @@ 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( + return CreateWalletMetadataSpecificsForAddressWithDetails( specifics_id, /*use_count=*/1, /*use_date=*/UseDateToProtoValue(kJune2017)); } -WalletMetadataSpecifics CreateWalletMetadataSpecificsForCardWithUseStats( +WalletMetadataSpecifics CreateWalletMetadataSpecificsForCardWithDetails( const std::string& specifics_id, size_t use_count, - int64_t use_date) { + int64_t use_date, + const std::string& billing_address_id = "") { 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(""); + // "" is the default value according to the constructor of AutofillProfile; + // this field is Base64 encoded in the protobuf. + specifics.set_card_billing_address_id(GetBase64EncodedId(billing_address_id)); return specifics; } @@ -144,29 +150,49 @@ 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( + return CreateWalletMetadataSpecificsForCardWithDetails( 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 CreateServerProfileWithDetails(const std::string& server_id, + size_t use_count, + int64_t use_date, + bool has_converted = false) { AutofillProfile profile = CreateServerProfile(server_id); profile.set_use_count(use_count); profile.set_use_date(UseDateFromProtoValue(use_date)); + profile.set_has_converted(has_converted); return profile; } -CreditCard CreateServerCreditCardWithUseStats(const std::string& server_id, - size_t use_count, - int64_t use_date) { +CreditCard CreateServerCreditCardWithDetails( + const std::string& server_id, + size_t use_count, + int64_t use_date, + const std::string& billing_address_id = "") { CreditCard card = CreateServerCreditCard(server_id); card.set_use_count(use_count); card.set_use_date(UseDateFromProtoValue(use_date)); + card.set_billing_address_id(billing_address_id); return card; } +AutofillProfile CreateServerProfileFromSpecifics( + const WalletMetadataSpecifics& specifics) { + return CreateServerProfileWithDetails( + GetBase64DecodedId(specifics.id()), specifics.use_count(), + specifics.use_date(), specifics.address_has_converted()); +} + +CreditCard CreateServerCreditCardFromSpecifics( + const WalletMetadataSpecifics& specifics) { + return CreateServerCreditCardWithDetails( + GetBase64DecodedId(specifics.id()), specifics.use_count(), + specifics.use_date(), + GetBase64DecodedId(specifics.card_billing_address_id())); +} + void ExtractWalletMetadataSpecificsFromDataBatch( std::unique_ptr<DataBatch> batch, std::vector<WalletMetadataSpecifics>* output) { @@ -182,7 +208,7 @@ std::string WalletMetadataSpecificsAsDebugString( output << "[id: " << specifics.id() << ", type: " << static_cast<int>(specifics.type()) << ", use_count: " << specifics.use_count() - << ", use_date: " << UseDateFromProtoValue(specifics.use_date()) + << ", use_date: " << specifics.use_date() << ", card_billing_address_id: " << (specifics.has_card_billing_address_id() ? specifics.card_billing_address_id() @@ -256,11 +282,47 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test { mock_processor_.DelegateCallsByDefaultTo(real_processor_.get()); } - void ResetBridge() { + void ResetBridge(bool initial_sync_done = true) { + sync_pb::ModelTypeState model_type_state; + model_type_state.set_initial_sync_done(initial_sync_done); + EXPECT_TRUE(table()->UpdateModelTypeState(syncer::AUTOFILL_WALLET_METADATA, + model_type_state)); bridge_.reset(new AutofillWalletMetadataSyncBridge( mock_processor_.CreateForwardingProcessor(), &backend_)); } + void StartSyncing( + const std::vector<WalletMetadataSpecifics>& 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(); + + ReceiveUpdates(remote_data); + } + + void ReceiveUpdates( + const std::vector<WalletMetadataSpecifics>& remote_data = {}) { + // Make sure each update has an updated response version so that it does not + // get filtered out as reflection by the processor. + ++response_version; + // After this update initial sync is for sure done. + sync_pb::ModelTypeState state; + state.set_initial_sync_done(true); + + syncer::UpdateResponseDataList updates; + for (const WalletMetadataSpecifics& specifics : remote_data) { + updates.push_back(SpecificsToUpdateResponse(specifics)); + } + real_processor_->OnUpdateReceived(state, updates); + } + EntityData SpecificsToEntity(const WalletMetadataSpecifics& specifics) { EntityData data; *data.specifics.mutable_wallet_metadata() = specifics; @@ -269,6 +331,14 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test { return data; } + syncer::UpdateResponseData SpecificsToUpdateResponse( + const WalletMetadataSpecifics& specifics) { + syncer::UpdateResponseData data; + data.entity = SpecificsToEntity(specifics).PassToPtr(); + data.response_version = response_version; + return data; + } + std::vector<WalletMetadataSpecifics> GetAllLocalData() { std::vector<WalletMetadataSpecifics> data; // Perform an async call synchronously for testing. @@ -321,6 +391,7 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test { MockAutofillWebDataBackend* backend() { return &backend_; } private: + int response_version = 0; autofill::TestAutofillClock test_clock_; ScopedTempDir temp_dir_; base::test::ScopedTaskEnvironment scoped_task_environment_; @@ -449,15 +520,15 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, GetData_ShouldReturnCompleteData) { // local metadata is updated. TEST_F(AutofillWalletMetadataSyncBridgeTest, DontSendLowerValueToServerOnUpdate) { - table()->SetServerProfiles({CreateServerProfileWithUseStats( + table()->SetServerProfiles({CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/2, /*use_date=*/5)}); - table()->SetServerCreditCards({CreateServerCreditCardWithUseStats( + table()->SetServerCreditCards({CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/3, /*use_date=*/6)}); ResetBridge(); - AutofillProfile updated_profile = CreateServerProfileWithUseStats( + AutofillProfile updated_profile = CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/1, /*use_date=*/4); - CreditCard updated_card = CreateServerCreditCardWithUseStats( + CreditCard updated_card = CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/2, /*use_date=*/5); EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); @@ -472,9 +543,44 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, EXPECT_THAT( GetAllLocalDataInclRestart(), UnorderedElementsAre( - EqualsSpecifics(CreateWalletMetadataSpecificsForAddressWithUseStats( + EqualsSpecifics(CreateWalletMetadataSpecificsForAddressWithDetails( kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/5)), - EqualsSpecifics(CreateWalletMetadataSpecificsForCardWithUseStats( + EqualsSpecifics(CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6)))); +} + +// Verify that lower values of metadata are not sent to the sync server when +// local metadata is created (tests the case when metadata with higher use +// counts arrive before the data, the data bridge later notifies about creation +// for data that is already there). +TEST_F(AutofillWalletMetadataSyncBridgeTest, + DontSendLowerValueToServerOnCreation) { + table()->SetServerProfiles({CreateServerProfileWithDetails( + kAddr1ServerId, /*use_count=*/2, /*use_date=*/5)}); + table()->SetServerCreditCards({CreateServerCreditCardWithDetails( + kCard1ServerId, /*use_count=*/3, /*use_date=*/6)}); + ResetBridge(); + + AutofillProfile updated_profile = CreateServerProfileWithDetails( + kAddr1ServerId, /*use_count=*/1, /*use_date=*/4); + CreditCard updated_card = CreateServerCreditCardWithDetails( + kCard1ServerId, /*use_count=*/2, /*use_date=*/5); + + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + bridge()->AutofillProfileChanged( + AutofillProfileChange(AutofillProfileChange::ADD, + updated_profile.server_id(), &updated_profile)); + bridge()->CreditCardChanged(CreditCardChange( + CreditCardChange::ADD, updated_card.server_id(), &updated_card)); + + // Check that also the local metadata did not get updated. + EXPECT_THAT( + GetAllLocalDataInclRestart(), + UnorderedElementsAre( + EqualsSpecifics(CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/5)), + EqualsSpecifics(CreateWalletMetadataSpecificsForCardWithDetails( kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6)))); } @@ -482,22 +588,22 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, // metadata is updated. TEST_F(AutofillWalletMetadataSyncBridgeTest, SendHigherValuesToServerOnLocalUpdate) { - table()->SetServerProfiles({CreateServerProfileWithUseStats( + table()->SetServerProfiles({CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/1, /*use_date=*/2)}); - table()->SetServerCreditCards({CreateServerCreditCardWithUseStats( + table()->SetServerCreditCards({CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/3, /*use_date=*/4)}); ResetBridge(); - AutofillProfile updated_profile = CreateServerProfileWithUseStats( + AutofillProfile updated_profile = CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/10, /*use_date=*/20); - CreditCard updated_card = CreateServerCreditCardWithUseStats( + CreditCard updated_card = CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/30, /*use_date=*/40); WalletMetadataSpecifics expected_profile_specifics = - CreateWalletMetadataSpecificsForAddressWithUseStats( + CreateWalletMetadataSpecificsForAddressWithDetails( kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20); WalletMetadataSpecifics expected_card_specifics = - CreateWalletMetadataSpecificsForCardWithUseStats( + CreateWalletMetadataSpecificsForCardWithDetails( kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40); EXPECT_CALL( @@ -522,16 +628,16 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, TEST_F(AutofillWalletMetadataSyncBridgeTest, SendNewDataToServerOnLocalAddition) { ResetBridge(); - AutofillProfile new_profile = CreateServerProfileWithUseStats( + AutofillProfile new_profile = CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/10, /*use_date=*/20); - CreditCard new_card = CreateServerCreditCardWithUseStats( + CreditCard new_card = CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/30, /*use_date=*/40); WalletMetadataSpecifics expected_profile_specifics = - CreateWalletMetadataSpecificsForAddressWithUseStats( + CreateWalletMetadataSpecificsForAddressWithDetails( kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20); WalletMetadataSpecifics expected_card_specifics = - CreateWalletMetadataSpecificsForCardWithUseStats( + CreateWalletMetadataSpecificsForCardWithDetails( kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40); EXPECT_CALL( @@ -556,16 +662,16 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, // recreates metadata that may get deleted in the mean-time). TEST_F(AutofillWalletMetadataSyncBridgeTest, SendNewDataToServerOnLocalUpdate) { ResetBridge(); - AutofillProfile new_profile = CreateServerProfileWithUseStats( + AutofillProfile new_profile = CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/10, /*use_date=*/20); - CreditCard new_card = CreateServerCreditCardWithUseStats( + CreditCard new_card = CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/30, /*use_date=*/40); WalletMetadataSpecifics expected_profile_specifics = - CreateWalletMetadataSpecificsForAddressWithUseStats( + CreateWalletMetadataSpecificsForAddressWithDetails( kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/20); WalletMetadataSpecifics expected_card_specifics = - CreateWalletMetadataSpecificsForCardWithUseStats( + CreateWalletMetadataSpecificsForCardWithDetails( kCard1SpecificsId, /*use_count=*/30, /*use_date=*/40); EXPECT_CALL( @@ -588,9 +694,9 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, SendNewDataToServerOnLocalUpdate) { // Verify that one-off deletion of existing metadata is sent to the sync server. TEST_F(AutofillWalletMetadataSyncBridgeTest, DeleteExistingDataFromServerOnLocalDeletion) { - AutofillProfile existing_profile = CreateServerProfileWithUseStats( + AutofillProfile existing_profile = CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/10, /*use_date=*/20); - CreditCard existing_card = CreateServerCreditCardWithUseStats( + CreditCard existing_card = CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/30, /*use_date=*/40); table()->SetServerProfiles({existing_profile}); table()->SetServerCreditCards({existing_card}); @@ -611,9 +717,9 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, // Verify that deletion of non-existing metadata is not sent to the sync server. TEST_F(AutofillWalletMetadataSyncBridgeTest, DoNotDeleteNonExistingDataFromServerOnLocalDeletion) { - AutofillProfile existing_profile = CreateServerProfileWithUseStats( + AutofillProfile existing_profile = CreateServerProfileWithDetails( kAddr1ServerId, /*use_count=*/10, /*use_date=*/20); - CreditCard existing_card = CreateServerCreditCardWithUseStats( + CreditCard existing_card = CreateServerCreditCardWithDetails( kCard1ServerId, /*use_count=*/30, /*use_date=*/40); // Save only data and not metadata. table()->SetServerAddressesData({existing_profile}); @@ -624,7 +730,6 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, ASSERT_THAT(GetAllLocalDataInclRestart(), IsEmpty()); EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); - EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); bridge()->AutofillProfileChanged(AutofillProfileChange( AutofillProfileChange::REMOVE, existing_profile.server_id(), nullptr)); @@ -635,4 +740,639 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest, EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty()); } +enum RemoteChangesMode { + INITIAL_SYNC_ADD, // Initial sync -> ADD changes. + LATER_SYNC_ADD, // Later sync; the client receives the data for the first + // time -> ADD changes. + LATER_SYNC_UPDATE // Later sync; the client has received the data before -> + // UPDATE changes. +}; + +// Parametrized fixture for tests that apply in the same way for all +// RemoteChangesModes. +class AutofillWalletMetadataSyncBridgeRemoteChangesTest + : public testing::WithParamInterface<RemoteChangesMode>, + public AutofillWalletMetadataSyncBridgeTest { + public: + AutofillWalletMetadataSyncBridgeRemoteChangesTest() {} + ~AutofillWalletMetadataSyncBridgeRemoteChangesTest() override {} + + void ResetBridgeWithPotentialInitialSync( + const std::vector<WalletMetadataSpecifics>& remote_data) { + AutofillWalletMetadataSyncBridgeTest::ResetBridge( + /*initial_sync_done=*/GetParam() != INITIAL_SYNC_ADD); + + if (GetParam() == LATER_SYNC_UPDATE) { + StartSyncing(remote_data); + } + } + + void ReceivePotentiallyInitialUpdates( + const std::vector<WalletMetadataSpecifics>& remote_data = {}) { + if (GetParam() != LATER_SYNC_UPDATE) { + StartSyncing(remote_data); + } else { + AutofillWalletMetadataSyncBridgeTest::ReceiveUpdates(remote_data); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillWalletMetadataSyncBridgeRemoteChangesTest); +}; + +// No upstream communication or local DB change happens if the server sends an +// empty update. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, EmptyUpdateIgnored) { + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ResetBridgeWithPotentialInitialSync({}); + ReceivePotentiallyInitialUpdates({}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty()); +} + +// No upstream communication or local DB change happens if the server sends the +// same data as we have locally. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, SameDataIgnored) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/5); + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({profile, card}); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates({profile, card}); + + EXPECT_THAT( + GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(profile), EqualsSpecifics(card))); +} + +// Tests that if the remote use stats are higher / newer, they should win over +// local stats. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_PreferHigherValues_RemoteWins) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/5); + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({profile, card}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/50); + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/60); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates( + {updated_remote_profile, updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(updated_remote_profile), + EqualsSpecifics(updated_remote_card))); +} + +// Tests that if the local use stats are higher / newer, they should win over +// remote stats. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_PreferHigherValues_LocalWins) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/50); + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/60); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({profile, card}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/5); + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kAddr1StorageKey, HasSpecifics(profile), _)); + EXPECT_CALL(mock_processor(), Put(kCard1StorageKey, HasSpecifics(card), _)); + + ReceivePotentiallyInitialUpdates( + {updated_remote_profile, updated_remote_card}); + + EXPECT_THAT( + GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(profile), EqualsSpecifics(card))); +} + +// Tests that the conflicts are resolved component-wise (a higher use_count is +// taken from local data, a newer use_data is taken from remote data). +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_PreferHigherValues_BothWin1) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/5); + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/6); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({profile, card}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/50); + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60); + + WalletMetadataSpecifics merged_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/50); + WalletMetadataSpecifics merged_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/60); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kAddr1StorageKey, HasSpecifics(merged_profile), _)); + EXPECT_CALL(mock_processor(), + Put(kCard1StorageKey, HasSpecifics(merged_card), _)); + + ReceivePotentiallyInitialUpdates( + {updated_remote_profile, updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(merged_profile), + EqualsSpecifics(merged_card))); +} + +// Tests that the conflicts are resolved component-wise, like the previous test, +// only the other way around (a higher use_count is taken from remote data, a +// newer use_data is taken from local data). +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_PreferHigherValues_BothWin2) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/2, /*use_date=*/50); + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({profile, card}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/5); + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/6); + + WalletMetadataSpecifics merged_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/50); + WalletMetadataSpecifics merged_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/60); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kAddr1StorageKey, HasSpecifics(merged_profile), _)); + EXPECT_CALL(mock_processor(), + Put(kCard1StorageKey, HasSpecifics(merged_card), _)); + + ReceivePotentiallyInitialUpdates( + {updated_remote_profile, updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(merged_profile), + EqualsSpecifics(merged_card))); +} + +// No merge logic is applied if local data has initial use_count (=1). In this +// situation, we just take over the remote entity completely. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_PreferRemoteIfLocalHasInitialUseCount) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50); + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/1, /*use_date=*/60); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({profile, card}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/20, /*use_date=*/5); + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/6); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates( + {updated_remote_profile, updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(updated_remote_profile), + EqualsSpecifics(updated_remote_card))); +} + +// Tests that with a conflict in billing_address_id, we prefer an ID of a local +// profile over an ID of a server profile. In this test, the preferred ID is in +// the remote update that we need to store locally. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferLocalBillingAddressId_RemoteWins) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kLocalAddr1ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(updated_remote_card))); +} + +// Tests that with a conflict in billing_address_id, we prefer an ID of a local +// profile over an ID of a server profile. In this test, the preferred ID is in +// the local data that we need to upstream. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferLocalBillingAddressId_LocalWins) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kLocalAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kAddr1ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(kCard1StorageKey, HasSpecifics(card), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(card))); +} + +// Tests that if both addresses have billing address ids of local profiles, we +// prefer the one from the most recently used entity. In this test, it is the +// remote entity. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferNewerBillingAddressOutOfLocalIds_RemoteWins) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kLocalAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60, + /*billing_address_id=*/kLocalAddr2ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(updated_remote_card))); +} + +// Tests that if both addresses have billing address ids of local profiles, we +// prefer the one from the most recently used entity. In this test, it is the +// local entity. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferNewerBillingAddressOutOfLocalIds_LocalWins) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60, + /*billing_address_id=*/kLocalAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kLocalAddr2ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(kCard1StorageKey, HasSpecifics(card), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(card))); +} + +// Tests that if both addresses have billing address ids of server profiles, we +// prefer the one from the most recently used entity. In this test, it is the +// remote entity. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferNewerBillingAddressOutOfServerIds_RemoteWins) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60, + /*billing_address_id=*/kAddr2ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(updated_remote_card))); +} + +// Tests that if both addresses have billing address ids of server profiles, we +// prefer the one from the most recently used entity. In this test, it is the +// local entity. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferNewerBillingAddressOutOfServerIds_LocalWins) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60, + /*billing_address_id=*/kAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/6, + /*billing_address_id=*/kAddr2ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(kCard1StorageKey, HasSpecifics(card), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(card))); +} + +// Tests that the conflict resolution happens component-wise. To avoid +// combinatorial explosion, this only tests when both have billing address ids +// of server profiles, one entity is more recently used but the other entity has +// a higher use_count. We should pick the billing_address_id of the newer one +// but have the use_count updated to the maximum as well. In this test, the +// remote entity is the more recently used. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferNewerBillingAddressOutOfServerIds_BothWin1) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/6, + /*billing_address_id=*/kAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60, + /*billing_address_id=*/kAddr2ServerId); + + WalletMetadataSpecifics merged_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/60, + /*billing_address_id=*/kAddr2ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kCard1StorageKey, HasSpecifics(merged_card), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(merged_card))); +} + +// Tests that the conflict resolution happens component-wise. To avoid +// combinatorial explosion, this only tests when both have billing address ids +// of server profiles, one entity is more recently used but the other entity has +// a higher use_count. We should pick the billing_address_id of the newer one +// but have the use_count updated to the maximum as well. In this test, the +// local entity is the more recently used. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Card_PreferNewerBillingAddressOutOfServerIds_BothWin2) { + WalletMetadataSpecifics card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/3, /*use_date=*/60, + /*billing_address_id=*/kAddr1ServerId); + + table()->SetServerCreditCards({CreateServerCreditCardFromSpecifics(card)}); + ResetBridgeWithPotentialInitialSync({card}); + + WalletMetadataSpecifics updated_remote_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/6, + /*billing_address_id=*/kAddr2ServerId); + + WalletMetadataSpecifics merged_card = + CreateWalletMetadataSpecificsForCardWithDetails( + kCard1SpecificsId, /*use_count=*/30, /*use_date=*/60, + /*billing_address_id=*/kAddr1ServerId); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kCard1StorageKey, HasSpecifics(merged_card), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_card}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(merged_card))); +} + +// Tests that if the has_converted bit differs, we always end up with the true +// value. This test has the remote entity converted which should get updated in +// the local DB. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Address_HasConverted_RemoteWins) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50, + /*has_converted=*/false); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + ResetBridgeWithPotentialInitialSync({profile}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50, + /*has_converted=*/true); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), Put(_, _, _)).Times(0); + + ReceivePotentiallyInitialUpdates({updated_remote_profile}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(updated_remote_profile))); +} + +// Tests that if the has_converted bit differs, we always end up with the true +// value. This test has the local entity converted which should get upstreamed. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Address_HasConverted_LocalWins) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50, + /*has_converted=*/true); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + ResetBridgeWithPotentialInitialSync({profile}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50, + /*has_converted=*/false); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kAddr1StorageKey, HasSpecifics(profile), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_profile}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(profile))); +} + +// Tests that the conflict resolution happens component-wise. If one entity +// has_converted but the other entity has higher use_count, we should end up +// with an entity that has_converted and has the higher use_count. This test has +// the remote entity converted. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Address_HasConverted_BothWin1) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/50, + /*has_converted=*/false); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + ResetBridgeWithPotentialInitialSync({profile}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50, + /*has_converted=*/true); + + WalletMetadataSpecifics merged_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/50, + /*has_converted=*/true); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kAddr1StorageKey, HasSpecifics(merged_profile), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_profile}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(merged_profile))); +} + +// Tests that the conflict resolution happens component-wise. If one entity +// has_converted but the other entity has higher use_count, we should end up +// with an entity that has_converted and has the higher use_count. This test has +// the local entity converted. +TEST_P(AutofillWalletMetadataSyncBridgeRemoteChangesTest, + Conflict_Address_HasConverted_BothWin2) { + WalletMetadataSpecifics profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/1, /*use_date=*/50, + /*has_converted=*/true); + + table()->SetServerProfiles({CreateServerProfileFromSpecifics(profile)}); + ResetBridgeWithPotentialInitialSync({profile}); + + WalletMetadataSpecifics updated_remote_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/50, + /*has_converted=*/false); + + WalletMetadataSpecifics merged_profile = + CreateWalletMetadataSpecificsForAddressWithDetails( + kAddr1SpecificsId, /*use_count=*/10, /*use_date=*/50, + /*has_converted=*/true); + + EXPECT_CALL(mock_processor(), Delete(_, _)).Times(0); + EXPECT_CALL(mock_processor(), + Put(kAddr1StorageKey, HasSpecifics(merged_profile), _)); + + ReceivePotentiallyInitialUpdates({updated_remote_profile}); + + EXPECT_THAT(GetAllLocalDataInclRestart(), + UnorderedElementsAre(EqualsSpecifics(merged_profile))); +} + +INSTANTIATE_TEST_SUITE_P(, + AutofillWalletMetadataSyncBridgeRemoteChangesTest, + ::testing::Values(INITIAL_SYNC_ADD, + LATER_SYNC_ADD, + LATER_SYNC_UPDATE)); + } // namespace autofill + +namespace sync_pb { + +// Makes the GMock matchers print out a readable version of the protobuf. +void PrintTo(const WalletMetadataSpecifics& specifics, std::ostream* os) { + *os << autofill::WalletMetadataSpecificsAsDebugString(specifics); +} + +} // namespace sync_pb 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 86fd8a07dff..7b88c1b8b36 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc @@ -511,8 +511,6 @@ syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges( // get rid of this hack. DCHECK(!ignore_multiple_changed_notification_); ignore_multiple_changed_notification_ = true; - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " ProcessSyncChanges notify the PDM"; web_data_backend_->NotifyOfMultipleAutofillChanges(); ignore_multiple_changed_notification_ = false; } @@ -541,13 +539,9 @@ void AutofillWalletMetadataSyncableService::AutofillProfileChanged( it->GetSpecifics().wallet_metadata(); const AutofillProfile& local = *change.data_model(); - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " AutofillProfileChanged " << local; if (!AreLocalUseStatsUpdated(remote, local) && !IsLocalHasConvertedStatusUpdated(remote, local)) { - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " Nothing has changed, not syncing up."; return; } @@ -573,8 +567,11 @@ void AutofillWalletMetadataSyncableService::CreditCardChanged( server_id, sync_pb::WalletMetadataSpecifics::CARD, &cache_); if (it == cache_.end()) return; - // Implicitly, we filter out ADD (not in cache) and REMOVE (!data_model()). - DCHECK(change.type() == AutofillProfileChange::UPDATE); + // Deletions and creations are treated by Wallet data sync (and propagated + // here by AutofillMultipleChanged()). We only treat updates here. + if (change.type() != AutofillProfileChange::UPDATE) { + return; + } const sync_pb::WalletMetadataSpecifics& remote = it->GetSpecifics().wallet_metadata(); @@ -662,8 +659,6 @@ bool AutofillWalletMetadataSyncableService::GetLocalData( bool AutofillWalletMetadataSyncableService::UpdateAddressStats( const AutofillProfile& profile) { - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " Applying change from sync " << profile; return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()) ->UpdateServerAddressMetadata(profile); } @@ -763,8 +758,6 @@ syncer::SyncMergeResult AutofillWalletMetadataSyncableService::MergeData( // get rid of this hack. DCHECK(!ignore_multiple_changed_notification_); ignore_multiple_changed_notification_ = true; - // TODO(crbug.com/915229): Remove once the investigation is over. - DLOG(WARNING) << this << " MergeData notify the PDM"; web_data_backend_->NotifyOfMultipleAutofillChanges(); ignore_multiple_changed_notification_ = false; } diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc index 8631ea78944..a3a4494ddb1 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc @@ -21,6 +21,7 @@ #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/autofill/core/common/autofill_util.h" +#include "components/sync/base/data_type_histogram.h" #include "components/sync/driver/sync_driver_switches.h" #include "components/sync/model/entity_data.h" #include "components/sync/model/mutable_data_batch.h" @@ -253,8 +254,7 @@ bool AutofillWalletSyncBridge::SupportsIncrementalUpdates() const { return false; } -AutofillWalletSyncBridge::StopSyncResponse -AutofillWalletSyncBridge::ApplyStopSyncChanges( +void 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. @@ -262,11 +262,25 @@ AutofillWalletSyncBridge::ApplyStopSyncChanges( if (initial_sync_done_) { active_callback_.Run(false); } + + // Report count of entities to delete. This use case should be pretty rare + // so it is okay to read it from DB again. + // TODO(crbug.com/853688): Remove when wallet data is launched on USS, incl. + // the helper function SyncWalletDataRecordClearedEntitiesCount(). + 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)) { + int count = profiles.size() + cards.size() + (customer_data ? 1 : 0); + SyncWalletDataRecordClearedEntitiesCount(count); + } + SetSyncData(syncer::EntityChangeList()); initial_sync_done_ = false; } - return StopSyncResponse::kModelStillReadyToSync; } void AutofillWalletSyncBridge::GetAllDataForTesting(DataCallback callback) { @@ -327,6 +341,13 @@ void AutofillWalletSyncBridge::SetSyncData( wallet_data_changed |= SetWalletAddresses(std::move(wallet_addresses), should_log_diff); + // Commit the transaction to make sure the data and the metadata with the + // new progress marker is written down (especially on Android where we + // cannot rely on commiting transactions on shutdown). We need to commit + // even if the wallet data has not changed because the model type state incl. + // the progress marker always changes. + web_data_backend_->CommitChanges(); + if (web_data_backend_ && wallet_data_changed) web_data_backend_->NotifyOfMultipleAutofillChanges(); } diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h index 17ea21c91bb..3f91a3c6276 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h +++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h @@ -66,9 +66,8 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data, 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; + void 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 (whereas GetAllDataForDebugging() has to make them UTF-8). diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc index 97c9520760b..9549f984cc4 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc +++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc @@ -369,7 +369,7 @@ class AutofillWalletSyncBridgeTest : public UssSwitchToggler, base::MockCallback<base::RepeatingCallback<void(bool)>>* active_callback() { return &active_callback_; - }; + } private: autofill::TestAutofillClock test_clock_; @@ -487,6 +487,7 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) { &customer_data_specifics); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()); + EXPECT_CALL(*backend(), CommitChanges()); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged( AddChange(address2.server_id(), address2))); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged( @@ -533,6 +534,7 @@ TEST_P(AutofillWalletSyncBridgeTest, &customer_data_specifics); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()); + EXPECT_CALL(*backend(), CommitChanges()); StartSyncing({profile_specifics, card_specifics, customer_data_specifics}); if (IsWalletMetadataOnUSS()) { @@ -573,6 +575,7 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NewPaymentsCustomerData) { &customer_data_specifics2); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()); + EXPECT_CALL(*backend(), CommitChanges()); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0); EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0); StartSyncing({profile_specifics, card_specifics, customer_data_specifics2}); @@ -596,6 +599,7 @@ TEST_P(AutofillWalletSyncBridgeTest, MergeSyncData_NoWalletAddressOrCard) { table()->SetServerCreditCards({local_card}); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()); + EXPECT_CALL(*backend(), CommitChanges()); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged( RemoveChange(local_profile.server_id()))); EXPECT_CALL(*backend(), @@ -636,6 +640,8 @@ TEST_P(AutofillWalletSyncBridgeTest, &customer_data_specifics); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0); + // We still need to commit the updated progress marker on the client. + EXPECT_CALL(*backend(), CommitChanges()); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0); EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0); StartSyncing({profile_specifics, card_specifics, customer_data_specifics}); @@ -672,6 +678,7 @@ TEST_P(AutofillWalletSyncBridgeTest, SetAutofillWalletSpecificsFromPaymentsCustomerData(customer_data, &customer_data_specifics); + EXPECT_CALL(*backend(), CommitChanges()); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged( RemoveChange(profile2.server_id()))); @@ -817,6 +824,7 @@ TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) { CreditCard local_card = test::GetMaskedServerCard(); table()->SetServerCreditCards({local_card}); + EXPECT_CALL(*backend(), CommitChanges()); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged( RemoveChange(local_profile.server_id()))); @@ -846,6 +854,8 @@ TEST_P(AutofillWalletSyncBridgeTest, ApplyStopSyncChanges_KeepData) { CreditCard local_card = test::GetMaskedServerCard(); table()->SetServerCreditCards({local_card}); + // We do not write to DB at all, so we should not commit any changes. + EXPECT_CALL(*backend(), CommitChanges()).Times(0); EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0); EXPECT_CALL(*backend(), NotifyOfAutofillProfileChanged(_)).Times(0); EXPECT_CALL(*backend(), NotifyOfCreditCardChanged(_)).Times(0); @@ -884,8 +894,8 @@ TEST_P(AutofillWalletSyncBridgeTest, NotifiesWhenActivelySyncing) { bridge()->ApplyStopSyncChanges(/*delete_metadata_change_list=*/nullptr); } -INSTANTIATE_TEST_CASE_P(USS, - AutofillWalletSyncBridgeTest, - ::testing::Values(false, true)); +INSTANTIATE_TEST_SUITE_P(USS, + AutofillWalletSyncBridgeTest, + ::testing::Values(false, true)); } // namespace autofill diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend.h index 43ff06e9619..aa37b89bc4d 100644 --- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend.h +++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend.h @@ -34,6 +34,12 @@ class AutofillWebDataBackend { // Remove expired elements from the database and commit if needed. virtual void RemoveExpiredFormElements() = 0; + // Commits the currently open transaction in the database. Should be only used + // by parties that talk directly to the database and not through the + // WebDatabase backend (notably Sync reacting to remote changes coming from + // the server). + virtual void CommitChanges() = 0; + // Notifies listeners on the DB sequence that an AutofillProfile has been // added/removed/updated in the WebDatabase. // NOTE: This method is intended to be called from the DB sequence. The UI 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 e69f6834bc4..d7cb6af4768 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 @@ -25,6 +25,12 @@ using base::Time; namespace autofill { +namespace { +WebDatabase::State DoNothingAndCommit(WebDatabase* db) { + return WebDatabase::COMMIT_NEEDED; +} +} // namespace + AutofillWebDataBackendImpl::AutofillWebDataBackendImpl( scoped_refptr<WebDatabaseBackend> web_database_backend, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, @@ -64,6 +70,10 @@ WebDatabase* AutofillWebDataBackendImpl::GetDatabase() { return web_database_backend_->database(); } +void AutofillWebDataBackendImpl::CommitChanges() { + web_database_backend_->ExecuteWriteTask(Bind(&DoNothingAndCommit)); +} + void AutofillWebDataBackendImpl::RemoveExpiredFormElements() { web_database_backend_->ExecuteWriteTask( Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl, this)); 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 9b4a5a2abb6..b508bda93b1 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 @@ -70,6 +70,7 @@ class AutofillWebDataBackendImpl void NotifyOfCreditCardChanged(const CreditCardChange& change) override; void NotifyOfMultipleAutofillChanges() override; void NotifyThatSyncHasStarted(syncer::ModelType model_type) override; + void CommitChanges() override; // TODO(crbug.com/920214): Deprecated, will be removed when // autocomplete retention policy shipped. Replaced by diff --git a/chromium/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h b/chromium/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h index 7b747246664..3368878abf0 100644 --- a/chromium/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h +++ b/chromium/components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h @@ -27,6 +27,7 @@ class MockAutofillWebDataBackend : public AutofillWebDataBackend { MOCK_METHOD1(RemoveObserver, void(AutofillWebDataServiceObserverOnDBSequence* observer)); MOCK_METHOD0(RemoveExpiredFormElements, void()); + MOCK_METHOD0(CommitChanges, void()); MOCK_METHOD1(NotifyOfAutofillProfileChanged, void(const AutofillProfileChange& change)); MOCK_METHOD1(NotifyOfCreditCardChanged, void(const CreditCardChange& change)); |