summaryrefslogtreecommitdiff
path: root/chromium/components/autofill/core
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 15:06:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:48:58 +0000
commitdaa093eea7c773db06799a13bd7e4e2e2a9f8f14 (patch)
tree96cc5e7b9194c1b29eab927730bfa419e7111c25 /chromium/components/autofill/core
parentbe59a35641616a4cf23c4a13fa0632624b021c1b (diff)
downloadqtwebengine-chromium-daa093eea7c773db06799a13bd7e4e2e2a9f8f14.tar.gz
BASELINE: Update Chromium to 63.0.3239.58
Change-Id: Ia93b322a00ba4dd4004f3bcf1254063ba90e1605 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/autofill/core')
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn15
-rw-r--r--chromium/components/autofill/core/browser/address_normalization_manager.cc106
-rw-r--r--chromium/components/autofill/core/browser/address_normalization_manager.h104
-rw-r--r--chromium/components/autofill/core/browser/address_normalization_manager_unittest.cc63
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer.h54
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl.cc189
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl.h61
-rw-r--r--chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc245
-rw-r--r--chromium/components/autofill/core/browser/address_validation_util.cc13
-rw-r--r--chromium/components/autofill/core/browser/address_validation_util_unittest.cc52
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager.cc7
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc11
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.h10
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util_unittest.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc38
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.h14
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments_unittest.cc181
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.cc40
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.h20
-rw-r--r--chromium/components/autofill/core/browser/autofill_field_unittest.cc103
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc158
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h26
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc595
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc11
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc272
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h73
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc899
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.cc95
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.h12
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_unittest.cc195
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc54
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.h6
-rw-r--r--chromium/components/autofill/core/browser/credit_card.cc20
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc50
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h4
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc153
-rw-r--r--chromium/components/autofill/core/browser/form_types.cc26
-rw-r--r--chromium/components/autofill/core/browser/form_types.h26
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc711
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h147
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc1513
-rw-r--r--chromium/components/autofill/core/browser/phone_email_validation_util.cc29
-rw-r--r--chromium/components/autofill/core/browser/phone_email_validation_util_unittest.cc26
-rw-r--r--chromium/components/autofill/core/browser/phone_number_i18n.cc89
-rw-r--r--chromium/components/autofill/core/browser/phone_number_i18n.h20
-rw-r--r--chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc191
-rw-r--r--chromium/components/autofill/core/browser/popup_item_ids.h1
-rw-r--r--chromium/components/autofill/core/browser/proto/server.proto10
-rw-r--r--chromium/components/autofill/core/browser/region_data_loader_impl.h6
-rw-r--r--chromium/components/autofill/core/browser/subkey_requester.cc143
-rw-r--r--chromium/components/autofill/core/browser/subkey_requester.h76
-rw-r--r--chromium/components/autofill/core/browser/subkey_requester_unittest.cc202
-rw-r--r--chromium/components/autofill/core/browser/test_address_normalizer.cc38
-rw-r--r--chromium/components/autofill/core/browser/test_address_normalizer.h47
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.cc15
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.h8
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.h2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.cc11
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc197
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc42
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc42
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h10
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h2
-rw-r--r--chromium/components/autofill/core/common/autofill_pref_names.cc14
-rw-r--r--chromium/components/autofill/core/common/autofill_pref_names.h5
-rw-r--r--chromium/components/autofill/core/common/autofill_regex_constants.cc73
-rw-r--r--chromium/components/autofill/core/common/password_form.cc16
-rw-r--r--chromium/components/autofill/core/common/password_form.h16
-rw-r--r--chromium/components/autofill/core/common/password_generation_util.h6
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc3
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.h1
77 files changed, 6456 insertions, 1272 deletions
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index efd501528ef..73e59c10804 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -14,6 +14,11 @@ static_library("browser") {
"address_field.h",
"address_i18n.cc",
"address_i18n.h",
+ "address_normalization_manager.cc",
+ "address_normalization_manager.h",
+ "address_normalizer.h",
+ "address_normalizer_impl.cc",
+ "address_normalizer_impl.h",
"address_rewriter.cc",
"address_rewriter.h",
"address_rewriter_rules.cc",
@@ -93,6 +98,8 @@ static_library("browser") {
"form_group.h",
"form_structure.cc",
"form_structure.h",
+ "form_types.cc",
+ "form_types.h",
"legal_message_line.cc",
"legal_message_line.h",
"name_field.cc",
@@ -126,6 +133,8 @@ static_library("browser") {
"risk_data_loader.h",
"state_names.cc",
"state_names.h",
+ "subkey_requester.cc",
+ "subkey_requester.h",
"suggestion.cc",
"suggestion.h",
"ui/card_unmask_prompt_controller.h",
@@ -250,6 +259,8 @@ static_library("test_support") {
"data_driven_test.cc",
"data_driven_test.h",
"suggestion_test_helpers.h",
+ "test_address_normalizer.cc",
+ "test_address_normalizer.h",
"test_autofill_client.cc",
"test_autofill_client.h",
"test_autofill_clock.cc",
@@ -326,6 +337,8 @@ source_set("unit_tests") {
"address_combobox_model_unittest.cc",
"address_field_unittest.cc",
"address_i18n_unittest.cc",
+ "address_normalization_manager_unittest.cc",
+ "address_normalizer_impl_unittest.cc",
"address_rewriter_unittest.cc",
"address_unittest.cc",
"address_validation_util_unittest.cc",
@@ -335,6 +348,7 @@ source_set("unit_tests") {
"autofill_data_util_unittest.cc",
"autofill_download_manager_unittest.cc",
"autofill_driver_factory_unittest.cc",
+ "autofill_experiments_unittest.cc",
"autofill_external_delegate_unittest.cc",
"autofill_field_unittest.cc",
"autofill_ie_toolbar_import_win_unittest.cc",
@@ -365,6 +379,7 @@ source_set("unit_tests") {
"phone_number_i18n_unittest.cc",
"phone_number_unittest.cc",
"region_combobox_model_unittest.cc",
+ "subkey_requester_unittest.cc",
"ui/card_unmask_prompt_controller_impl_unittest.cc",
"validation_unittest.cc",
"webdata/autocomplete_sync_bridge_unittest.cc",
diff --git a/chromium/components/autofill/core/browser/address_normalization_manager.cc b/chromium/components/autofill/core/browser/address_normalization_manager.cc
new file mode 100644
index 00000000000..3cd73cec2f1
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalization_manager.cc
@@ -0,0 +1,106 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/address_normalization_manager.h"
+
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+
+namespace {
+constexpr int kAddressNormalizationTimeoutSeconds = 5;
+} // namespace
+
+AddressNormalizationManager::AddressNormalizationManager(
+ AddressNormalizer* address_normalizer,
+ const std::string& default_country_code)
+ : default_country_code_(default_country_code),
+ address_normalizer_(address_normalizer) {
+ DCHECK(autofill::data_util::IsValidCountryCode(default_country_code));
+ DCHECK(address_normalizer_);
+}
+
+AddressNormalizationManager::~AddressNormalizationManager() {}
+
+void AddressNormalizationManager::FinalizePendingRequestsWithCompletionCallback(
+ base::OnceClosure completion_callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!completion_callback_);
+ completion_callback_ = std::move(completion_callback);
+ accepting_requests_ = false;
+ MaybeRunCompletionCallback();
+}
+
+void AddressNormalizationManager::StartNormalizingAddress(
+ AutofillProfile* profile) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(accepting_requests_) << "FinalizeWithCompletionCallback has been "
+ "called, cannot normalize more addresses";
+
+ delegates_.push_back(
+ base::MakeUnique<NormalizerDelegate>(this, address_normalizer_, profile));
+}
+
+void AddressNormalizationManager::MaybeRunCompletionCallback() {
+ if (accepting_requests_ || !completion_callback_)
+ return;
+
+ for (const auto& delegate : delegates_) {
+ if (!delegate->has_completed())
+ return;
+ }
+
+ // We're no longer accepting requests, and all the delegates have completed.
+ // Now's the time to run the completion callback.
+ std::move(completion_callback_).Run();
+
+ // Start accepting requests after the completion callback has run.
+ delegates_.clear();
+ accepting_requests_ = true;
+}
+
+AddressNormalizationManager::NormalizerDelegate::NormalizerDelegate(
+ AddressNormalizationManager* owner,
+ AddressNormalizer* address_normalizer,
+ AutofillProfile* profile)
+ : owner_(owner), profile_(profile) {
+ DCHECK(owner_);
+ DCHECK(profile_);
+
+ std::string country_code =
+ base::UTF16ToUTF8(profile_->GetRawInfo(ADDRESS_HOME_COUNTRY));
+ if (!autofill::data_util::IsValidCountryCode(country_code))
+ country_code = owner_->default_country_code_;
+
+ address_normalizer->StartAddressNormalization(
+ *profile_, country_code, kAddressNormalizationTimeoutSeconds, this);
+}
+
+void AddressNormalizationManager::NormalizerDelegate::OnAddressNormalized(
+ const AutofillProfile& normalized_profile) {
+ OnCompletion(normalized_profile);
+}
+
+void AddressNormalizationManager::NormalizerDelegate::OnCouldNotNormalize(
+ const AutofillProfile& profile) {
+ // Since the phone number is formatted in either case, this profile should
+ // be used.
+ OnCompletion(profile);
+}
+
+void AddressNormalizationManager::NormalizerDelegate::OnCompletion(
+ const AutofillProfile& profile) {
+ DCHECK(!has_completed_);
+ has_completed_ = true;
+ *profile_ = profile;
+ owner_->MaybeRunCompletionCallback();
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/address_normalization_manager.h b/chromium/components/autofill/core/browser/address_normalization_manager.h
new file mode 100644
index 00000000000..f4be49831d6
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalization_manager.h
@@ -0,0 +1,104 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZATION_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZATION_MANAGER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/threading/thread_checker.h"
+#include "components/autofill/core/browser/address_normalizer.h"
+
+namespace autofill {
+
+class AddressNormalizer;
+class AutofillProfile;
+
+// Class to handle multiple concurrent address normalization requests. This
+// class is not thread-safe.
+class AddressNormalizationManager {
+ public:
+ // Initializes an AddressNormalizationManager. |default_country_code| will be
+ // used if the country code in an AutofillProfile to normalize is not valid.
+ // The AddressNormalizationManager does not own |address_normalizer|.
+ AddressNormalizationManager(AddressNormalizer* address_normalizer,
+ const std::string& default_country_code);
+
+ ~AddressNormalizationManager();
+
+ // Stops accepting normalization requests until all pending requests complete.
+ // If all the address normalization requests have already completed,
+ // |completion_callback| will be called before this method returns. Otherwise,
+ // it will be called as soon as the last pending request completes.
+ void FinalizePendingRequestsWithCompletionCallback(
+ base::OnceClosure completion_callback);
+
+ // Normalizes the address in |profile|. This may or may not happen
+ // asynchronously. On completion, the address in |profile| will be updated
+ // with the normalized address.
+ void StartNormalizingAddress(AutofillProfile* profile);
+
+ private:
+ // Implements the payments::AddressNormalizer::Delegate interface, and
+ // notifies its parent AddressNormalizationManager when normalization has
+ // completed.
+ class NormalizerDelegate : public autofill::AddressNormalizer::Delegate {
+ public:
+ // |owner| is the parent AddressNormalizationManager, |address_normalizer|
+ // is a pointer to an instance of AddressNormalizer which will handle
+ // normalization of |profile|. |profile| will be updated when normalization
+ // is complete.
+ NormalizerDelegate(AddressNormalizationManager* owner,
+ AddressNormalizer* address_normalizer,
+ AutofillProfile* profile);
+
+ // Returns whether this delegate has completed or not.
+ bool has_completed() const { return has_completed_; }
+
+ // AddressNormalizer::Delegate:
+ void OnAddressNormalized(
+ const AutofillProfile& normalized_profile) override;
+ void OnCouldNotNormalize(const AutofillProfile& profile) override;
+
+ private:
+ // Helper method that handles when normalization has completed.
+ void OnCompletion(const AutofillProfile& profile);
+
+ bool has_completed_ = false;
+ AddressNormalizationManager* owner_ = nullptr;
+ autofill::AutofillProfile* profile_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(NormalizerDelegate);
+ };
+
+ friend class NormalizerDelegate;
+
+ // Runs the completion callback if all the delegates have completed.
+ void MaybeRunCompletionCallback();
+
+ // Whether the AddressNormalizationManager is still accepting requests or not.
+ bool accepting_requests_ = true;
+
+ // The default country code to use if a profile does not have a valid country.
+ const std::string default_country_code_;
+
+ // The callback to execute when all addresses have been normalized.
+ base::OnceClosure completion_callback_;
+
+ // Storage for all the delegates that handle the normalization requests.
+ std::vector<std::unique_ptr<NormalizerDelegate>> delegates_;
+
+ // An unowned raw pointer to the AddressNormalizer to use.
+ AddressNormalizer* address_normalizer_;
+
+ THREAD_CHECKER(thread_checker_);
+ DISALLOW_COPY_AND_ASSIGN(AddressNormalizationManager);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZATION_MANAGER_H_
diff --git a/chromium/components/autofill/core/browser/address_normalization_manager_unittest.cc b/chromium/components/autofill/core/browser/address_normalization_manager_unittest.cc
new file mode 100644
index 00000000000..ffef4787500
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalization_manager_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/address_normalization_manager.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "components/autofill/core/browser/test_address_normalizer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+class AddressNormalizationManagerTest : public testing::Test {
+ protected:
+ AddressNormalizationManagerTest() {}
+
+ void Initialize(const std::string& country_code) {
+ manager_ = std::make_unique<AddressNormalizationManager>(
+ &address_normalizer_, country_code);
+ }
+
+ void Finalize() {
+ manager_->FinalizePendingRequestsWithCompletionCallback(
+ base::BindOnce(&AddressNormalizationManagerTest::CompletionCallback,
+ base::Unretained(this)));
+ }
+
+ void CompletionCallback() { completion_callback_called_ = true; }
+
+ TestAddressNormalizer address_normalizer_;
+ std::unique_ptr<AddressNormalizationManager> manager_;
+ bool completion_callback_called_ = false;
+};
+
+TEST_F(AddressNormalizationManagerTest, SynchronousResult) {
+ Initialize("US");
+
+ AutofillProfile profile_to_normalize;
+ manager_->StartNormalizingAddress(&profile_to_normalize);
+
+ EXPECT_FALSE(completion_callback_called_);
+ Finalize();
+ EXPECT_TRUE(completion_callback_called_);
+}
+
+TEST_F(AddressNormalizationManagerTest, AsynchronousResult) {
+ Initialize("US");
+ address_normalizer_.DelayNormalization();
+
+ AutofillProfile profile_to_normalize;
+ manager_->StartNormalizingAddress(&profile_to_normalize);
+
+ EXPECT_FALSE(completion_callback_called_);
+ Finalize();
+ EXPECT_FALSE(completion_callback_called_);
+ address_normalizer_.CompleteAddressNormalization();
+ EXPECT_TRUE(completion_callback_called_);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/address_normalizer.h b/chromium/components/autofill/core/browser/address_normalizer.h
new file mode 100644
index 00000000000..81010da2cd2
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalizer.h
@@ -0,0 +1,54 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
+
+#include <string>
+
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+
+namespace autofill {
+
+class AutofillProfile;
+
+// A class used to normalize addresses.
+class AddressNormalizer : public autofill::LoadRulesListener {
+ public:
+ // The interface for the normalization delegates.
+ class Delegate {
+ public:
+ virtual void OnAddressNormalized(
+ const AutofillProfile& normalized_profile) = 0;
+
+ virtual void OnCouldNotNormalize(const AutofillProfile& profile) = 0;
+
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ // Start loading the validation rules for the specified |region_code|.
+ virtual void LoadRulesForRegion(const std::string& region_code) = 0;
+
+ // Returns whether the rules for the specified |region_code| have finished
+ // loading.
+ virtual bool AreRulesLoadedForRegion(const std::string& region_code) = 0;
+
+ // Starts the normalization of the |profile| based on the |region_code|. The
+ // normalized profile will be returned to the |requester| possibly
+ // asynchronously. If the normalization is not completed in |timeout_seconds|
+ // the requester will be informed and the request cancelled. This value should
+ // be greater or equal to 0, for which it means that the normalization should
+ // happen synchronously, or not at all if the rules are not already loaded.
+ // Will start loading the rules for the |region_code| if they had not started
+ // loading.
+ virtual void StartAddressNormalization(const AutofillProfile& profile,
+ const std::string& region_code,
+ int timeout_seconds,
+ Delegate* requester) = 0;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_H_
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl.cc b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
new file mode 100644
index 00000000000..d7240126b28
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl.cc
@@ -0,0 +1,189 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/address_normalizer_impl.h"
+
+#include <stddef.h>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/cancelable_callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#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/address_i18n.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+
+namespace autofill {
+
+namespace {
+
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+
+} // namespace
+
+class AddressNormalizerImpl::NormalizationRequest {
+ public:
+ // The |delegate| and |address_validator| need to outlive this Request.
+ NormalizationRequest(const AutofillProfile& profile,
+ const std::string& region_code,
+ int timeout_seconds,
+ AddressNormalizer::Delegate* delegate,
+ AddressValidator* address_validator)
+ : profile_(profile),
+ region_code_(region_code),
+ delegate_(delegate),
+ address_validator_(address_validator),
+ has_responded_(false),
+ on_timeout_(base::Bind(&NormalizationRequest::OnRulesLoaded,
+ base::Unretained(this),
+ false)) {
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, on_timeout_.callback(),
+ base::TimeDelta::FromSeconds(timeout_seconds));
+ }
+
+ ~NormalizationRequest() {}
+
+ void OnRulesLoaded(bool success) {
+ on_timeout_.Cancel();
+
+ // Check if the timeout happened before the rules were loaded.
+ if (has_responded_)
+ return;
+ has_responded_ = true;
+
+ // In either case, format the phone number.
+ FormatPhoneNumberForResponse();
+
+ if (!success) {
+ delegate_->OnCouldNotNormalize(profile_);
+ return;
+ }
+
+ // The rules should be loaded.
+ DCHECK(address_validator_->AreRulesLoadedForRegion(region_code_));
+
+ // Create the AddressData from the profile.
+ ::i18n::addressinput::AddressData address_data =
+ *autofill::i18n::CreateAddressDataFromAutofillProfile(profile_,
+ region_code_);
+
+ // Normalize the address.
+ if (address_validator_ &&
+ address_validator_->NormalizeAddress(&address_data)) {
+ profile_.SetRawInfo(ADDRESS_HOME_STATE,
+ base::UTF8ToUTF16(address_data.administrative_area));
+ profile_.SetRawInfo(ADDRESS_HOME_CITY,
+ base::UTF8ToUTF16(address_data.locality));
+ profile_.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ base::UTF8ToUTF16(address_data.dependent_locality));
+ }
+
+ delegate_->OnAddressNormalized(profile_);
+ }
+
+ private:
+ // Tries to format the phone number to the E.164 format to send in the Payment
+ // Response, as defined in the Payment Request spec. Keeps the original
+ // if it cannot be formatted. More info at:
+ // https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm
+ void FormatPhoneNumberForResponse() {
+ const std::string original_number = base::UTF16ToUTF8(
+ profile_.GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), region_code_));
+
+ std::string formatted_number =
+ autofill::i18n::FormatPhoneForResponse(original_number, region_code_);
+
+ profile_.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16(formatted_number));
+ }
+
+ AutofillProfile profile_;
+ std::string region_code_;
+ AddressNormalizer::Delegate* delegate_;
+ AddressValidator* address_validator_;
+
+ bool has_responded_;
+ base::CancelableCallback<void()> on_timeout_;
+
+ DISALLOW_COPY_AND_ASSIGN(NormalizationRequest);
+};
+
+AddressNormalizerImpl::AddressNormalizerImpl(std::unique_ptr<Source> source,
+ std::unique_ptr<Storage> storage)
+ : address_validator_(std::move(source), std::move(storage), this) {}
+
+AddressNormalizerImpl::~AddressNormalizerImpl() {}
+
+void AddressNormalizerImpl::LoadRulesForRegion(const std::string& region_code) {
+ address_validator_.LoadRules(region_code);
+}
+
+bool AddressNormalizerImpl::AreRulesLoadedForRegion(
+ const std::string& region_code) {
+ return address_validator_.AreRulesLoadedForRegion(region_code);
+}
+
+void AddressNormalizerImpl::StartAddressNormalization(
+ const AutofillProfile& profile,
+ const std::string& region_code,
+ int timeout_seconds,
+ AddressNormalizer::Delegate* requester) {
+ DCHECK_GE(timeout_seconds, 0);
+
+ std::unique_ptr<NormalizationRequest> request =
+ std::make_unique<NormalizationRequest>(profile, region_code,
+ timeout_seconds, requester,
+ &address_validator_);
+
+ // If the rules are already loaded for |region_code|, the |request| will call
+ // back to the delegate (|requester|) synchronously.
+ if (AreRulesLoadedForRegion(region_code)) {
+ request->OnRulesLoaded(true);
+ return;
+ }
+
+ // Setup the variables so the profile gets normalized when the rules have
+ // finished loading.
+ auto it = pending_normalization_.find(region_code);
+ if (it == pending_normalization_.end()) {
+ // If no entry exists yet, create the entry and assign it to |it|.
+ it = pending_normalization_
+ .insert(std::make_pair(
+ region_code,
+ std::vector<std::unique_ptr<NormalizationRequest>>()))
+ .first;
+ }
+
+ it->second.push_back(std::move(request));
+
+ // Start loading the rules for that region. If the rules were already in the
+ // process of being loaded, this call will do nothing.
+ LoadRulesForRegion(region_code);
+}
+
+void AddressNormalizerImpl::OnAddressValidationRulesLoaded(
+ const std::string& region_code,
+ bool success) {
+ // Check if an address normalization is pending.
+ auto it = pending_normalization_.find(region_code);
+ if (it != pending_normalization_.end()) {
+ for (size_t i = 0; i < it->second.size(); ++i) {
+ it->second[i]->OnRulesLoaded(success);
+ }
+ pending_normalization_.erase(it);
+ }
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl.h b/chromium/components/autofill/core/browser/address_normalizer_impl.h
new file mode 100644
index 00000000000..3d40ea04823
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl.h
@@ -0,0 +1,61 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/autofill/core/browser/address_normalizer.h"
+
+namespace i18n {
+namespace addressinput {
+class Source;
+class Storage;
+} // namespace addressinput
+} // namespace i18n
+
+namespace autofill {
+
+class AutofillProfile;
+
+// A class used to normalize addresses.
+class AddressNormalizerImpl : public AddressNormalizer {
+ public:
+ AddressNormalizerImpl(std::unique_ptr<::i18n::addressinput::Source> source,
+ std::unique_ptr<::i18n::addressinput::Storage> storage);
+ ~AddressNormalizerImpl() override;
+
+ // AddressNormalizer implementation.
+ void LoadRulesForRegion(const std::string& region_code) override;
+ bool AreRulesLoadedForRegion(const std::string& region_code) override;
+ void StartAddressNormalization(const AutofillProfile& profile,
+ const std::string& region_code,
+ int timeout_seconds,
+ Delegate* requester) override;
+
+ private:
+ // Called when the validation rules for the |region_code| have finished
+ // loading. Implementation of the LoadRulesListener interface.
+ void OnAddressValidationRulesLoaded(const std::string& region_code,
+ bool success) override;
+
+ // Map associating a region code to pending normalizations.
+ class NormalizationRequest;
+ std::map<std::string, std::vector<std::unique_ptr<NormalizationRequest>>>
+ pending_normalization_;
+
+ // The address validator used to normalize addresses.
+ AddressValidator address_validator_;
+
+ DISALLOW_COPY_AND_ASSIGN(AddressNormalizerImpl);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ADDRESS_NORMALIZER_IMPL_H_
diff --git a/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc b/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc
new file mode 100644
index 00000000000..7ec31cab1ca
--- /dev/null
+++ b/chromium/components/autofill/core/browser/address_normalizer_impl_unittest.cc
@@ -0,0 +1,245 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/address_normalizer_impl.h"
+
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+#include "third_party/libaddressinput/src/cpp/test/testdata_source.h"
+
+namespace autofill {
+namespace {
+
+using ::i18n::addressinput::NullStorage;
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+using ::i18n::addressinput::TestdataSource;
+
+const char kLocale[] = "US";
+
+// The requester of normalization for this test.
+class NormalizationDelegate : public AddressNormalizer::Delegate {
+ public:
+ NormalizationDelegate()
+ : normalized_called_(false), not_normalized_called_(false) {}
+
+ ~NormalizationDelegate() override {}
+
+ void OnAddressNormalized(const AutofillProfile& profile) override {
+ normalized_called_ = true;
+ profile_ = profile;
+ }
+
+ void OnCouldNotNormalize(const AutofillProfile& profile) override {
+ not_normalized_called_ = true;
+ profile_ = profile;
+ }
+
+ bool normalized_called() const { return normalized_called_; }
+
+ bool not_normalized_called() const { return not_normalized_called_; }
+
+ const AutofillProfile& profile() const { return profile_; }
+
+ private:
+ bool normalized_called_;
+ bool not_normalized_called_;
+ AutofillProfile profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(NormalizationDelegate);
+};
+
+// Used to load region rules for this test.
+class ChromiumTestdataSource : public TestdataSource {
+ public:
+ ChromiumTestdataSource() : TestdataSource(true) {}
+
+ ~ChromiumTestdataSource() override {}
+
+ // For this test, only load the rules for the kLocale.
+ void Get(const std::string& key, const Callback& data_ready) const override {
+ data_ready(
+ true, key,
+ new std::string("{\"data/US\": "
+ "{\"id\":\"data/US\",\"key\":\"US\",\"name\":\"UNITED "
+ "STATES\",\"lang\":\"en\",\"languages\":\"en\"}}"));
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromiumTestdataSource);
+};
+
+// A test subclass of the AddressNormalizerImpl. Used to simulate rules not
+// being loaded.
+class TestAddressNormalizer : public AddressNormalizerImpl {
+ public:
+ TestAddressNormalizer(std::unique_ptr<::i18n::addressinput::Source> source,
+ std::unique_ptr<::i18n::addressinput::Storage> storage)
+ : AddressNormalizerImpl(std::move(source), std::move(storage)),
+ should_load_rules_(true) {}
+
+ ~TestAddressNormalizer() override {}
+
+ void ShouldLoadRules(bool should_load_rules) {
+ should_load_rules_ = should_load_rules;
+ }
+
+ void LoadRulesForRegion(const std::string& region_code) override {
+ if (should_load_rules_) {
+ AddressNormalizerImpl::LoadRulesForRegion(region_code);
+ }
+ }
+
+ private:
+ bool should_load_rules_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAddressNormalizer);
+};
+
+} // namespace
+
+class AddressNormalizerTest : public testing::Test {
+ protected:
+ AddressNormalizerTest()
+ : normalizer_(new TestAddressNormalizer(
+ std::unique_ptr<Source>(new ChromiumTestdataSource),
+ std::unique_ptr<Storage>(new NullStorage))) {}
+
+ ~AddressNormalizerTest() override {}
+
+ const std::unique_ptr<TestAddressNormalizer> normalizer_;
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AddressNormalizerTest);
+};
+
+// Tests that rules are not loaded by default.
+TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_NotLoaded) {
+ EXPECT_FALSE(normalizer_->AreRulesLoadedForRegion(kLocale));
+}
+
+// Tests that the rules are loaded correctly.
+TEST_F(AddressNormalizerTest, AreRulesLoadedForRegion_Loaded) {
+ normalizer_->LoadRulesForRegion(kLocale);
+ EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+}
+
+// Tests that if the rules are loaded before the normalization is started, the
+// normalized profile will be returned to the delegate synchronously.
+TEST_F(AddressNormalizerTest, StartNormalization_RulesLoaded) {
+ NormalizationDelegate delegate;
+ AutofillProfile profile;
+
+ // Load the rules.
+ normalizer_->LoadRulesForRegion(kLocale);
+ EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+
+ // Start the normalization.
+ normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+ // Since the rules are already loaded, the address should be normalized
+ // synchronously.
+ EXPECT_TRUE(delegate.normalized_called());
+ EXPECT_FALSE(delegate.not_normalized_called());
+}
+
+// Tests that if the rules are not loaded before the normalization and cannot be
+// loaded after, the address will not be normalized and the delegate will be
+// notified.
+TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillNotLoad) {
+ NormalizationDelegate delegate;
+ AutofillProfile profile;
+
+ // Make sure the rules will not be loaded in the StartAddressNormalization
+ // call.
+ normalizer_->ShouldLoadRules(false);
+
+ // Start the normalization.
+ normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+ // Let the timeout execute.
+ scoped_task_environment_.RunUntilIdle();
+
+ // Since the rules are never loaded and the timeout is 0, the delegate should
+ // get notified that the address could not be normalized.
+ EXPECT_FALSE(delegate.normalized_called());
+ EXPECT_TRUE(delegate.not_normalized_called());
+}
+
+// Tests that if the rules are not loaded before the call to
+// StartAddressNormalization, they will be loaded in the call.
+TEST_F(AddressNormalizerTest, StartNormalization_RulesNotLoaded_WillLoad) {
+ NormalizationDelegate delegate;
+ AutofillProfile profile;
+
+ // Start the normalization.
+ normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+ // Even if the rules are not loaded before the call to
+ // StartAddressNormalization, they should get loaded in the call. Since our
+ // test source is synchronous, the normalization will happen synchronously
+ // too.
+ EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+ EXPECT_TRUE(delegate.normalized_called());
+ EXPECT_FALSE(delegate.not_normalized_called());
+}
+
+// Tests that the phone number is formatted when the address is normalized.
+TEST_F(AddressNormalizerTest, FormatPhone_AddressNormalized) {
+ NormalizationDelegate delegate;
+ AutofillProfile profile;
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16("(515) 123-1234"));
+
+ // Load the rules.
+ normalizer_->LoadRulesForRegion(kLocale);
+ EXPECT_TRUE(normalizer_->AreRulesLoadedForRegion(kLocale));
+
+ // Start the normalization.
+ normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+ // Make sure the address was normalized.
+ EXPECT_TRUE(delegate.normalized_called());
+
+ // Expect that the phone number was formatted.
+ EXPECT_EQ("+15151231234", base::UTF16ToUTF8(delegate.profile().GetRawInfo(
+ PHONE_HOME_WHOLE_NUMBER)));
+}
+
+// Tests that the phone number is formatted even when the address is not
+// normalized.
+TEST_F(AddressNormalizerTest, FormatPhone_AddressNotNormalized) {
+ NormalizationDelegate delegate;
+ AutofillProfile profile;
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16("515-123-1234"));
+
+ // Make sure the rules will not be loaded in the StartAddressNormalization
+ // call.
+ normalizer_->ShouldLoadRules(false);
+
+ // Start the normalization.
+ normalizer_->StartAddressNormalization(profile, kLocale, 0, &delegate);
+
+ // Let the timeout execute.
+ scoped_task_environment_.RunUntilIdle();
+
+ // Make sure the address was not normalized.
+ EXPECT_TRUE(delegate.not_normalized_called());
+
+ // Expect that the phone number was formatted.
+ EXPECT_EQ("+15151231234", base::UTF16ToUTF8(delegate.profile().GetRawInfo(
+ PHONE_HOME_WHOLE_NUMBER)));
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/address_validation_util.cc b/chromium/components/autofill/core/browser/address_validation_util.cc
index 76b056dc178..0f1a01eadab 100644
--- a/chromium/components/autofill/core/browser/address_validation_util.cc
+++ b/chromium/components/autofill/core/browser/address_validation_util.cc
@@ -97,6 +97,15 @@ void InitializeAddressFromProfile(const AutofillProfile& profile,
base::UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP));
}
+void SetEmptyValidityIfEmpty(AutofillProfile* profile) {
+ if (profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty())
+ profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY);
+ if (profile->GetRawInfo(ADDRESS_HOME_STATE).empty())
+ profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY);
+ if (profile->GetRawInfo(ADDRESS_HOME_ZIP).empty())
+ profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY);
+}
+
} // namespace
namespace address_validation_util {
@@ -116,6 +125,7 @@ AutofillProfile::ValidityState ValidateAddress(
// unclear which, if any, rule should apply.
SetAllValidityStates(profile, AutofillProfile::UNVALIDATED);
SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::INVALID);
+ SetEmptyValidityIfEmpty(profile);
return AutofillProfile::INVALID;
}
@@ -148,6 +158,9 @@ AutofillProfile::ValidityState ValidateAddress(
profile_validity = AutofillProfile::INVALID;
}
}
+
+ SetEmptyValidityIfEmpty(profile);
+
return profile_validity;
}
diff --git a/chromium/components/autofill/core/browser/address_validation_util_unittest.cc b/chromium/components/autofill/core/browser/address_validation_util_unittest.cc
index 604995c8124..172b7f899eb 100644
--- a/chromium/components/autofill/core/browser/address_validation_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/address_validation_util_unittest.cc
@@ -127,6 +127,20 @@ TEST_F(AutofillAddressValidationTest, ValidateFullProfile_CountryCodeNotExist) {
profile.GetValidityState(ADDRESS_HOME_ZIP));
}
+TEST_F(AutofillAddressValidationTest, ValidateFullProfile_EmptyCountryCode) {
+ // This is a profile with no country code, therefore it cannot be validated
+ // according to ValidationTestDataSource.
+ AutofillProfile profile(autofill::test::GetFullValidProfile());
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(""));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile));
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(AutofillProfile::UNVALIDATED,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+ EXPECT_EQ(AutofillProfile::UNVALIDATED,
+ profile.GetValidityState(ADDRESS_HOME_ZIP));
+}
+
TEST_F(AutofillAddressValidationTest, ValidateFullProfile_RuleNotAvailable) {
// This is a profile with valid country code, but the rule is not available in
// the ValidationTestDataSource.
@@ -155,6 +169,18 @@ TEST_F(AutofillAddressValidationTest, ValidateAddress_AdminAreaNotExists) {
EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP));
}
+TEST_F(AutofillAddressValidationTest, ValidateAddress_EmptyAdminArea) {
+ AutofillProfile profile(autofill::test::GetFullValidProfile());
+ profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(""));
+
+ EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile));
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+ EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP));
+}
+
TEST_F(AutofillAddressValidationTest, ValidateAddress_AdminAreaFullName) {
const std::string admin_area = "Quebec";
AutofillProfile profile(autofill::test::GetFullValidProfile());
@@ -223,6 +249,32 @@ TEST_F(AutofillAddressValidationTest, ValidateAddress_InvalidZip) {
profile.GetValidityState(ADDRESS_HOME_ZIP));
}
+TEST_F(AutofillAddressValidationTest, ValidateAddress_EmptyZip) {
+ AutofillProfile profile(autofill::test::GetFullValidProfile());
+ profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(""));
+
+ EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile));
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+ EXPECT_EQ(AutofillProfile::EMPTY, profile.GetValidityState(ADDRESS_HOME_ZIP));
+}
+
+TEST_F(AutofillAddressValidationTest,
+ ValidateFullProfile_EmptyCountryCodeAreaAndZip) {
+ AutofillProfile profile(autofill::test::GetFullValidProfile());
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(""));
+ profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(""));
+ profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(""));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidateAddressTest(&profile));
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+ EXPECT_EQ(AutofillProfile::EMPTY, profile.GetValidityState(ADDRESS_HOME_ZIP));
+}
+
// TODO(crbug/754727): add tests for a non-default language.
// Ex: Nouveau-Brunswick for Canada.
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
index ec5738c43a5..6683d0ea077 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -6,7 +6,6 @@
#include <vector>
-#include "base/profiler/scoped_tracker.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_client.h"
@@ -141,12 +140,6 @@ void AutocompleteHistoryManager::SendSuggestions(
void AutocompleteHistoryManager::OnWebDataServiceRequestDone(
WebDataServiceBase::Handle h,
std::unique_ptr<WDTypedResult> result) {
- // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
- // fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "422460 AutocompleteHistoryManager::OnWebDataServiceRequestDone"));
-
DCHECK(pending_query_handle_);
pending_query_handle_ = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index 784409dd086..7e0f53bba64 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -12,6 +12,8 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/grit/components_scaled_resources.h"
@@ -442,5 +444,14 @@ bool IsValidCountryCode(const base::string16& country_code) {
return IsValidCountryCode(base::UTF16ToUTF8(country_code));
}
+std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile,
+ const std::string& app_locale) {
+ std::string country_code =
+ base::UTF16ToUTF8(profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
+ if (!IsValidCountryCode(country_code))
+ country_code = AutofillCountry::CountryCodeForLocale(app_locale);
+ return country_code;
+}
+
} // namespace data_util
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.h b/chromium/components/autofill/core/browser/autofill_data_util.h
index 2e3d6fcb1a5..74c972ecdfc 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.h
+++ b/chromium/components/autofill/core/browser/autofill_data_util.h
@@ -9,9 +9,11 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece_forward.h"
-#include "components/autofill/core/browser/autofill_profile.h"
namespace autofill {
+
+class AutofillProfile;
+
namespace data_util {
struct NameParts {
@@ -66,6 +68,12 @@ const char* GetIssuerNetworkForBasicCardIssuerNetwork(
bool IsValidCountryCode(const std::string& country_code);
bool IsValidCountryCode(const base::string16& country_code);
+// Returns a country code to be used when validating this profile. If the
+// profile has a valid country code set, it is returned. If not, a country code
+// associated with |app_locale| is used as a fallback.
+std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile,
+ const std::string& app_locale);
+
} // namespace data_util
} // 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 1a66f8e59a4..d2de5151ec8 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util_unittest.cc
@@ -5,6 +5,7 @@
#include "components/autofill/core/browser/autofill_data_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index e727dd6159e..33ce68a6b77 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -11,7 +11,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/common/autofill_pref_names.h"
@@ -25,16 +24,26 @@
namespace autofill {
+const base::Feature kAutofillAlwaysFillAddresses{
+ "AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAutofillCreateDataForTest{
+ "AutofillCreateDataForTest", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreditCardAssist{
"AutofillCreditCardAssist", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillScanCardholderName{
"AutofillScanCardholderName", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreditCardBankNameDisplay{
"AutofillCreditCardBankNameDisplay", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillCreditCardAblationExperiment{
+ "AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreditCardPopupLayout{
"AutofillCreditCardPopupLayout", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillCreditCardLastUsedDateDisplay{
"AutofillCreditCardLastUsedDateDisplay", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillDeleteDisusedAddresses{
+ "AutofillDeleteDisusedAddresses", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillDeleteDisusedCreditCards{
+ "AutofillDeleteDisusedCreditCards", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillOfferLocalSaveIfServerCardManuallyEntered{
"AutofillOfferLocalSaveIfServerCardManuallyEntered",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -43,6 +52,10 @@ const base::Feature kAutofillRationalizeFieldTypePredictions{
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kAutofillSuppressDisusedAddresses{
"AutofillSuppressDisusedAddresses", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillSuppressDisusedCreditCards{
+ "AutofillSuppressDisusedCreditCards", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillUpstreamAllowAllEmailDomains{
+ "AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillUpstreamRequestCvcIfMissing{
"AutofillUpstreamRequestCvcIfMissing", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillUpstreamShowGoogleLogo{
@@ -51,9 +64,6 @@ const base::Feature kAutofillUpstreamShowNewUi{
"AutofillUpstreamShowNewUi", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillUpstreamUseAutofillProfileComparator{
"AutofillUpstreamUseAutofillProfileComparator",
- base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAutofillUpstreamUseNotRecentlyUsedAutofillProfile{
- "AutofillUpstreamUseNotRecentlyUsedAutofillProfile",
base::FEATURE_DISABLED_BY_DEFAULT};
const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
const char kAutofillCreditCardPopupBackgroundColorKey[] = "background_color";
@@ -67,8 +77,6 @@ const char kAutofillCreditCardPopupIsIconAtStartKey[] =
const char kAutofillPopupMarginKey[] = "margin";
const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[] =
"show_expiration_date";
-const char kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey[] =
- "max_minutes_since_autofill_profile_use";
#if defined(OS_MACOSX)
const base::Feature kCreditCardAutofillTouchBar{
@@ -238,8 +246,12 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
if (user_email.empty())
return false;
std::string domain = gaia::ExtractDomainName(user_email);
- if (!(domain == "googlemail.com" || domain == "gmail.com" ||
- domain == "google.com")) {
+ // If the "allow all email domains" flag is off, restrict credit card upload
+ // only to Google Accounts with @googlemail, @gmail, @google, or @chromium
+ // domains.
+ if (!base::FeatureList::IsEnabled(kAutofillUpstreamAllowAllEmailDomains) &&
+ !(domain == "googlemail.com" || domain == "gmail.com" ||
+ domain == "google.com" || domain == "chromium.org")) {
return false;
}
@@ -286,16 +298,6 @@ bool IsAutofillUpstreamShowNewUiExperimentEnabled() {
#endif
}
-base::TimeDelta GetMaxTimeSinceAutofillProfileUseForCardUpload() {
- int value;
- const std::string param_value = variations::GetVariationParamValueByFeature(
- kAutofillUpstreamUseNotRecentlyUsedAutofillProfile,
- kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey);
- if (!param_value.empty() && base::StringToInt(param_value, &value))
- return base::TimeDelta::FromMinutes(value);
- return base::TimeDelta();
-}
-
#if defined(OS_MACOSX)
bool IsCreditCardAutofillTouchBarExperimentEnabled() {
return base::FeatureList::IsEnabled(kCreditCardAutofillTouchBar);
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.h b/chromium/components/autofill/core/browser/autofill_experiments.h
index 6fcc5168320..d00394042c9 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.h
+++ b/chromium/components/autofill/core/browser/autofill_experiments.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/strings/string16.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -26,19 +25,25 @@ namespace autofill {
struct Suggestion;
+extern const base::Feature kAutofillAlwaysFillAddresses;
+extern const base::Feature kAutofillCreateDataForTest;
extern const base::Feature kAutofillCreditCardAssist;
extern const base::Feature kAutofillScanCardholderName;
+extern const base::Feature kAutofillCreditCardAblationExperiment;
extern const base::Feature kAutofillCreditCardBankNameDisplay;
extern const base::Feature kAutofillCreditCardPopupLayout;
extern const base::Feature kAutofillCreditCardLastUsedDateDisplay;
+extern const base::Feature kAutofillDeleteDisusedAddresses;
+extern const base::Feature kAutofillDeleteDisusedCreditCards;
extern const base::Feature kAutofillOfferLocalSaveIfServerCardManuallyEntered;
extern const base::Feature kAutofillRationalizeFieldTypePredictions;
extern const base::Feature kAutofillSuppressDisusedAddresses;
+extern const base::Feature kAutofillSuppressDisusedCreditCards;
+extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
extern const base::Feature kAutofillUpstreamRequestCvcIfMissing;
extern const base::Feature kAutofillUpstreamShowGoogleLogo;
extern const base::Feature kAutofillUpstreamShowNewUi;
extern const base::Feature kAutofillUpstreamUseAutofillProfileComparator;
-extern const base::Feature kAutofillUpstreamUseNotRecentlyUsedAutofillProfile;
extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
extern const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[];
extern const char kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey[];
@@ -136,11 +141,6 @@ bool IsAutofillUpstreamShowGoogleLogoExperimentEnabled();
// new save card bubble/infobar design.
bool IsAutofillUpstreamShowNewUiExperimentEnabled();
-// Returns the maximum time that could have elapsed since an address profile's
-// most recent use for the adress profile to be included in the candidate set
-// for card upload. Returns 0 if the experiment is not enabled.
-base::TimeDelta GetMaxTimeSinceAutofillProfileUseForCardUpload();
-
#if defined(OS_MACOSX)
// Returns whether the Credit Card Autofill Touch Bar experiment is enabled.
bool IsCreditCardAutofillTouchBarExperimentEnabled();
diff --git a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
new file mode 100644
index 00000000000..ef45b490b98
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -0,0 +1,181 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/autofill_experiments.h"
+
+#include "base/test/scoped_command_line.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_switches.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/sync/driver/fake_sync_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+namespace {
+
+class TestSyncService : public syncer::FakeSyncService {
+ public:
+ TestSyncService()
+ : can_sync_start_(true),
+ preferred_data_types_(syncer::ModelTypeSet::All()),
+ is_engine_initialized_(true),
+ is_using_secondary_passphrase_(false) {}
+
+ bool CanSyncStart() const override { return can_sync_start_; }
+
+ syncer::ModelTypeSet GetPreferredDataTypes() const override {
+ return preferred_data_types_;
+ }
+
+ bool IsEngineInitialized() const override { return is_engine_initialized_; }
+
+ bool IsUsingSecondaryPassphrase() const override {
+ return is_using_secondary_passphrase_;
+ }
+
+ void SetCanSyncStart(bool can_sync_start) {
+ can_sync_start_ = can_sync_start;
+ }
+
+ void SetPreferredDataTypes(syncer::ModelTypeSet preferred_data_types) {
+ preferred_data_types_ = preferred_data_types;
+ }
+
+ void SetIsEngineInitialized(bool is_engine_initialized) {
+ is_engine_initialized_ = is_engine_initialized;
+ }
+
+ void SetIsUsingSecondaryPassphrase(bool is_using_secondary_passphrase) {
+ is_using_secondary_passphrase_ = is_using_secondary_passphrase;
+ }
+
+ private:
+ bool can_sync_start_;
+ syncer::ModelTypeSet preferred_data_types_;
+ bool is_engine_initialized_;
+ bool is_using_secondary_passphrase_;
+};
+
+} // namespace
+
+class AutofillExperimentsTest : public testing::Test {
+ public:
+ AutofillExperimentsTest() {}
+
+ protected:
+ void SetUp() override {
+ pref_service_.registry()->RegisterBooleanPref(
+ prefs::kAutofillWalletImportEnabled, true);
+ }
+
+ bool IsCreditCardUploadEnabled() {
+ return IsCreditCardUploadEnabled("john.smith@gmail.com", "Default");
+ }
+
+ bool IsCreditCardUploadEnabled(const std::string& user_email) {
+ return IsCreditCardUploadEnabled(user_email, "Default");
+ }
+
+ bool IsCreditCardUploadEnabled(const std::string& user_email,
+ const std::string& field_trial_value) {
+ base::FieldTrialList field_trial_list(nullptr);
+ base::FieldTrialList::CreateFieldTrial("OfferUploadCreditCards",
+ field_trial_value);
+
+ return autofill::IsCreditCardUploadEnabled(&pref_service_, &sync_service_,
+ user_email);
+ }
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+ TestingPrefServiceSimple pref_service_;
+ TestSyncService sync_service_;
+};
+
+TEST_F(AutofillExperimentsTest, DenyUpload_SyncServiceCannotStart) {
+ sync_service_.SetCanSyncStart(false);
+ EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
+TEST_F(AutofillExperimentsTest,
+ DenyUpload_SyncServiceDoesNotHaveAutofillProfilePreferredDataType) {
+ sync_service_.SetPreferredDataTypes(syncer::ModelTypeSet());
+ EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_SyncServiceEngineNotInitialized) {
+ sync_service_.SetIsEngineInitialized(false);
+ EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
+TEST_F(AutofillExperimentsTest,
+ DenyUpload_SyncServiceUsingSecondaryPassphrase) {
+ sync_service_.SetIsUsingSecondaryPassphrase(true);
+ EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
+TEST_F(AutofillExperimentsTest,
+ DenyUpload_AutofillWalletImportEnabledPrefIsDisabled) {
+ pref_service_.SetBoolean(prefs::kAutofillWalletImportEnabled, false);
+ EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_EmptyUserEmail) {
+ EXPECT_FALSE(IsCreditCardUploadEnabled(""));
+}
+
+TEST_F(AutofillExperimentsTest, AllowUpload_UserEmailWithGoogleDomain) {
+ EXPECT_TRUE(IsCreditCardUploadEnabled("john.smith@gmail.com"));
+ EXPECT_TRUE(IsCreditCardUploadEnabled("googler@google.com"));
+ EXPECT_TRUE(IsCreditCardUploadEnabled("old.school@googlemail.com"));
+ EXPECT_TRUE(IsCreditCardUploadEnabled("code.committer@chromium.org"));
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_UserEmailWithNonGoogleDomain) {
+ EXPECT_FALSE(IsCreditCardUploadEnabled("cool.user@hotmail.com"));
+ EXPECT_FALSE(IsCreditCardUploadEnabled("john.smith@johnsmith.com"));
+ EXPECT_FALSE(IsCreditCardUploadEnabled("fake.googler@google.net"));
+ EXPECT_FALSE(IsCreditCardUploadEnabled("fake.committer@chromium.com"));
+}
+
+TEST_F(AutofillExperimentsTest,
+ AllowUpload_UserEmailWithNonGoogleDomainIfExperimentEnabled) {
+ scoped_feature_list_.InitAndEnableFeature(
+ kAutofillUpstreamAllowAllEmailDomains);
+ EXPECT_TRUE(IsCreditCardUploadEnabled("cool.user@hotmail.com"));
+ EXPECT_TRUE(IsCreditCardUploadEnabled("john.smith@johnsmith.com"));
+ EXPECT_TRUE(IsCreditCardUploadEnabled("fake.googler@google.net"));
+ EXPECT_TRUE(IsCreditCardUploadEnabled("fake.committer@chromium.com"));
+}
+
+TEST_F(AutofillExperimentsTest,
+ AllowUpload_CommandLineSwitchOnEvenIfGroupDisabled) {
+ base::test::ScopedCommandLine scoped_command_line;
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch(
+ switches::kEnableOfferUploadCreditCards);
+ EXPECT_TRUE(IsCreditCardUploadEnabled("john.smith@gmail.com", "Disabled"));
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_CommandLineSwitchOff) {
+ base::test::ScopedCommandLine scoped_command_line;
+ scoped_command_line.GetProcessCommandLine()->AppendSwitch(
+ switches::kDisableOfferUploadCreditCards);
+ EXPECT_FALSE(IsCreditCardUploadEnabled());
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_GroupNameEmpty) {
+ EXPECT_FALSE(IsCreditCardUploadEnabled("john.smith@gmail.com", ""));
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_GroupNameDisabled) {
+ EXPECT_FALSE(IsCreditCardUploadEnabled("john.smith@gmail.com", "Disabled"));
+}
+
+TEST_F(AutofillExperimentsTest, DenyUpload_GroupNameAnythingButDisabled) {
+ EXPECT_TRUE(IsCreditCardUploadEnabled("john.smith@gmail.com", "Enabled"));
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_field.cc b/chromium/components/autofill/core/browser/autofill_field.cc
index af0cddb0fea..eaab80bf791 100644
--- a/chromium/components/autofill/core/browser/autofill_field.cc
+++ b/chromium/components/autofill/core/browser/autofill_field.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/i18n/case_conversion.h"
#include "base/i18n/string_search.h"
#include "base/logging.h"
@@ -16,6 +17,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h"
#include "components/autofill/core/browser/credit_card.h"
@@ -198,15 +200,18 @@ bool FillExpirationMonthSelectControl(const base::string16& value,
if (!StringToInt(value, &month) || month <= 0 || month > 12)
return false;
- // We trim the whitespace and a specific prefix used in AngularJS from the
+ // Trim the whitespace and specific prefixes used in AngularJS from the
// select values before attempting to convert them to months.
std::vector<base::string16> trimmed_values(field->option_values.size());
const base::string16 kNumberPrefix = ASCIIToUTF16("number:");
+ const base::string16 kStringPrefix = ASCIIToUTF16("string:");
for (size_t i = 0; i < field->option_values.size(); ++i) {
base::TrimWhitespace(field->option_values[i], base::TRIM_ALL,
&trimmed_values[i]);
base::ReplaceFirstSubstringAfterOffset(&trimmed_values[i], 0, kNumberPrefix,
ASCIIToUTF16(""));
+ base::ReplaceFirstSubstringAfterOffset(&trimmed_values[i], 0, kStringPrefix,
+ ASCIIToUTF16(""));
}
if (trimmed_values.size() == 12) {
@@ -535,7 +540,7 @@ base::string16 RemoveWhitespace(const base::string16& value) {
} // namespace
AutofillField::AutofillField()
- : server_type_(NO_SERVER_DATA),
+ : overall_server_type_(NO_SERVER_DATA),
heuristic_type_(UNKNOWN_TYPE),
html_type_(HTML_TYPE_UNSPECIFIED),
html_mode_(HTML_MODE_NONE),
@@ -551,7 +556,7 @@ AutofillField::AutofillField(const FormFieldData& field,
const base::string16& unique_name)
: FormFieldData(field),
unique_name_(unique_name),
- server_type_(NO_SERVER_DATA),
+ overall_server_type_(NO_SERVER_DATA),
heuristic_type_(UNKNOWN_TYPE),
html_type_(HTML_TYPE_UNSPECIFIED),
html_mode_(HTML_MODE_NONE),
@@ -578,12 +583,12 @@ void AutofillField::set_heuristic_type(ServerFieldType type) {
}
}
-void AutofillField::set_server_type(ServerFieldType type) {
+void AutofillField::set_overall_server_type(ServerFieldType type) {
// Chrome no longer supports fax numbers, but the server still does.
if (type >= PHONE_FAX_NUMBER && type <= PHONE_FAX_WHOLE_NUMBER)
return;
- server_type_ = type;
+ overall_server_type_ = type;
}
void AutofillField::SetHtmlType(HtmlFieldType type, HtmlFieldMode mode) {
@@ -601,11 +606,11 @@ void AutofillField::SetHtmlType(HtmlFieldType type, HtmlFieldMode mode) {
void AutofillField::SetTypeTo(ServerFieldType type) {
if (type == UNKNOWN_TYPE || type == NO_SERVER_DATA) {
heuristic_type_ = UNKNOWN_TYPE;
- server_type_ = NO_SERVER_DATA;
- } else if (server_type_ == NO_SERVER_DATA) {
+ overall_server_type_ = NO_SERVER_DATA;
+ } else if (overall_server_type_ == NO_SERVER_DATA) {
heuristic_type_ = type;
} else {
- server_type_ = type;
+ overall_server_type_ = type;
}
}
@@ -617,26 +622,26 @@ AutofillType AutofillField::Type() const {
return AutofillType(html_type_, html_mode_);
}
- if (server_type_ != NO_SERVER_DATA) {
+ if (overall_server_type_ != NO_SERVER_DATA) {
// See http://crbug.com/429236 for background on why we might not always
// believe the server.
// TODO(http://crbug.com/589129) investigate how well the server is doing in
// regard to credit card predictions.
bool believe_server =
- !(server_type_ == NAME_FULL &&
+ !(overall_server_type_ == NAME_FULL &&
heuristic_type_ == CREDIT_CARD_NAME_FULL) &&
- !(server_type_ == CREDIT_CARD_NAME_FULL &&
+ !(overall_server_type_ == CREDIT_CARD_NAME_FULL &&
heuristic_type_ == NAME_FULL) &&
- !(server_type_ == NAME_FIRST &&
+ !(overall_server_type_ == NAME_FIRST &&
heuristic_type_ == CREDIT_CARD_NAME_FIRST) &&
- !(server_type_ == NAME_LAST &&
+ !(overall_server_type_ == NAME_LAST &&
heuristic_type_ == CREDIT_CARD_NAME_LAST) &&
// CVC is sometimes type="password", which tricks the server.
// See http://crbug.com/469007
- !(AutofillType(server_type_).group() == PASSWORD_FIELD &&
+ !(AutofillType(overall_server_type_).group() == PASSWORD_FIELD &&
heuristic_type_ == CREDIT_CARD_VERIFICATION_CODE);
if (believe_server)
- return AutofillType(server_type_);
+ return AutofillType(overall_server_type_);
}
return AutofillType(heuristic_type_);
@@ -668,7 +673,8 @@ bool AutofillField::FillFormField(const AutofillField& field,
// Don't fill if autocomplete=off is set on |field| on desktop for non credit
// card related fields.
- if (!field.should_autocomplete && IsDesktopPlatform() &&
+ if (!base::FeatureList::IsEnabled(kAutofillAlwaysFillAddresses) &&
+ !field.should_autocomplete && IsDesktopPlatform() &&
(type.group() != CREDIT_CARD)) {
return false;
}
@@ -778,7 +784,7 @@ int AutofillField::FindShortestSubstringMatchInSelect(
}
bool AutofillField::IsCreditCardPrediction() const {
- return AutofillType(server_type_).group() == CREDIT_CARD ||
+ return AutofillType(overall_server_type_).group() == CREDIT_CARD ||
AutofillType(heuristic_type_).group() == CREDIT_CARD;
}
diff --git a/chromium/components/autofill/core/browser/autofill_field.h b/chromium/components/autofill/core/browser/autofill_field.h
index edfb606627b..8d4438ace13 100644
--- a/chromium/components/autofill/core/browser/autofill_field.h
+++ b/chromium/components/autofill/core/browser/autofill_field.h
@@ -36,7 +36,11 @@ class AutofillField : public FormFieldData {
const std::string& section() const { return section_; }
ServerFieldType heuristic_type() const { return heuristic_type_; }
- ServerFieldType server_type() const { return server_type_; }
+ ServerFieldType overall_server_type() const { return overall_server_type_; }
+ const std::vector<AutofillQueryResponseContents::Field::FieldPrediction>&
+ server_predictions() const {
+ return server_predictions_;
+ }
HtmlFieldType html_type() const { return html_type_; }
HtmlFieldMode html_mode() const { return html_mode_; }
const ServerFieldTypeSet& possible_types() const { return possible_types_; }
@@ -47,7 +51,12 @@ class AutofillField : public FormFieldData {
// Setters for the detected type and section for this field.
void set_section(const std::string& section) { section_ = section; }
void set_heuristic_type(ServerFieldType type);
- void set_server_type(ServerFieldType type);
+ void set_overall_server_type(ServerFieldType type);
+ void set_server_predictions(
+ const std::vector<AutofillQueryResponseContents::Field::FieldPrediction>
+ predictions) {
+ server_predictions_ = std::move(predictions);
+ }
void set_possible_types(const ServerFieldTypeSet& possible_types) {
possible_types_ = possible_types;
}
@@ -159,7 +168,12 @@ class AutofillField : public FormFieldData {
std::string section_;
// The type of the field, as determined by the Autofill server.
- ServerFieldType server_type_;
+ ServerFieldType overall_server_type_;
+
+ // The possible types of the field, as determined by the Autofill server,
+ // including |overall_server_type_| as the first item.
+ std::vector<AutofillQueryResponseContents::Field::FieldPrediction>
+ server_predictions_;
// The type of the field, as determined by the local heuristics.
ServerFieldType heuristic_type_;
diff --git a/chromium/components/autofill/core/browser/autofill_field_unittest.cc b/chromium/components/autofill/core/browser/autofill_field_unittest.cc
index ef6b2e87bea..1d30b269d7e 100644
--- a/chromium/components/autofill/core/browser/autofill_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_field_unittest.cc
@@ -10,6 +10,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/country_names.h"
@@ -118,7 +120,7 @@ class AutofillFieldTest : public testing::Test {
TEST_F(AutofillFieldTest, Type) {
AutofillField field;
- ASSERT_EQ(NO_SERVER_DATA, field.server_type());
+ ASSERT_EQ(NO_SERVER_DATA, field.overall_server_type());
ASSERT_EQ(UNKNOWN_TYPE, field.heuristic_type());
// |server_type_| is NO_SERVER_DATA, so |heuristic_type_| is returned.
@@ -130,12 +132,12 @@ TEST_F(AutofillFieldTest, Type) {
EXPECT_EQ(NAME, field.Type().group());
// Set the server type and check it.
- field.set_server_type(ADDRESS_BILLING_LINE1);
+ field.set_overall_server_type(ADDRESS_BILLING_LINE1);
EXPECT_EQ(ADDRESS_HOME_LINE1, field.Type().GetStorableType());
EXPECT_EQ(ADDRESS_BILLING, field.Type().group());
// Remove the server type to make sure the heuristic type is preserved.
- field.set_server_type(NO_SERVER_DATA);
+ field.set_overall_server_type(NO_SERVER_DATA);
EXPECT_EQ(NAME_FIRST, field.Type().GetStorableType());
EXPECT_EQ(NAME, field.Type().group());
}
@@ -171,18 +173,18 @@ TEST_F(AutofillFieldTest, Type_CreditCardOverrideHtml_ServerPredicitons) {
field.SetHtmlType(HTML_TYPE_UNRECOGNIZED, HTML_MODE_NONE);
// A credit card server prediction overrides the unrecognized type.
- field.set_server_type(CREDIT_CARD_NUMBER);
+ field.set_overall_server_type(CREDIT_CARD_NUMBER);
EXPECT_EQ(CREDIT_CARD_NUMBER, field.Type().GetStorableType());
// A non credit card server prediction doesn't override the unrecognized
// type.
- field.set_server_type(NAME_FIRST);
+ field.set_overall_server_type(NAME_FIRST);
EXPECT_EQ(UNKNOWN_TYPE, field.Type().GetStorableType());
// A credit card server prediction doesn't override a known specified html
// type.
field.SetHtmlType(HTML_TYPE_NAME, HTML_MODE_NONE);
- field.set_server_type(CREDIT_CARD_NUMBER);
+ field.set_overall_server_type(CREDIT_CARD_NUMBER);
EXPECT_EQ(NAME_FULL, field.Type().GetStorableType());
}
@@ -219,7 +221,7 @@ TEST_F(AutofillFieldTest, FieldSignatureAsStr) {
EXPECT_EQ("502192749", field.FieldSignatureAsStr());
// Server type does not affect FieldSignature.
- field.set_server_type(NAME_LAST);
+ field.set_overall_server_type(NAME_LAST);
EXPECT_EQ("502192749", field.FieldSignatureAsStr());
}
@@ -236,12 +238,12 @@ TEST_F(AutofillFieldTest, IsFieldFillable) {
// Only server type is set.
field.set_heuristic_type(UNKNOWN_TYPE);
- field.set_server_type(NAME_LAST);
+ field.set_overall_server_type(NAME_LAST);
EXPECT_TRUE(field.IsFieldFillable());
// Both types set.
field.set_heuristic_type(NAME_FIRST);
- field.set_server_type(NAME_LAST);
+ field.set_overall_server_type(NAME_LAST);
EXPECT_TRUE(field.IsFieldFillable());
// Field has autocomplete="off" set. Since autofill was able to make a
@@ -251,8 +253,12 @@ TEST_F(AutofillFieldTest, IsFieldFillable) {
}
// Verify that non credit card related fields with the autocomplete attribute
-// set to off don't get filled on desktop.
-TEST_F(AutofillFieldTest, FillFormField_AutocompleteOff_AddressField) {
+// set to off don't get filled on desktop when the feature to Autofill all
+// addresses is disabled.
+TEST_F(AutofillFieldTest, FillFormField_AutocompleteOffRespected_AddressField) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+
AutofillField field;
field.should_autocomplete = false;
@@ -260,7 +266,7 @@ TEST_F(AutofillFieldTest, FillFormField_AutocompleteOff_AddressField) {
AutofillField::FillFormField(field, ASCIIToUTF16("Test"), "en-US", "en-US",
&field);
- // Verifiy that the field is filled on mobile but not on desktop.
+ // Verify that the field is filled on mobile but not on desktop.
if (IsDesktopPlatform()) {
EXPECT_EQ(base::string16(), field.value);
} else {
@@ -268,6 +274,22 @@ TEST_F(AutofillFieldTest, FillFormField_AutocompleteOff_AddressField) {
}
}
+// Verify that non credit card related fields with the autocomplete attribute
+// set to off are filled on desktop when the feature to Autofill all
+// addresses is enabled (default).
+TEST_F(AutofillFieldTest,
+ FillFormField_AutocompleteOffNotRespected_AddressField) {
+ AutofillField field;
+ field.should_autocomplete = false;
+
+ // Non credit card related field.
+ AutofillField::FillFormField(field, ASCIIToUTF16("Test"), "en-US", "en-US",
+ &field);
+
+ // Verify that the field is filled in all circumstances.
+ EXPECT_EQ(ASCIIToUTF16("Test"), field.value);
+}
+
// Verify that credit card related fields with the autocomplete attribute
// set to off get filled.
TEST_F(AutofillFieldTest, FillFormField_AutocompleteOff_CreditCardField) {
@@ -683,13 +705,18 @@ INSTANTIATE_TEST_CASE_P(
{"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10",
"11"},
NotNumericMonthsContentsNoPlaceholder()},
- // The AngularJS framework adds a prefix to number types. Test that it
- // is removed.
+ // The AngularJS framework can add a "number:" prefix to select values.
FillWithExpirationMonthTestCase{
{"number:1", "number:2", "number:3", "number:4", "number:5",
"number:6", "number:7", "number:8", "number:9", "number:10",
"number:11", "number:12"},
NotNumericMonthsContentsNoPlaceholder()},
+ // The AngularJS framework can add a "string:" prefix to select values.
+ FillWithExpirationMonthTestCase{
+ {"string:1", "string:2", "string:3", "string:4", "string:5",
+ "string:6", "string:7", "string:8", "string:9", "string:10",
+ "string:11", "string:12"},
+ NotNumericMonthsContentsNoPlaceholder()},
// Values start at 0 and the first content is a placeholder.
FillWithExpirationMonthTestCase{
{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
@@ -739,7 +766,7 @@ TEST_F(AutofillFieldTest, FillSelectControlWithAbbreviatedMonthName) {
EXPECT_EQ(ASCIIToUTF16("Apr"), field.value);
}
-TEST_F(AutofillFieldTest, FillSelectControlWithFullMonthName) {
+TEST_F(AutofillFieldTest, FillSelectControlWithMonthName) {
std::vector<const char*> kMonthsFull = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December",
@@ -753,7 +780,49 @@ TEST_F(AutofillFieldTest, FillSelectControlWithFullMonthName) {
EXPECT_EQ(ASCIIToUTF16("April"), field.value);
}
-TEST_F(AutofillFieldTest, FillSelectControlWithFrenchMonthName) {
+TEST_F(AutofillFieldTest, FillSelectControlWithMonthNameAndDigits) {
+ std::vector<const char*> kMonthsFullWithDigits = {
+ "January (01)", "February (02)", "March (03)", "April (04)",
+ "May (05)", "June (06)", "July (07)", "August (08)",
+ "September (09)", "October (10)", "November (11)", "December (12)",
+ };
+ AutofillField field;
+ test::CreateTestSelectField(kMonthsFullWithDigits, &field);
+ field.set_heuristic_type(CREDIT_CARD_EXP_MONTH);
+
+ AutofillField::FillFormField(field, ASCIIToUTF16("04"), "en-US", "en-US",
+ &field);
+ EXPECT_EQ(ASCIIToUTF16("April (04)"), field.value);
+}
+
+TEST_F(AutofillFieldTest, FillSelectControlWithMonthNameAndDigits_French) {
+ std::vector<const char*> kMonthsFullWithDigits = {
+ "01 - JANVIER",
+ "02 - FÉVRIER",
+ "03 - MARS",
+ "04 - AVRIL",
+ "05 - MAI",
+ "06 - JUIN",
+ "07 - JUILLET",
+ "08 - AOÛT",
+ "09 - SEPTEMBRE",
+ "10 - OCTOBRE",
+ "11 - NOVEMBRE",
+ "12 - DECEMBRE" /* Intentionally not including accent in DÉCEMBRE */,
+ };
+ AutofillField field;
+ test::CreateTestSelectField(kMonthsFullWithDigits, &field);
+ field.set_heuristic_type(CREDIT_CARD_EXP_MONTH);
+
+ AutofillField::FillFormField(field, ASCIIToUTF16("08"), "fr-FR", "fr-FR",
+ &field);
+ EXPECT_EQ(UTF8ToUTF16("08 - AOÛT"), field.value);
+ AutofillField::FillFormField(field, ASCIIToUTF16("12"), "fr-FR", "fr-FR",
+ &field);
+ EXPECT_EQ(UTF8ToUTF16("12 - DECEMBRE"), field.value);
+}
+
+TEST_F(AutofillFieldTest, FillSelectControlWithMonthName_French) {
std::vector<const char*> kMonthsFrench = {"JANV", "FÉVR.", "MARS",
"décembre"};
AutofillField field;
@@ -873,7 +942,7 @@ TEST_F(AutofillFieldTest, FillStreetAddressTextArea) {
TEST_F(AutofillFieldTest, FillStreetAddressTextField) {
AutofillField field;
field.form_control_type = "text";
- field.set_server_type(ADDRESS_HOME_STREET_ADDRESS);
+ field.set_overall_server_type(ADDRESS_HOME_STREET_ADDRESS);
base::string16 value = ASCIIToUTF16("123 Fake St.\n"
"Apt. 42");
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 31143c2309a..01583656d21 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -33,7 +33,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_restrictions.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_client.h"
@@ -248,6 +247,7 @@ AutofillManager::AutofillManager(
found_cvc_field_(false),
found_value_in_cvc_field_(false),
found_cvc_value_in_non_cvc_field_(false),
+ enable_ablation_logging_(false),
external_delegate_(NULL),
test_delegate_(NULL),
#if defined(OS_ANDROID) || defined(OS_IOS)
@@ -275,8 +275,7 @@ void AutofillManager::RegisterProfilePrefs(
registry->RegisterIntegerPref(
prefs::kAutofillCreditCardSigninPromoImpressionCount, 0);
registry->RegisterBooleanPref(
- prefs::kAutofillEnabled,
- true,
+ prefs::kAutofillEnabled, true,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
registry->RegisterBooleanPref(
prefs::kAutofillProfileUseDatesFixed, false,
@@ -284,6 +283,9 @@ void AutofillManager::RegisterProfilePrefs(
registry->RegisterIntegerPref(
prefs::kAutofillLastVersionDeduped, 0,
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+ registry->RegisterIntegerPref(
+ prefs::kAutofillLastVersionDisusedAddressesDeleted, 0,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
// These choices are made on a per-device basis, so they're not syncable.
registry->RegisterBooleanPref(prefs::kAutofillWalletImportEnabled, true);
registry->RegisterBooleanPref(
@@ -291,6 +293,9 @@ void AutofillManager::RegisterProfilePrefs(
registry->RegisterIntegerPref(
prefs::kAutofillAcceptSaveCreditCardPromptState,
prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_NONE);
+ registry->RegisterIntegerPref(
+ prefs::kAutofillLastVersionDisusedCreditCardsDeleted, 0);
+ registry->RegisterBooleanPref(prefs::kAutofillCreditCardEnabled, true);
}
void AutofillManager::SetExternalDelegate(AutofillExternalDelegate* delegate) {
@@ -411,7 +416,8 @@ bool AutofillManager::OnWillSubmitFormImpl(const FormData& form,
autocomplete_history_manager_->OnWillSubmitForm(form_for_autocomplete);
address_form_event_logger_->OnWillSubmitForm();
- credit_card_form_event_logger_->OnWillSubmitForm();
+ if (IsCreditCardAutofillEnabled())
+ credit_card_form_event_logger_->OnWillSubmitForm();
StartUploadProcess(std::move(submitted_form), timestamp, true);
@@ -428,8 +434,18 @@ bool AutofillManager::OnFormSubmitted(const FormData& form) {
return false;
}
- address_form_event_logger_->OnFormSubmitted();
- credit_card_form_event_logger_->OnFormSubmitted();
+ CreditCard credit_card =
+ personal_data_->ExtractCreditCardFromForm(*submitted_form);
+ if (IsValidCreditCardNumber(credit_card.number())) {
+ credit_card_form_event_logger_->DetectedCardInSubmittedForm();
+ if (personal_data_->IsKnownCard(credit_card)) {
+ credit_card_form_event_logger_->SubmittedKnownCard();
+ }
+ }
+
+ address_form_event_logger_->OnFormSubmitted(/*force_logging=*/false);
+ if (IsCreditCardAutofillEnabled())
+ credit_card_form_event_logger_->OnFormSubmitted(enable_ablation_logging_);
// Update Personal Data with the form's submitted data.
if (submitted_form->IsAutofillable())
@@ -531,19 +547,22 @@ void AutofillManager::OnTextFieldDidChangeImpl(const FormData& form,
if (!user_did_type_) {
user_did_type_ = true;
- AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_TYPE);
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_TYPE,
+ autofill_field->Type().group());
}
if (autofill_field->is_autofilled) {
autofill_field->is_autofilled = false;
autofill_field->set_previously_autofilled(true);
AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD);
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD,
+ autofill_field->Type().group());
if (!user_did_edit_autofilled_field_) {
user_did_edit_autofilled_field_ = true;
AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE);
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE,
+ autofill_field->Type().group());
}
}
@@ -597,8 +616,10 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
if (is_autofill_possible && driver()->RendererIsAvailable() &&
got_autofillable_form) {
// On desktop, don't return non credit card related suggestions for forms or
- // fields that have the "autocomplete" attribute set to off.
- if (IsDesktopPlatform() && !is_filling_credit_card &&
+ // fields that have the "autocomplete" attribute set to off, only if the
+ // feature to always fill addresses is off.
+ if (!base::FeatureList::IsEnabled(kAutofillAlwaysFillAddresses) &&
+ IsDesktopPlatform() && !is_filling_credit_card &&
!field.should_autocomplete) {
return;
}
@@ -609,6 +630,16 @@ void AutofillManager::OnQueryFormFieldAutofillImpl(
GetProfileSuggestions(*form_structure, field, *autofill_field);
}
+ // Logic for disabling/ablating credit card autofill.
+ if (base::FeatureList::IsEnabled(kAutofillCreditCardAblationExperiment) &&
+ is_filling_credit_card && !suggestions.empty()) {
+ suggestions.clear();
+ autocomplete_history_manager_->CancelPendingQuery();
+ external_delegate_->OnSuggestionsReturned(query_id, suggestions);
+ enable_ablation_logging_ = true;
+ return;
+ }
+
if (!suggestions.empty()) {
if (is_filling_credit_card)
AutofillMetrics::LogIsQueriedCreditCardFormSecure(is_context_secure);
@@ -840,11 +871,19 @@ void AutofillManager::OnDidFillAutofillFormData(const FormData& form,
UpdatePendingForm(form);
- AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL);
+ FormStructure* form_structure = NULL;
+ std::set<FormType> form_types;
+ // Find the FormStructure that corresponds to |form|. Use default form type if
+ // form is not present in our cache, which will happen rarely.
+ if (FindCachedForm(form, &form_structure)) {
+ form_types = form_structure->GetFormTypes();
+ }
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL,
+ form_types);
if (!user_did_autofill_) {
user_did_autofill_ = true;
AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_AUTOFILL_ONCE);
+ AutofillMetrics::USER_DID_AUTOFILL_ONCE, form_types);
}
UpdateInitialInteractionTimestamp(timestamp);
@@ -861,12 +900,14 @@ void AutofillManager::DidShowSuggestions(bool is_new_popup,
return;
if (is_new_popup) {
- AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN,
+ autofill_field->Type().group());
if (!did_show_suggestions_) {
did_show_suggestions_ = true;
AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::SUGGESTIONS_SHOWN_ONCE);
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE,
+ autofill_field->Type().group());
}
if (autofill_field->Type().group() == CREDIT_CARD) {
@@ -1000,8 +1041,7 @@ void AutofillManager::SetTestDelegate(AutofillManagerTestDelegate* delegate) {
void AutofillManager::OnSetDataList(const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
- if (!IsValidString16Vector(values) ||
- !IsValidString16Vector(labels) ||
+ if (!IsValidString16Vector(values) || !IsValidString16Vector(labels) ||
values.size() != labels.size())
return;
@@ -1197,6 +1237,11 @@ bool AutofillManager::IsCreditCardUploadEnabled() {
GetIdentityProvider()->GetActiveUsername());
}
+bool AutofillManager::IsCreditCardAutofillEnabled() {
+ return client_->GetPrefs()->GetBoolean(prefs::kAutofillCreditCardEnabled) &&
+ client_->IsAutofillSupported();
+}
+
bool AutofillManager::ShouldUploadForm(const FormStructure& form) {
return IsAutofillEnabled() && !driver()->IsIncognito() &&
form.ShouldBeParsed() &&
@@ -1210,15 +1255,16 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
if (!personal_data_->ImportFormData(
- submitted_form, IsCreditCardUploadEnabled(), &imported_credit_card,
+ submitted_form, IsCreditCardAutofillEnabled(),
+ IsCreditCardUploadEnabled(), &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card))
return;
#ifdef ENABLE_FORM_DEBUG_DUMP
// Debug code for research on what autofill Chrome extracts from the last few
// forms when submitting credit card data. See DumpAutofillData().
- bool dump_data = base::CommandLine::ForCurrentProcess()->HasSwitch(
- "dump-autofill-data");
+ bool dump_data =
+ base::CommandLine::ForCurrentProcess()->HasSwitch("dump-autofill-data");
// Save the form data for future dumping.
if (dump_data) {
@@ -1377,23 +1423,6 @@ int AutofillManager::SetProfilesForCreditCardUpload(
AutofillMetrics::LogHasModifiedProfileOnCreditCardFormSubmission(
has_modified_profile);
- // If there are no recently used or modified profiles and experiment to use
- // profiles that were not recently used is enabled, collect the profiles that
- // used within the maximum time specified in the experiment.
- if (candidate_profiles.empty()) {
- const base::TimeDelta max_time_since_use =
- GetMaxTimeSinceAutofillProfileUseForCardUpload();
- if (!max_time_since_use.is_zero()) {
- for (AutofillProfile* profile : personal_data_->GetProfiles())
- if ((now - profile->modification_date()) < max_time_since_use ||
- (now - profile->use_date()) < max_time_since_use)
- candidate_profiles.push_back(*profile);
- if (!candidate_profiles.empty())
- upload_request->active_experiments.push_back(
- kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name);
- }
- }
-
if (candidate_profiles.empty()) {
upload_decision_metrics |=
has_profile
@@ -1591,6 +1620,7 @@ void AutofillManager::Reset() {
user_did_type_ = false;
user_did_autofill_ = false;
user_did_edit_autofilled_field_ = false;
+ enable_ablation_logging_ = false;
masked_card_ = CreditCard();
unmasking_query_id_ = -1;
unmasking_form_ = FormData();
@@ -1646,8 +1676,7 @@ bool AutofillManager::RefreshDataModels() {
return false;
// No autofill data to return if the profiles are empty.
- const std::vector<AutofillProfile*>& profiles =
- personal_data_->GetProfiles();
+ const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
const std::vector<CreditCard*>& credit_cards =
personal_data_->GetCreditCards();
@@ -1748,8 +1777,8 @@ void AutofillManager::FillOrPreviewDataModelForm(
base::string16 profile_full_name;
std::string profile_language_code;
if (!is_credit_card) {
- profile_full_name = data_model.GetInfo(
- AutofillType(NAME_FULL), app_locale_);
+ profile_full_name =
+ data_model.GetInfo(AutofillType(NAME_FULL), app_locale_);
profile_language_code =
static_cast<const AutofillProfile*>(&data_model)->language_code();
}
@@ -1761,10 +1790,8 @@ void AutofillManager::FillOrPreviewDataModelForm(
if (iter.SameFieldAs(field)) {
base::string16 value =
data_model.GetInfo(autofill_field->Type(), app_locale_);
- if (AutofillField::FillFormField(*autofill_field,
- value,
- profile_language_code,
- app_locale_,
+ if (AutofillField::FillFormField(*autofill_field, value,
+ profile_language_code, app_locale_,
&iter)) {
// Mark the cached field as autofilled, so that we can detect when a
// user edits an autofilled field (for metrics).
@@ -1806,12 +1833,12 @@ void AutofillManager::FillOrPreviewDataModelForm(
base::string16 value =
data_model.GetInfo(cached_field->Type(), app_locale_);
- if (is_credit_card &&
- cached_field->Type().GetStorableType() ==
- CREDIT_CARD_VERIFICATION_CODE) {
+ if (is_credit_card && cached_field->Type().GetStorableType() ==
+ CREDIT_CARD_VERIFICATION_CODE) {
value = cvc;
- } else if (is_credit_card && IsCreditCardExpirationType(
- cached_field->Type().GetStorableType()) &&
+ } else if (is_credit_card &&
+ IsCreditCardExpirationType(
+ cached_field->Type().GetStorableType()) &&
static_cast<const CreditCard*>(&data_model)
->IsExpired(AutofillClock::Now())) {
// Don't fill expired cards expiration date.
@@ -1822,16 +1849,12 @@ void AutofillManager::FillOrPreviewDataModelForm(
// Only notify autofilling of empty fields and the field that initiated
// the filling (note that "select-one" controls may not be empty but will
// still be autofilled).
- bool should_notify =
- !is_credit_card &&
- !value.empty() &&
- (result.fields[i].SameFieldAs(field) ||
- result.fields[i].form_control_type == "select-one" ||
- result.fields[i].value.empty());
- if (AutofillField::FillFormField(*cached_field,
- value,
- profile_language_code,
- app_locale_,
+ bool should_notify = !is_credit_card && !value.empty() &&
+ (result.fields[i].SameFieldAs(field) ||
+ result.fields[i].form_control_type == "select-one" ||
+ result.fields[i].value.empty());
+ if (AutofillField::FillFormField(*cached_field, value,
+ profile_language_code, app_locale_,
&result.fields[i])) {
// Mark the cached field as autofilled, so that we can detect when a
// user edits an autofilled field (for metrics).
@@ -1963,8 +1986,7 @@ bool AutofillManager::UpdateCachedForm(const FormData& live_form,
const FormStructure* cached_form,
FormStructure** updated_form) {
bool needs_update =
- (!cached_form ||
- live_form.fields.size() != cached_form->field_count());
+ (!cached_form || live_form.fields.size() != cached_form->field_count());
for (size_t i = 0; !needs_update && i < cached_form->field_count(); ++i)
needs_update = !cached_form->field(i)->SameFieldAs(live_form.fields[i]);
@@ -2050,6 +2072,7 @@ void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
std::vector<FormStructure*> non_queryable_forms;
std::vector<FormStructure*> queryable_forms;
+ std::set<FormType> form_types;
for (const FormData& form : forms) {
const auto parse_form_start_time = TimeTicks::Now();
@@ -2058,6 +2081,8 @@ void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
continue;
DCHECK(form_structure);
+ std::set<FormType> current_form_types = form_structure->GetFormTypes();
+ form_types.insert(current_form_types.begin(), current_form_types.end());
// Set aside forms with method GET or author-specified types, so that they
// are not included in the query to the server.
if (form_structure->ShouldBeCrowdsourced())
@@ -2070,7 +2095,8 @@ void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
}
if (!queryable_forms.empty() || !non_queryable_forms.empty()) {
- AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::FORMS_LOADED);
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::FORMS_LOADED,
+ form_types);
#if defined(OS_IOS)
// Log this from same location as AutofillMetrics::FORMS_LOADED to ensure
@@ -2181,7 +2207,7 @@ void AutofillManager::SplitFrontendID(int frontend_id,
std::string* cc_backend_id,
std::string* profile_backend_id) const {
int cc_int_id = (frontend_id >> std::numeric_limits<uint16_t>::digits) &
- std::numeric_limits<uint16_t>::max();
+ std::numeric_limits<uint16_t>::max();
int profile_int_id = frontend_id & std::numeric_limits<uint16_t>::max();
*cc_backend_id = IntToBackendID(cc_int_id);
@@ -2387,8 +2413,8 @@ void AutofillManager::DumpAutofillData(bool imported_cc) const {
fputs("Got a new credit card on CC form:\n", file);
else
fputs("Submitted form:\n", file);
- for (int i = static_cast<int>(recently_autofilled_forms_.size()) - 1;
- i >= 0; i--) {
+ for (int i = static_cast<int>(recently_autofilled_forms_.size()) - 1; i >= 0;
+ i--) {
for (const auto& pair : recently_autofilled_forms_[i]) {
fputs(" ", file);
fputs(pair.first.c_str(), file);
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index ededde78f65..b8c8ecf2619 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -27,6 +27,7 @@
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/card_unmask_delegate.h"
#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/form_types.h"
#include "components/autofill/core/browser/payments/full_card_request.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -201,6 +202,10 @@ class AutofillManager : public AutofillHandler,
// are satisfied.
virtual bool IsCreditCardUploadEnabled();
+ // Returns true if the value of the AutofillCreditCardEnabled pref is true and
+ // the client supports Autofill.
+ virtual bool IsCreditCardAutofillEnabled();
+
// Shared code to determine if |form| should be uploaded to the Autofill
// server. It verifies that uploading is allowed and |form| meets conditions
// to be uploadable. Exposed for testing.
@@ -582,6 +587,10 @@ class AutofillManager : public AutofillHandler,
// determined to be a CVC field via heuristics has a valid CVC |value|.
bool found_cvc_value_in_non_cvc_field_;
+ // Ablation experiment turns off autofill, but logging still has to be kept
+ // for metrics analysis.
+ bool enable_ablation_logging_;
+
GURL pending_upload_request_url_;
#ifdef ENABLE_FORM_DEBUG_DUMP
@@ -632,6 +641,18 @@ class AutofillManager : public AutofillHandler,
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, CreditCardSubmittedFormEvents);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest,
CreditCardCheckoutFlowUserActions);
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillMetricsTest,
+ CreditCardSubmittedWithoutSelectingSuggestionsNoCard);
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillMetricsTest,
+ CreditCardSubmittedWithoutSelectingSuggestionsUnknownCard);
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillMetricsTest,
+ CreditCardSubmittedWithoutSelectingSuggestionsKnownCard);
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillMetricsTest,
+ ShouldNotLogSubmitWithoutSelectingSuggestionsIfSuggestionFilled);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, ProfileCheckoutFlowUserActions);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, DeveloperEngagement);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, FormFillDuration);
@@ -646,7 +667,10 @@ class AutofillManager : public AutofillHandler,
TestTabContentsWithExternalDelegate);
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest,
UserHappinessFormLoadAndSubmission);
- FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, UserHappinessFormInteraction);
+ FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest,
+ UserHappinessFormInteraction_AddressForm);
+ FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest,
+ UserHappinessFormInteraction_CreditCardForm);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
OnLoadedServerPredictions);
FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index 1280500a66e..74d41a7f88f 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -572,6 +572,7 @@ class TestAutofillManager : public AutofillManager {
context_getter_(driver->GetURLRequestContext()),
test_payments_client_(new TestPaymentsClient(context_getter_, this)),
autofill_enabled_(true),
+ credit_card_enabled_(true),
credit_card_upload_enabled_(false),
credit_card_was_uploaded_(false),
expected_observed_submission_(true),
@@ -594,6 +595,15 @@ class TestAutofillManager : public AutofillManager {
credit_card_upload_enabled_ = credit_card_upload_enabled;
}
+ bool IsCreditCardAutofillEnabled() override { return credit_card_enabled_; }
+
+ void set_credit_card_enabled(bool credit_card_enabled) {
+ credit_card_enabled_ = credit_card_enabled;
+ if (!credit_card_enabled_)
+ // Credit card data is refreshed when this pref is changed.
+ personal_data_->ClearCreditCards();
+ }
+
bool credit_card_was_uploaded() { return credit_card_was_uploaded_; }
void set_expected_submitted_field_types(
@@ -675,7 +685,7 @@ class TestAutofillManager : public AutofillManager {
return personal_data_->GetLocalCreditCards();
}
- const std::vector<CreditCard*>& GetCreditCards() const {
+ std::vector<CreditCard*> GetCreditCards() const {
return personal_data_->GetCreditCards();
}
@@ -723,6 +733,7 @@ class TestAutofillManager : public AutofillManager {
net::URLRequestContextGetter* context_getter_; // Weak reference.
TestPaymentsClient* test_payments_client_; // Weak reference.
bool autofill_enabled_;
+ bool credit_card_enabled_;
bool credit_card_upload_enabled_;
bool credit_card_was_uploaded_;
bool expected_observed_submission_;
@@ -1096,11 +1107,16 @@ class AutofillManagerTest : public testing::Test {
scoped_feature_list_.InitAndEnableFeature(kAutofillUpstreamShowNewUi);
}
- void DisableAutofillUpstreamUseAutofillProfileComparator() {
- scoped_feature_list_.InitAndDisableFeature(
+ void EnableAutofillUpstreamUseAutofillProfileComparator() {
+ scoped_feature_list_.InitAndEnableFeature(
kAutofillUpstreamUseAutofillProfileComparator);
}
+ void DisableCreditCardAutofill() {
+ scoped_feature_list_.InitAndEnableFeature(
+ kAutofillCreditCardAblationExperiment);
+ }
+
void ExpectUniqueFillableFormParsedUkm() {
// Check that one source is logged.
ASSERT_EQ(1U, test_ukm_recorder_.sources_count());
@@ -1215,7 +1231,7 @@ class TestFormStructure : public FormStructure {
AutofillField* form_field = field(i);
ASSERT_TRUE(form_field);
form_field->set_heuristic_type(heuristic_types[i]);
- form_field->set_server_type(server_types[i]);
+ form_field->set_overall_server_type(server_types[i]);
}
UpdateAutofillCount();
@@ -2088,6 +2104,62 @@ TEST_F(AutofillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) {
external_delegate_->CheckNoSuggestions(kDefaultPageID);
}
+TEST_F(AutofillManagerTest,
+ ShouldShowAddressSuggestionsIfCreditCardAutofillDisabled) {
+ DisableCreditCardAutofill();
+
+ // Set up our form data.
+ FormData form;
+ test::CreateTestAddressFormData(&form);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ FormFieldData field = form.fields[0];
+ GetAutofillSuggestions(form, field);
+
+ // Check that address suggestions will still be available.
+ external_delegate_->CheckSuggestions(
+ kDefaultPageID, Suggestion("Charles", "123 Apple St.", "", 1),
+ Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
+}
+
+TEST_F(AutofillManagerTest,
+ ShouldNotShowCreditCardsSuggestionsIfCreditCardAutofillDisabled) {
+ DisableCreditCardAutofill();
+
+ // Set up our form data.
+ FormData form;
+ CreateTestCreditCardFormData(&form, true, false);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ FormFieldData field = form.fields[0];
+ GetAutofillSuggestions(form, field);
+
+ // Check that credit card suggestions will not be available.
+ external_delegate_->CheckNoSuggestions(kDefaultPageID);
+}
+
+TEST_F(AutofillManagerTest,
+ ShouldLogFormSubmitEventIfCreditCardAutofillDisabled) {
+ DisableCreditCardAutofill();
+
+ // Set up our form data.
+ FormData form;
+ CreateTestCreditCardFormData(&form, true, false);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ FormFieldData field = form.fields[0];
+ GetAutofillSuggestions(form, field);
+
+ base::HistogramTester histogram_tester;
+ FormSubmitted(form);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
+}
+
// Test that we return autocomplete-like suggestions when trying to autofill
// already filled forms.
TEST_F(AutofillManagerTest, GetFieldSuggestionsWhenFormIsAutofilled) {
@@ -2566,8 +2638,12 @@ TEST_F(AutofillManagerTest, FillAddressForm_UnrecognizedAttribute) {
}
// Test that non credit card related fields with the autocomplete attribute set
-// to off are not filled on desktop.
-TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOff) {
+// to off are not filled on desktop when the feature to autofill all addresses
+// is disabled.
+TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOffRespected) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+
FormData address_form;
address_form.name = ASCIIToUTF16("MyForm");
address_form.origin = GURL("https://myform.com/form.html");
@@ -2622,6 +2698,48 @@ TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOff) {
}
}
+// Test that non credit card related fields with the autocomplete attribute set
+// to off are filled on all platforms when the feature to autofill all addresses
+// is enabled (default).
+TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOffNotRespected) {
+ FormData address_form;
+ address_form.name = ASCIIToUTF16("MyForm");
+ address_form.origin = GURL("https://myform.com/form.html");
+ address_form.action = GURL("https://myform.com/submit.html");
+ FormFieldData field;
+ test::CreateTestFormField("First name", "firstname", "", "text", &field);
+ address_form.fields.push_back(field);
+ test::CreateTestFormField("Middle name", "middle", "", "text", &field);
+ field.should_autocomplete = false;
+ address_form.fields.push_back(field);
+ test::CreateTestFormField("Last name", "lastname", "", "text", &field);
+ field.should_autocomplete = true;
+ address_form.fields.push_back(field);
+ test::CreateTestFormField("Address Line 1", "addr1", "", "text", &field);
+ field.should_autocomplete = false;
+ address_form.fields.push_back(field);
+ std::vector<FormData> address_forms(1, address_form);
+ FormsSeen(address_forms);
+
+ // Fill the address form.
+ const char guid[] = "00000000-0000-0000-0000-000000000001";
+ int response_page_id = 0;
+ FormData response_data;
+ FillAutofillFormDataAndSaveResults(
+ kDefaultPageID, address_form, address_form.fields[0],
+ MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
+
+ // All fields should be filled.
+ ExpectFilledField("First name", "firstname", "Elvis", "text",
+ response_data.fields[0]);
+ ExpectFilledField("Middle name", "middle", "Aaron", "text",
+ response_data.fields[1]);
+ ExpectFilledField("Last name", "lastname", "Presley", "text",
+ response_data.fields[2]);
+ ExpectFilledField("Address Line 1", "addr1", "3734 Elvis Presley Blvd.",
+ "text", response_data.fields[3]);
+}
+
// Test that a field with a value equal to it's placeholder attribute is filled.
TEST_F(AutofillManagerTest, FillAddressForm_PlaceholderEqualsValue) {
FormData address_form;
@@ -3628,16 +3746,16 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
autofill_manager_->AddSeenForm(base::WrapUnique(form_structure2));
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(3);
+ response.add_field()->set_overall_type_prediction(3);
for (int i = 0; i < 7; ++i) {
- response.add_field()->set_autofill_type(0);
+ response.add_field()->set_overall_type_prediction(0);
}
- response.add_field()->set_autofill_type(3);
- response.add_field()->set_autofill_type(2);
- response.add_field()->set_autofill_type(61);
- response.add_field()->set_autofill_type(5);
- response.add_field()->set_autofill_type(4);
- response.add_field()->set_autofill_type(35);
+ response.add_field()->set_overall_type_prediction(3);
+ response.add_field()->set_overall_type_prediction(2);
+ response.add_field()->set_overall_type_prediction(61);
+ response.add_field()->set_overall_type_prediction(5);
+ response.add_field()->set_overall_type_prediction(4);
+ response.add_field()->set_overall_type_prediction(35);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -3680,13 +3798,13 @@ TEST_F(AutofillManagerTest, OnLoadedServerPredictions_ResetManager) {
autofill_manager_->AddSeenForm(base::WrapUnique(form_structure));
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(3);
+ response.add_field()->set_overall_type_prediction(3);
for (int i = 0; i < 7; ++i) {
- response.add_field()->set_autofill_type(0);
+ response.add_field()->set_overall_type_prediction(0);
}
- response.add_field()->set_autofill_type(3);
- response.add_field()->set_autofill_type(2);
- response.add_field()->set_autofill_type(61);
+ response.add_field()->set_overall_type_prediction(3);
+ response.add_field()->set_overall_type_prediction(2);
+ response.add_field()->set_overall_type_prediction(61);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -4272,7 +4390,8 @@ TEST_F(AutofillManagerTest, DisambiguateUploadTypes) {
// Assign the specified predicted type for each field in the test case.
FormStructure form_structure(form);
for (size_t i = 0; i < test_fields.size(); ++i) {
- form_structure.field(i)->set_server_type(test_fields[i].predicted_type);
+ form_structure.field(i)->set_overall_server_type(
+ test_fields[i].predicted_type);
}
AutofillManager::DeterminePossibleFieldTypesForUpload(
@@ -4670,6 +4789,78 @@ TEST_F(AutofillManagerTest, FillInUpdatedExpirationDate) {
"4012888888881881");
}
+TEST_F(AutofillManagerTest, CreditCardDisabledDoesNotSave) {
+ personal_data_.ClearAutofillProfiles();
+ autofill_manager_->set_credit_card_enabled(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));
+ ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen(std::vector<FormData>(1, credit_card_form));
+
+ // Edit the data, and submit.
+ credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
+ credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[2].value = ASCIIToUTF16("11");
+ credit_card_form.fields[3].value = ASCIIToUTF16("2017");
+ credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
+ // The credit card should neither be saved locally or uploaded.
+ EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+
+ // Verify that no histogram entry was logged.
+ histogram_tester.ExpectTotalCount("Autofill.CardUploadDecisionMetric", 0);
+}
+
+TEST_F(AutofillManagerTest, CreditCardDisabledDoesNotFillFormData) {
+ autofill_manager_->set_credit_card_enabled(false);
+
+ // Set up our form data.
+ FormData form;
+ CreateTestCreditCardFormData(&form, true, false);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ const char guid[] = "00000000-0000-0000-0000-000000000004";
+
+ // Expect no fields filled, no form data sent to renderer.
+ EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _)).Times(0);
+
+ FillAutofillFormData(kDefaultPageID, form, *form.fields.begin(),
+ MakeFrontendID(guid, std::string()));
+}
+
+TEST_F(AutofillManagerTest, CreditCardDisabledDoesNotSuggest) {
+ autofill_manager_->set_credit_card_enabled(false);
+
+ // Set up our form data.
+ FormData form;
+ CreateTestCreditCardFormData(&form, true, false);
+ std::vector<FormData> forms(1, form);
+ EXPECT_CALL(autofill_client_, ShouldShowSigninPromo());
+ FormsSeen(forms);
+
+ FormFieldData field;
+ test::CreateTestFormField("Name on Card", "nameoncard", "pres", "text",
+ &field);
+ GetAutofillSuggestions(form, field);
+ // Expect no suggestions as autofill and autocomplete are disabled for credit
+ // cards.
+ EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
+}
+
TEST_F(AutofillManagerTest, UploadCreditCard) {
personal_data_.ClearCreditCards();
personal_data_.ClearAutofillProfiles();
@@ -4703,9 +4894,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
// Server did not send a server_id, expect copy of card is not stored.
EXPECT_TRUE(autofill_manager_->GetCreditCards().empty());
@@ -4755,9 +4944,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard_RequestCVCEnabled_DoesNotTrigger) {
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
// Submitted form included CVC, so user did not need to enter CVC.
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
}
TEST_F(AutofillManagerTest, UploadCreditCardAndSaveCopy) {
@@ -5271,10 +5458,8 @@ TEST_F(AutofillManagerTest,
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name,
- kAutofillUpstreamRequestCvcIfMissing.name));
+ EXPECT_THAT(autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamRequestCvcIfMissing.name));
// Verify that the correct histogram entries were logged.
ExpectCardUploadDecision(histogram_tester, AutofillMetrics::UPLOAD_OFFERED);
@@ -5371,16 +5556,12 @@ TEST_F(AutofillManagerTest,
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
// Confirm upload happened and the new UI flag was sent in the request.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name,
- kAutofillUpstreamShowNewUi.name));
+ EXPECT_THAT(autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamShowNewUi.name));
}
TEST_F(AutofillManagerTest,
@@ -5408,15 +5589,11 @@ TEST_F(AutofillManagerTest,
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
- // Confirm upload happened and the new UI flag was sent in the request.
+ // Confirm upload happened and the new UI flag was not sent in the request.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
}
TEST_F(AutofillManagerTest,
@@ -5445,17 +5622,13 @@ TEST_F(AutofillManagerTest,
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
// Confirm upload happened and the show Google logo flag was sent in the
// request.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name,
- kAutofillUpstreamShowGoogleLogo.name));
+ EXPECT_THAT(autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamShowGoogleLogo.name));
}
TEST_F(AutofillManagerTest,
@@ -5483,16 +5656,12 @@ TEST_F(AutofillManagerTest,
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
- base::HistogramTester histogram_tester;
-
- // Confirm upload happened and the show Google logo flag was sent in the
+ // Confirm upload happened and the show Google logo flag was not sent in the
// request.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
}
#endif
@@ -5580,63 +5749,6 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoRecentlyUsedProfile) {
}
TEST_F(AutofillManagerTest,
- UploadCreditCard_NoRecentlyUsedProfile_CanUseOldProfile) {
- variation_params_.SetVariationParamsWithFeatureAssociations(
- kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name,
- {{kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey,
- base::IntToString((kMuchLaterTime - kArbitraryTime).InMinutes() + 1)}},
- {kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name});
-
- // Create the test clock and set the time to a specific value.
- TestAutofillClock test_clock;
- test_clock.SetNow(kArbitraryTime);
-
- personal_data_.ClearAutofillProfiles();
- autofill_manager_->set_credit_card_upload_enabled(true);
-
- // Create, fill and submit an address form in order to establish a profile.
- FormData address_form;
- test::CreateTestAddressFormData(&address_form);
- FormsSeen({address_form});
-
- ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form);
- FormSubmitted(address_form);
-
- // Advance the current time. Although |address_form| is not a recently used
- // address profile, we will include it in the candidate profiles because
- // there are no recently used address profiles and the feature to use older
- // profiles is enabled.
- test_clock.SetNow(kMuchLaterTime);
-
- // 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("11");
- credit_card_form.fields[3].value = ASCIIToUTF16("2017");
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // Upload should be offered.
- EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
- FormSubmitted(credit_card_form);
- EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_THAT(autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(
- kAutofillUpstreamUseAutofillProfileComparator.name,
- kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name));
-
- // Verify that the correct histogram entry (and only that) was logged.
- ExpectUniqueCardUploadDecision(histogram_tester,
- AutofillMetrics::UPLOAD_OFFERED);
-}
-
-TEST_F(AutofillManagerTest,
UploadCreditCard_CvcUnavailableAndNoProfileAvailable) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -5795,19 +5907,20 @@ TEST_F(AutofillManagerTest, UploadCreditCard_ZipCodesDiscardWhitespace) {
base::HistogramTester histogram_tester;
- // Zips match because we discard whitespace before comparison.
+ // Neither a local save nor an upload should happen in this case.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
- EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
// Verify that the correct histogram entry (and only that) was logged.
- ExpectUniqueCardUploadDecision(histogram_tester,
- AutofillMetrics::UPLOAD_OFFERED);
+ ExpectUniqueCardUploadDecision(
+ histogram_tester, AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS);
}
TEST_F(AutofillManagerTest,
- UploadCreditCard_ZipCodesDiscardWhitespace_DisableComparator) {
- DisableAutofillUpstreamUseAutofillProfileComparator();
+ UploadCreditCard_ZipCodesDiscardWhitespace_ComparatorEnabled) {
+ EnableAutofillUpstreamUseAutofillProfileComparator();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -5838,14 +5951,17 @@ TEST_F(AutofillManagerTest,
base::HistogramTester histogram_tester;
- // Neither a local save nor an upload should happen in this case.
+ // Zips match because we discard whitespace before comparison.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
- EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_THAT(
+ autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
// Verify that the correct histogram entry (and only that) was logged.
- ExpectUniqueCardUploadDecision(
- histogram_tester, AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS);
+ ExpectUniqueCardUploadDecision(histogram_tester,
+ AutofillMetrics::UPLOAD_OFFERED);
}
TEST_F(AutofillManagerTest, UploadCreditCard_ZipCodesHavePrefixMatch) {
@@ -5976,6 +6092,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CCFormHasMiddleInitial) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(histogram_tester,
@@ -5985,8 +6102,8 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CCFormHasMiddleInitial) {
}
TEST_F(AutofillManagerTest,
- UploadCreditCard_CCFormHasMiddleInitial_DisableComparator) {
- DisableAutofillUpstreamUseAutofillProfileComparator();
+ UploadCreditCard_CCFormHasMiddleInitial_ComparatorEnabled) {
+ EnableAutofillUpstreamUseAutofillProfileComparator();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -6023,11 +6140,15 @@ TEST_F(AutofillManagerTest,
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
+ EXPECT_THAT(
+ autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(histogram_tester,
AutofillMetrics::UPLOAD_OFFERED);
+ // Verify that the correct UKM was logged.
+ ExpectCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
TEST_F(AutofillManagerTest, UploadCreditCard_NoMiddleInitialInCCForm) {
@@ -6073,8 +6194,8 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NoMiddleInitialInCCForm) {
}
TEST_F(AutofillManagerTest,
- UploadCreditCard_NoMiddleInitialInCCForm_DisableComparator) {
- DisableAutofillUpstreamUseAutofillProfileComparator();
+ UploadCreditCard_NoMiddleInitialInCCForm_ComparatorEnabled) {
+ EnableAutofillUpstreamUseAutofillProfileComparator();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -6112,6 +6233,8 @@ TEST_F(AutofillManagerTest,
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(histogram_tester,
AutofillMetrics::UPLOAD_OFFERED);
+ // Verify that the correct UKM was logged.
+ ExpectCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
TEST_F(AutofillManagerTest, UploadCreditCard_CCFormHasMiddleName) {
@@ -6139,10 +6262,52 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CCFormHasMiddleName) {
base::HistogramTester histogram_tester;
+ // Names match loosely but we have disabled comparator. Upload should not
+ // happen.
+ EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
+ FormSubmitted(credit_card_form);
+ EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
+
+ // Verify that the correct histogram entry (and only that) was logged.
+ ExpectUniqueCardUploadDecision(
+ histogram_tester, AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES);
+}
+
+TEST_F(AutofillManagerTest,
+ UploadCreditCard_CCFormHasMiddleName_ComparatorEnabled) {
+ EnableAutofillUpstreamUseAutofillProfileComparator();
+ personal_data_.ClearAutofillProfiles();
+ autofill_manager_->set_credit_card_upload_enabled(true);
+
+ // Create, fill and submit address form without middle name.
+ FormData address_form;
+ test::CreateTestAddressFormData(&address_form);
+ FormsSeen({address_form});
+ ManuallyFillAddressForm("John", "Adams", "77401", "US", &address_form);
+ FormSubmitted(address_form);
+
+ // Set up our credit card form data.
+ FormData credit_card_form;
+ CreateTestCreditCardFormData(&credit_card_form, true, false);
+ FormsSeen({credit_card_form});
+
+ // Edit the name by adding a middle name.
+ credit_card_form.fields[0].value = ASCIIToUTF16("John Quincy Adams");
+ credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
+ credit_card_form.fields[2].value = ASCIIToUTF16("11");
+ credit_card_form.fields[3].value = ASCIIToUTF16("2017");
+ credit_card_form.fields[4].value = ASCIIToUTF16("123");
+
+ base::HistogramTester histogram_tester;
+
// Names match loosely, upload should happen.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_THAT(
+ autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(histogram_tester,
@@ -6151,17 +6316,15 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CCFormHasMiddleName) {
ExpectCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
-TEST_F(AutofillManagerTest,
- UploadCreditCard_CCFormHasMiddleName_DisableComparator) {
- DisableAutofillUpstreamUseAutofillProfileComparator();
+TEST_F(AutofillManagerTest, UploadCreditCard_CCFormRemovesMiddleName) {
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
- // Create, fill and submit address form without middle name.
+ // Create, fill and submit address form with middle name.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
FormsSeen({address_form});
- ManuallyFillAddressForm("John", "Adams", "77401", "US", &address_form);
+ ManuallyFillAddressForm("John Quincy", "Adams", "77401", "US", &address_form);
FormSubmitted(address_form);
// Set up our credit card form data.
@@ -6169,8 +6332,8 @@ TEST_F(AutofillManagerTest,
CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen({credit_card_form});
- // Edit the name by adding a middle name.
- credit_card_form.fields[0].value = ASCIIToUTF16("John Quincy Adams");
+ // Edit the name by removing middle name.
+ credit_card_form.fields[0].value = ASCIIToUTF16("John Adams");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("11");
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
@@ -6178,18 +6341,23 @@ TEST_F(AutofillManagerTest,
base::HistogramTester histogram_tester;
- // Names match loosely but we have disabled comparator. Upload should not
- // happen.
+ // With the comparator disabled, names do not match; upload should not happen.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(
histogram_tester, AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES);
+ // Verify that the correct UKM was logged.
+ ExpectCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES);
}
-TEST_F(AutofillManagerTest, UploadCreditCard_CCFormRemovesMiddleName) {
+TEST_F(AutofillManagerTest,
+ UploadCreditCard_CCFormRemovesMiddleName_ComparatorEnabled) {
+ EnableAutofillUpstreamUseAutofillProfileComparator();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -6218,6 +6386,9 @@ TEST_F(AutofillManagerTest, UploadCreditCard_CCFormRemovesMiddleName) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_THAT(
+ autofill_manager_->GetActiveExperiments(),
+ UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(histogram_tester,
@@ -6264,6 +6435,7 @@ TEST_F(AutofillManagerTest, UploadCreditCard_NamesHaveToMatch) {
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
FormSubmitted(credit_card_form);
EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
+ EXPECT_TRUE(autofill_manager_->GetActiveExperiments().empty());
// Verify that the correct histogram entry (and only that) was logged.
ExpectUniqueCardUploadDecision(
@@ -6321,116 +6493,6 @@ TEST_F(AutofillManagerTest, UploadCreditCard_IgnoreOldProfiles) {
AutofillMetrics::UPLOAD_OFFERED);
}
-TEST_F(AutofillManagerTest,
- UploadCreditCard_IgnoreOldProfiles_CanUseOldProfiles) {
- variation_params_.SetVariationParamsWithFeatureAssociations(
- kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name,
- {{kAutofillUpstreamMaxMinutesSinceAutofillProfileUseKey,
- base::IntToString((kMuchLaterTime - kArbitraryTime).InMinutes() + 1)}},
- {kAutofillUpstreamUseNotRecentlyUsedAutofillProfile.name});
-
- // Create the test clock and set the time to a specific value.
- TestAutofillClock test_clock;
- test_clock.SetNow(kArbitraryTime);
-
- personal_data_.ClearAutofillProfiles();
- autofill_manager_->set_credit_card_upload_enabled(true);
-
- // Create, fill and submit two address forms with different names.
- FormData address_form1, address_form2;
- test::CreateTestAddressFormData(&address_form1);
- test::CreateTestAddressFormData(&address_form2);
- FormsSeen({address_form1, address_form2});
-
- ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form1);
- FormSubmitted(address_form1);
-
- // Advance the current time. Since |address_form1| will not be a recently
- // used address profile, we will not include it in the candidate profiles
- // because we have a recently used address.
- test_clock.SetNow(kMuchLaterTime);
-
- ManuallyFillAddressForm("Master", "Blaster", "77401", "US", &address_form2);
- FormSubmitted(address_form2);
-
- // 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, but use yet another name, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Master Blaster");
- credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
- credit_card_form.fields[2].value = ASCIIToUTF16("11");
- credit_card_form.fields[3].value = ASCIIToUTF16("2017");
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // Name matches recently used profile, should offer upload.
- EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
- FormSubmitted(credit_card_form);
- EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
- // Recently used profile was available, so did not need to use old profile.
- EXPECT_THAT(
- autofill_manager_->GetActiveExperiments(),
- UnorderedElementsAre(kAutofillUpstreamUseAutofillProfileComparator.name));
-
- // Verify that the correct histogram entry (and only that) was logged.
- ExpectUniqueCardUploadDecision(histogram_tester,
- AutofillMetrics::UPLOAD_OFFERED);
-}
-
-TEST_F(AutofillManagerTest,
- UploadCreditCard_NamesHaveToMatch_DisableComparator) {
- DisableAutofillUpstreamUseAutofillProfileComparator();
- personal_data_.ClearAutofillProfiles();
- autofill_manager_->set_credit_card_upload_enabled(true);
-
- // Create, fill and submit two address forms with different names.
- FormData address_form1, address_form2;
- test::CreateTestAddressFormData(&address_form1);
- test::CreateTestAddressFormData(&address_form2);
-
- std::vector<FormData> address_forms;
- address_forms.push_back(address_form1);
- address_forms.push_back(address_form2);
- FormsSeen(address_forms);
-
- ManuallyFillAddressForm("Flo", "Master", "77401", "US", &address_form1);
- FormSubmitted(address_form1);
-
- ManuallyFillAddressForm("Master", "Blaster", "77401", "US", &address_form2);
- FormSubmitted(address_form2);
-
- // Set up our credit card form data.
- FormData credit_card_form;
- CreateTestCreditCardFormData(&credit_card_form, true, false);
- FormsSeen({credit_card_form});
-
- // Edit the data, but use yet another name, and submit.
- credit_card_form.fields[0].value = ASCIIToUTF16("Bob Master");
- FormsSeen({credit_card_form});
-
- // Edit the credit card form 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("11");
- credit_card_form.fields[3].value = ASCIIToUTF16("2017");
- credit_card_form.fields[4].value = ASCIIToUTF16("123");
-
- base::HistogramTester histogram_tester;
-
- // Names are required to match, upload should not happen.
- EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_, _)).Times(0);
- FormSubmitted(credit_card_form);
- EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
-
- // Verify that the correct histogram entry (and only that) was logged.
- ExpectUniqueCardUploadDecision(
- histogram_tester, AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES);
-}
-
TEST_F(AutofillManagerTest, UploadCreditCard_LogPreviousUseDate) {
// Create the test clock and set the time to a specific value.
TestAutofillClock test_clock;
@@ -6974,7 +7036,46 @@ TEST_F(AutofillManagerTest, ShouldUploadForm) {
// Verify that no suggestions are shown on desktop for non credit card related
// fields if the initiating field has the "autocomplete" attribute set to off.
-TEST_F(AutofillManagerTest, DisplaySuggestions_AutocompleteOff_AddressField) {
+TEST_F(AutofillManagerTest,
+ DisplaySuggestions_AutocompleteOffNotRespected_AddressField) {
+ // Set up an address form.
+ FormData mixed_form;
+ mixed_form.name = ASCIIToUTF16("MyForm");
+ mixed_form.origin = GURL("https://myform.com/form.html");
+ mixed_form.action = GURL("https://myform.com/submit.html");
+ FormFieldData field;
+ test::CreateTestFormField("First name", "firstname", "", "text", &field);
+ field.should_autocomplete = false;
+ mixed_form.fields.push_back(field);
+ test::CreateTestFormField("Last name", "lastname", "", "text", &field);
+ field.should_autocomplete = true;
+ mixed_form.fields.push_back(field);
+ test::CreateTestFormField("Address", "address", "", "text", &field);
+ field.should_autocomplete = true;
+ mixed_form.fields.push_back(field);
+ std::vector<FormData> mixed_forms(1, mixed_form);
+ FormsSeen(mixed_forms);
+
+ // Suggestions should be displayed on desktop for this field in all
+ // circumstances.
+ GetAutofillSuggestions(mixed_form, mixed_form.fields[0]);
+ EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
+
+ // Suggestions should always be displayed for all the other fields.
+ for (size_t i = 1U; i < mixed_form.fields.size(); ++i) {
+ GetAutofillSuggestions(mixed_form, mixed_form.fields[i]);
+ EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
+ }
+}
+
+// Verify that no suggestions are shown on desktop for non credit card related
+// fields if the initiating field has the "autocomplete" attribute set to off
+// and the feature to autofill all addresses is also off.
+TEST_F(AutofillManagerTest,
+ DisplaySuggestions_AutocompleteOffRespected_AddressField) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
+
// Set up an address form.
FormData mixed_form;
mixed_form.name = ASCIIToUTF16("MyForm");
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index d04acca02c4..cd1b3ba0636 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -117,7 +117,7 @@ class PersonalDataManagerMock : public PersonalDataManager {
// PersonalDataManager:
std::string SaveImportedProfile(const AutofillProfile& profile) override;
- std::vector<AutofillProfile*> web_profiles() const override;
+ std::vector<AutofillProfile*> GetProfiles() const override;
private:
std::vector<std::unique_ptr<AutofillProfile>> profiles_;
@@ -146,7 +146,7 @@ std::string PersonalDataManagerMock::SaveImportedProfile(
return merged_guid;
}
-std::vector<AutofillProfile*> PersonalDataManagerMock::web_profiles() const {
+std::vector<AutofillProfile*> PersonalDataManagerMock::GetProfiles() const {
std::vector<AutofillProfile*> result;
for (const auto& profile : profiles_)
result.push_back(profile.get());
@@ -273,7 +273,10 @@ void AutofillMergeTest::MergeProfiles(const std::string& profiles,
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
personal_data_.ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure,
+ true, // credit card autofill enabled
+ false, // should return local card
+ &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card);
EXPECT_FALSE(imported_credit_card);
@@ -282,7 +285,7 @@ void AutofillMergeTest::MergeProfiles(const std::string& profiles,
}
}
- *merged_profiles = SerializeProfiles(personal_data_.web_profiles());
+ *merged_profiles = SerializeProfiles(personal_data_.GetProfiles());
}
ServerFieldType AutofillMergeTest::StringToFieldType(const std::string& str) {
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 3499f11478a..694016c5f95 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/metrics/user_metrics.h"
@@ -18,6 +19,7 @@
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/form_data.h"
@@ -232,13 +234,9 @@ void LogUMAHistogramEnumeration(const std::string& name,
DCHECK_LT(sample, boundary_value);
// Note: This leaks memory, which is expected behavior.
- base::HistogramBase* histogram =
- base::LinearHistogram::FactoryGet(
- name,
- 1,
- boundary_value,
- boundary_value + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
+ base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+ name, 1, boundary_value, boundary_value + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
histogram->Add(sample);
}
@@ -247,13 +245,9 @@ void LogUMAHistogramEnumeration(const std::string& name,
void LogUMAHistogramLongTimes(const std::string& name,
const base::TimeDelta& duration) {
// Note: This leaks memory, which is expected behavior.
- base::HistogramBase* histogram =
- base::Histogram::FactoryTimeGet(
- name,
- base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromHours(1),
- 50,
- base::HistogramBase::kUmaTargetedHistogramFlag);
+ base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
+ name, base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1),
+ 50, base::HistogramBase::kUmaTargetedHistogramFlag);
histogram->AddTime(duration);
}
@@ -701,7 +695,7 @@ void AutofillMetrics::LogServerPredictionQualityMetrics(
QualityMetricType metric_type) {
LogPredictionQualityMetrics(
PREDICTION_SOURCE_SERVER,
- AutofillType(field.server_type()).GetStorableType(),
+ AutofillType(field.overall_server_type()).GetStorableType(),
form_interactions_ukm_logger, form, field, metric_type);
}
@@ -723,52 +717,82 @@ void AutofillMetrics::LogServerQueryMetric(ServerQueryMetric metric) {
}
// static
-void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric) {
+void AutofillMetrics::LogUserHappinessMetric(UserHappinessMetric metric,
+ FieldTypeGroup field_type_group) {
+ LogUserHappinessMetric(
+ metric, {FormTypes::FieldTypeGroupToFormType(field_type_group)});
+}
+
+// static
+void AutofillMetrics::LogUserHappinessMetric(
+ UserHappinessMetric metric,
+ const std::set<FormType>& form_types) {
DCHECK_LT(metric, NUM_USER_HAPPINESS_METRICS);
UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness", metric,
NUM_USER_HAPPINESS_METRICS);
+ if (base::ContainsKey(form_types, CREDIT_CARD_FORM)) {
+ UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness.CreditCard", metric,
+ NUM_USER_HAPPINESS_METRICS);
+ }
+ if (base::ContainsKey(form_types, ADDRESS_FORM)) {
+ UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness.Address", metric,
+ NUM_USER_HAPPINESS_METRICS);
+ }
+ if (base::ContainsKey(form_types, PASSWORD_FORM)) {
+ UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness.Password", metric,
+ NUM_USER_HAPPINESS_METRICS);
+ }
+ if (base::ContainsKey(form_types, UNKNOWN_FORM_TYPE)) {
+ UMA_HISTOGRAM_ENUMERATION("Autofill.UserHappiness.Unknown", metric,
+ NUM_USER_HAPPINESS_METRICS);
+ }
}
// static
void AutofillMetrics::LogFormFillDurationFromLoadWithAutofill(
const base::TimeDelta& duration) {
- UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithAutofill",
- duration,
- base::TimeDelta::FromMilliseconds(100),
- base::TimeDelta::FromMinutes(10),
- 50);
+ LogFormFillDuration("Autofill.FillDuration.FromLoad.WithAutofill", duration);
}
// static
void AutofillMetrics::LogFormFillDurationFromLoadWithoutAutofill(
const base::TimeDelta& duration) {
- UMA_HISTOGRAM_CUSTOM_TIMES("Autofill.FillDuration.FromLoad.WithoutAutofill",
- duration,
- base::TimeDelta::FromMilliseconds(100),
- base::TimeDelta::FromMinutes(10),
- 50);
+ LogFormFillDuration("Autofill.FillDuration.FromLoad.WithoutAutofill",
+ duration);
}
// static
-void AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill(
+void AutofillMetrics::LogFormFillDurationFromInteraction(
+ const std::set<FormType>& form_types,
+ bool used_autofill,
const base::TimeDelta& duration) {
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Autofill.FillDuration.FromInteraction.WithAutofill",
- duration,
- base::TimeDelta::FromMilliseconds(100),
- base::TimeDelta::FromMinutes(10),
- 50);
+ std::string parent_metric;
+ if (used_autofill) {
+ parent_metric = "Autofill.FillDuration.FromInteraction.WithAutofill";
+ } else {
+ parent_metric = "Autofill.FillDuration.FromInteraction.WithoutAutofill";
+ }
+ LogFormFillDuration(parent_metric, duration);
+ if (base::ContainsKey(form_types, CREDIT_CARD_FORM)) {
+ LogFormFillDuration(parent_metric + ".CreditCard", duration);
+ }
+ if (base::ContainsKey(form_types, ADDRESS_FORM)) {
+ LogFormFillDuration(parent_metric + ".Address", duration);
+ }
+ if (base::ContainsKey(form_types, PASSWORD_FORM)) {
+ LogFormFillDuration(parent_metric + ".Password", duration);
+ }
+ if (base::ContainsKey(form_types, UNKNOWN_FORM_TYPE)) {
+ LogFormFillDuration(parent_metric + ".Unknown", duration);
+ }
}
// static
-void AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill(
- const base::TimeDelta& duration) {
- UMA_HISTOGRAM_CUSTOM_TIMES(
- "Autofill.FillDuration.FromInteraction.WithoutAutofill",
- duration,
- base::TimeDelta::FromMilliseconds(100),
- base::TimeDelta::FromMinutes(10),
- 50);
+void AutofillMetrics::LogFormFillDuration(const std::string& metric,
+ const base::TimeDelta& duration) {
+ base::UmaHistogramCustomTimes(metric, duration,
+ base::TimeDelta::FromMilliseconds(100),
+ base::TimeDelta::FromMinutes(10), 50);
}
// static
@@ -797,14 +821,118 @@ void AutofillMetrics::LogStoredProfileDaysSinceLastUse(size_t days) {
}
// static
-void AutofillMetrics::LogStoredLocalCreditCardCount(size_t num_local_cards) {
- UMA_HISTOGRAM_COUNTS("Autofill.StoredLocalCreditCardCount", num_local_cards);
-}
+void AutofillMetrics::LogStoredCreditCardMetrics(
+ const std::vector<std::unique_ptr<CreditCard>>& local_cards,
+ const std::vector<std::unique_ptr<CreditCard>>& server_cards,
+ base::TimeDelta disused_data_threshold) {
+ size_t num_local_cards = 0;
+ size_t num_masked_cards = 0;
+ size_t num_unmasked_cards = 0;
+ size_t num_disused_local_cards = 0;
+ size_t num_disused_masked_cards = 0;
+ size_t num_disused_unmasked_cards = 0;
+
+ // Concatenate the local and server cards into one big collection of raw
+ // CreditCard pointers.
+ std::vector<const CreditCard*> credit_cards;
+ credit_cards.reserve(local_cards.size() + server_cards.size());
+ for (const auto* collection : {&local_cards, &server_cards}) {
+ for (const auto& card : *collection) {
+ credit_cards.push_back(card.get());
+ }
+ }
-// static
-void AutofillMetrics::LogStoredServerCreditCardCounts(
- size_t num_masked_cards,
- size_t num_unmasked_cards) {
+ // Iterate over all of the cards and gather metrics.
+ const base::Time now = AutofillClock::Now();
+ for (const CreditCard* card : credit_cards) {
+ const base::TimeDelta time_since_last_use = now - card->use_date();
+ const int days_since_last_use = time_since_last_use.InDays();
+ const int disused_delta =
+ (time_since_last_use > disused_data_threshold) ? 1 : 0;
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.DaysSinceLastUse.StoredCreditCard",
+ days_since_last_use);
+ switch (card->record_type()) {
+ case CreditCard::LOCAL_CARD:
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Local",
+ days_since_last_use);
+ num_local_cards += 1;
+ num_disused_local_cards += disused_delta;
+ break;
+ case CreditCard::MASKED_SERVER_CARD:
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server",
+ days_since_last_use);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Masked",
+ days_since_last_use);
+ num_masked_cards += 1;
+ num_disused_masked_cards += disused_delta;
+ break;
+ case CreditCard::FULL_SERVER_CARD:
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server",
+ days_since_last_use);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Unmasked",
+ days_since_last_use);
+ num_unmasked_cards += 1;
+ num_disused_unmasked_cards += disused_delta;
+ break;
+ }
+ }
+
+ // Calculate some summary info.
+ const size_t num_server_cards = num_masked_cards + num_unmasked_cards;
+ const size_t num_cards = num_local_cards + num_server_cards;
+ const size_t num_disused_server_cards =
+ num_disused_masked_cards + num_disused_unmasked_cards;
+ const size_t num_disused_cards =
+ num_disused_local_cards + num_disused_server_cards;
+
+ // Log the overall counts.
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount", num_cards);
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Local",
+ num_local_cards);
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Server",
+ num_server_cards);
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Server.Masked",
+ num_masked_cards);
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Server.Unmasked",
+ num_unmasked_cards);
+
+ // For card types held by the user, log how many are disused.
+ if (num_cards) {
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardDisusedCount",
+ num_disused_cards);
+ }
+ if (num_local_cards) {
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardDisusedCount.Local",
+ num_disused_local_cards);
+ }
+ if (num_server_cards) {
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardDisusedCount.Server",
+ num_disused_server_cards);
+ }
+ if (num_masked_cards) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.StoredCreditCardDisusedCount.Server.Masked",
+ num_disused_masked_cards);
+ }
+ if (num_unmasked_cards) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Autofill.StoredCreditCardDisusedCount.Server.Unmasked",
+ num_disused_unmasked_cards);
+ }
+
+ // Legacy histogram names.
+ // Validated by:
+ // AutofillMetricsTest.StoredLocalCreditCardCount
+ // AutofillMetricsTest.StoredServerCreditCardCount_Masked
+ // AutofillMetricsTest.StoredServerCreditCardCount_Unmasked
+ // TODO(crbug/762131): Delete these in 2018/Q2 once enough UMA history is
+ // established for the new names.
+ UMA_HISTOGRAM_COUNTS("Autofill.StoredLocalCreditCardCount", num_local_cards);
UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredServerCreditCardCount.Masked",
num_masked_cards);
UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredServerCreditCardCount.Unmasked",
@@ -812,6 +940,18 @@ void AutofillMetrics::LogStoredServerCreditCardCounts(
}
// static
+void AutofillMetrics::LogNumberOfCreditCardsSuppressedForDisuse(
+ size_t num_cards) {
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.CreditCardsSuppressedForDisuse",
+ num_cards);
+}
+
+// static
+void AutofillMetrics::LogNumberOfCreditCardsDeletedForDisuse(size_t num_cards) {
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.CreditCardsDeletedForDisuse", num_cards);
+}
+
+// static
void AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission(
size_t num_profiles) {
UMA_HISTOGRAM_COUNTS(
@@ -833,6 +973,12 @@ void AutofillMetrics::LogNumberOfAddressesSuppressedForDisuse(
}
// static
+void AutofillMetrics::LogNumberOfAddressesDeletedForDisuse(
+ size_t num_profiles) {
+ UMA_HISTOGRAM_COUNTS_1000("Autofill.AddressesDeletedForDisuse", num_profiles);
+}
+
+// static
void AutofillMetrics::LogAddressSuggestionsCount(size_t num_suggestions) {
UMA_HISTOGRAM_COUNTS("Autofill.AddressSuggestionsCount", num_suggestions);
}
@@ -1011,6 +1157,8 @@ AutofillMetrics::FormEventLogger::FormEventLogger(
has_logged_will_submit_(false),
has_logged_submitted_(false),
has_logged_bank_name_available_(false),
+ has_logged_detected_card_in_submitted_form_(false),
+ has_logged_submitted_known_card(false),
logged_suggestion_filled_was_server_data_(false),
logged_suggestion_filled_was_masked_server_card_(false),
form_interactions_ukm_logger_(form_interactions_ukm_logger) {}
@@ -1175,7 +1323,7 @@ void AutofillMetrics::FormEventLogger::OnWillSubmitForm() {
base::RecordAction(base::UserMetricsAction("Autofill_OnWillSubmitForm"));
}
-void AutofillMetrics::FormEventLogger::OnFormSubmitted() {
+void AutofillMetrics::FormEventLogger::OnFormSubmitted(bool force_logging) {
// Not logging this kind of form if we haven't logged a user interaction.
if (!has_logged_interacted_)
return;
@@ -1196,8 +1344,20 @@ void AutofillMetrics::FormEventLogger::OnFormSubmitted() {
Log(AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_SUBMITTED_ONCE);
}
- if (has_logged_suggestions_shown_) {
+ if (has_logged_suggestions_shown_ || force_logging) {
Log(AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE);
+ if (is_for_credit_card_ && !has_logged_suggestion_filled_) {
+ if (!has_logged_detected_card_in_submitted_form_) {
+ Log(AutofillMetrics::
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD);
+ } else if (has_logged_submitted_known_card) {
+ Log(AutofillMetrics::
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD);
+ } else {
+ Log(AutofillMetrics::
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD);
+ }
+ }
}
}
@@ -1205,6 +1365,14 @@ void AutofillMetrics::FormEventLogger::SetBankNameAvailable() {
has_logged_bank_name_available_ = true;
}
+void AutofillMetrics::FormEventLogger::DetectedCardInSubmittedForm() {
+ has_logged_detected_card_in_submitted_form_ = true;
+}
+
+void AutofillMetrics::FormEventLogger::SubmittedKnownCard() {
+ has_logged_submitted_known_card = true;
+}
+
void AutofillMetrics::FormEventLogger::Log(FormEvent event) const {
DCHECK_LT(event, NUM_FORM_EVENTS);
std::string name("Autofill.FormEvents.");
@@ -1284,7 +1452,7 @@ void AutofillMetrics::FormInteractionsUkmLogger::LogSuggestionsShown(
ukm::builders::Autofill_SuggestionsShown(source_id_)
.SetHeuristicType(static_cast<int>(field.heuristic_type()))
.SetHtmlFieldType(static_cast<int>(field.html_type()))
- .SetServerType(static_cast<int>(field.server_type()))
+ .SetServerType(static_cast<int>(field.overall_server_type()))
.SetMillisecondsSinceFormParsed(
MillisecondsSinceFormParsed(form_parsed_timestamp))
.Record(ukm_recorder_);
@@ -1332,7 +1500,7 @@ void AutofillMetrics::FormInteractionsUkmLogger::LogTextFieldDidChange(
ukm::builders::Autofill_TextFieldDidChange(source_id_)
.SetFieldTypeGroup(static_cast<int>(field.Type().group()))
.SetHeuristicType(static_cast<int>(field.heuristic_type()))
- .SetServerType(static_cast<int>(field.server_type()))
+ .SetServerType(static_cast<int>(field.overall_server_type()))
.SetHtmlFieldType(static_cast<int>(field.html_type()))
.SetHtmlFieldMode(static_cast<int>(field.html_mode()))
.SetIsAutofilled(field.is_autofilled)
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index 3d5f9bafd11..7f0dae9c231 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -16,6 +16,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/form_types.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/signatures_util.h"
@@ -24,6 +25,7 @@
namespace autofill {
class AutofillField;
+class CreditCard;
class AutofillMetrics {
public:
@@ -424,6 +426,16 @@ class AutofillMetrics {
// 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,
+ // or Autofill failing to detect the card, one of the following will be
+ // triggered. Only one of the following three metrics will be triggered per
+ // page load.
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD,
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD,
+
NUM_FORM_EVENTS,
};
@@ -683,7 +695,11 @@ class AutofillMetrics {
static void LogServerQueryMetric(ServerQueryMetric metric);
- static void LogUserHappinessMetric(UserHappinessMetric metric);
+ static void LogUserHappinessMetric(UserHappinessMetric metric,
+ FieldTypeGroup field_type_group);
+
+ static void LogUserHappinessMetric(UserHappinessMetric metric,
+ const std::set<FormType>& form_types);
// Logs |event| to the unmask prompt events histogram.
static void LogUnmaskPromptEvent(UnmaskPromptEvent event);
@@ -720,17 +736,16 @@ class AutofillMetrics {
static void LogFormFillDurationFromLoadWithoutAutofill(
const base::TimeDelta& duration);
- // This should be called when a form that has been Autofilled is submitted.
- // |duration| should be the time elapsed between the initial form interaction
- // and submission.
- static void LogFormFillDurationFromInteractionWithAutofill(
+ // This should be called when a form is submitted. |duration| should be the
+ // time elapsed between the initial form interaction and submission. This
+ // metric is sliced by |form_type| and |used_autofill|.
+ static void LogFormFillDurationFromInteraction(
+ const std::set<FormType>& form_types,
+ bool used_autofill,
const base::TimeDelta& duration);
- // This should be called when a fillable form that has not been Autofilled is
- // submitted. |duration| should be the time elapsed between the initial form
- // interaction and submission.
- static void LogFormFillDurationFromInteractionWithoutAutofill(
- const base::TimeDelta& duration);
+ static void LogFormFillDuration(const std::string& metric,
+ const base::TimeDelta& duration);
// This should be called each time a page containing forms is loaded.
static void LogIsAutofillEnabledAtPageLoad(bool enabled);
@@ -750,12 +765,24 @@ class AutofillMetrics {
// called once per address profile each time a new chrome profile is launched.
static void LogStoredProfileDaysSinceLastUse(size_t days);
- // This should be called each time a new chrome profile is launched.
- static void LogStoredLocalCreditCardCount(size_t num_local_cards);
-
- // This should be called each time a new chrome profile is launched.
- static void LogStoredServerCreditCardCounts(size_t num_masked_cards,
- size_t num_unmasked_cards);
+ // Logs various metrics about the local and server cards associated with a
+ // profile. This should be called each time a new chrome profile is launched.
+ static void LogStoredCreditCardMetrics(
+ const std::vector<std::unique_ptr<CreditCard>>& local_cards,
+ const std::vector<std::unique_ptr<CreditCard>>& server_cards,
+ base::TimeDelta disused_data_threshold);
+
+ // Log the number of autofill credit card suggestions suppressed because they
+ // have not been used for a long time and are expired. Note that these cards
+ // are only suppressed when the user has not typed any data into the field
+ // from which autofill is triggered. Credit cards matching something the user
+ // has types are always offered, regardless of how recently they have been
+ // used.
+ static void LogNumberOfCreditCardsSuppressedForDisuse(size_t num_cards);
+
+ // Log the number of autofill credit card deleted during major version upgrade
+ // because they have not been used for a long time and are expired.
+ static void LogNumberOfCreditCardsDeletedForDisuse(size_t num_cards);
// Log the number of profiles available when an autofillable form is
// submitted.
@@ -774,6 +801,12 @@ class AutofillMetrics {
// always offered, regardless of how recently they have been used.
static void LogNumberOfAddressesSuppressedForDisuse(size_t num_profiles);
+ // Log the number of unverified autofill addresses deleted because they have
+ // not been used for a long time, and are not used as billing addresses of
+ // valid credit cards. Note the deletion only happens once per major version
+ // upgrade.
+ static void LogNumberOfAddressesDeletedForDisuse(size_t num_profiles);
+
// Log the number of Autofill address suggestions presented to the user when
// filling a form.
static void LogAddressSuggestionsCount(size_t num_suggestions);
@@ -889,10 +922,14 @@ class AutofillMetrics {
void OnWillSubmitForm();
- void OnFormSubmitted();
+ void OnFormSubmitted(bool force_logging);
void SetBankNameAvailable();
+ void DetectedCardInSubmittedForm();
+
+ void SubmittedKnownCard();
+
private:
void Log(FormEvent event) const;
void Log(BankNameDisplayedFormEvent event) const;
@@ -908,6 +945,8 @@ class AutofillMetrics {
bool has_logged_will_submit_;
bool has_logged_submitted_;
bool has_logged_bank_name_available_;
+ bool has_logged_detected_card_in_submitted_form_;
+ bool has_logged_submitted_known_card;
bool logged_suggestion_filled_was_server_data_;
bool logged_suggestion_filled_was_masked_server_card_;
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index 86aec540f46..9bb357a69b4 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -32,6 +32,7 @@
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
@@ -89,13 +90,14 @@ class TestPersonalDataManager : public PersonalDataManager {
// Overridden to avoid a trip to the database. This should be a no-op except
// for the side-effect of logging the profile count.
void LoadProfiles() override {
+ pending_profiles_query_ = 123;
+ pending_server_profiles_query_ = 124;
{
std::vector<std::unique_ptr<AutofillProfile>> profiles;
web_profiles_.swap(profiles);
std::unique_ptr<WDTypedResult> result = base::MakeUnique<
WDResult<std::vector<std::unique_ptr<AutofillProfile>>>>(
AUTOFILL_PROFILES_RESULT, std::move(profiles));
- pending_profiles_query_ = 123;
OnWebDataServiceRequestDone(pending_profiles_query_, std::move(result));
}
{
@@ -104,7 +106,6 @@ class TestPersonalDataManager : public PersonalDataManager {
std::unique_ptr<WDTypedResult> result = base::MakeUnique<
WDResult<std::vector<std::unique_ptr<AutofillProfile>>>>(
AUTOFILL_PROFILES_RESULT, std::move(profiles));
- pending_server_profiles_query_ = 124;
OnWebDataServiceRequestDone(pending_server_profiles_query_,
std::move(result));
}
@@ -112,13 +113,14 @@ class TestPersonalDataManager : public PersonalDataManager {
// Overridden to avoid a trip to the database.
void LoadCreditCards() override {
+ pending_creditcards_query_ = 125;
+ pending_server_creditcards_query_ = 126;
{
std::vector<std::unique_ptr<CreditCard>> credit_cards;
local_credit_cards_.swap(credit_cards);
std::unique_ptr<WDTypedResult> result =
base::MakeUnique<WDResult<std::vector<std::unique_ptr<CreditCard>>>>(
AUTOFILL_CREDITCARDS_RESULT, std::move(credit_cards));
- pending_creditcards_query_ = 125;
OnWebDataServiceRequestDone(pending_creditcards_query_,
std::move(result));
}
@@ -128,7 +130,6 @@ class TestPersonalDataManager : public PersonalDataManager {
std::unique_ptr<WDTypedResult> result =
base::MakeUnique<WDResult<std::vector<std::unique_ptr<CreditCard>>>>(
AUTOFILL_CREDITCARDS_RESULT, std::move(credit_cards));
- pending_server_creditcards_query_ = 126;
OnWebDataServiceRequestDone(pending_server_creditcards_query_,
std::move(result));
}
@@ -269,7 +270,7 @@ class TestFormStructure : public FormStructure {
AutofillField* form_field = field(i);
ASSERT_TRUE(form_field);
form_field->set_heuristic_type(heuristic_types[i]);
- form_field->set_server_type(server_types[i]);
+ form_field->set_overall_server_type(server_types[i]);
}
UpdateAutofillCount();
@@ -1308,13 +1309,13 @@ TEST_F(AutofillMetricsTest, QualityMetrics_BasedOnAutocomplete) {
AutofillQueryResponseContents response;
// Server response will match with autocomplete.
- response.add_field()->set_autofill_type(NAME_LAST);
+ response.add_field()->set_overall_type_prediction(NAME_LAST);
// Server response will NOT match with autocomplete.
- response.add_field()->set_autofill_type(NAME_FIRST);
+ response.add_field()->set_overall_type_prediction(NAME_FIRST);
// Server response will have no data.
- response.add_field()->set_autofill_type(NO_SERVER_DATA);
+ response.add_field()->set_overall_type_prediction(NO_SERVER_DATA);
// Not logged.
- response.add_field()->set_autofill_type(NAME_MIDDLE);
+ response.add_field()->set_overall_type_prediction(NAME_MIDDLE);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -1408,8 +1409,8 @@ TEST_F(AutofillMetricsTest, UpiVirtualPaymentAddress) {
test::CreateTestFormField("Payment Address", "payment_address", "user@upi",
"text", &field);
form.fields.push_back(field);
- heuristic_types.push_back(UNKNOWN_TYPE);
- server_types.push_back(NO_SERVER_DATA);
+ heuristic_types.push_back(ADDRESS_HOME_LINE1);
+ server_types.push_back(ADDRESS_HOME_LINE1);
// Simulate having seen this form on page load.
autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
@@ -1420,6 +1421,12 @@ TEST_F(AutofillMetricsTest, UpiVirtualPaymentAddress) {
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness", AutofillMetrics::USER_DID_ENTER_UPI_VPA, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_ENTER_UPI_VPA,
+ 1);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Password", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Unknown", 0);
}
// Verify that when a field is annotated with the autocomplete attribute, its
@@ -1978,6 +1985,126 @@ TEST_F(AutofillMetricsTest, UkmDeveloperEngagement_LogUpiVpaTypeHint) {
}
}
+TEST_F(AutofillMetricsTest, LogStoredCreditCardMetrics) {
+ // Helper timestamps for setting up the test data.
+ base::Time now = AutofillClock::Now();
+ base::Time one_month_ago = now - base::TimeDelta::FromDays(30);
+ base::Time::Exploded now_exploded;
+ base::Time::Exploded one_month_ago_exploded;
+ now.LocalExplode(&now_exploded);
+ one_month_ago.LocalExplode(&one_month_ago_exploded);
+
+ std::vector<std::unique_ptr<CreditCard>> local_cards;
+ std::vector<std::unique_ptr<CreditCard>> server_cards;
+ local_cards.reserve(2);
+ server_cards.reserve(10);
+
+ // Create in-use and in-disuse cards of each record type: 1 of each for local,
+ // 2 of each for masked, and 3 of each for unmasked.
+ const std::vector<CreditCard::RecordType> record_types{
+ CreditCard::LOCAL_CARD, CreditCard::MASKED_SERVER_CARD,
+ CreditCard::FULL_SERVER_CARD};
+ int num_cards_of_type = 0;
+ for (auto record_type : record_types) {
+ num_cards_of_type += 1;
+ for (int i = 0; i < num_cards_of_type; ++i) {
+ // Create a card that's still in active use.
+ CreditCard card_in_use = test::GetRandomCreditCard(record_type);
+ card_in_use.set_use_date(now - base::TimeDelta::FromDays(30));
+ card_in_use.set_use_count(10);
+
+ // Create a card that's not in active use.
+ CreditCard card_in_disuse = test::GetRandomCreditCard(record_type);
+ card_in_disuse.SetExpirationYear(one_month_ago_exploded.year);
+ card_in_disuse.SetExpirationMonth(one_month_ago_exploded.month);
+ card_in_disuse.set_use_date(now - base::TimeDelta::FromDays(200));
+ card_in_disuse.set_use_count(10);
+
+ // Add the cards to the personal data manager in the appropriate way.
+ auto& repo =
+ (record_type == CreditCard::LOCAL_CARD) ? local_cards : server_cards;
+ repo.push_back(base::MakeUnique<CreditCard>(std::move(card_in_use)));
+ repo.push_back(base::MakeUnique<CreditCard>(std::move(card_in_disuse)));
+ }
+ }
+
+ // Log the stored credit card metrics for the cards configured above.
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogStoredCreditCardMetrics(local_cards, server_cards,
+ base::TimeDelta::FromDays(180));
+
+ // Validate the basic count metrics.
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount", 1);
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Local", 1);
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Server", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardCount.Server.Masked", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardCount.Server.Unmasked", 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount", 12, 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Local", 2,
+ 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Server",
+ 10, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardCount.Server.Masked", 4, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardCount.Server.Unmasked", 6, 1);
+
+ // Validate the disused count metrics.
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardDisusedCount", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardDisusedCount.Local", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardDisusedCount.Server", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardDisusedCount.Server.Masked", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardDisusedCount.Server.Unmasked", 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardDisusedCount", 6,
+ 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardDisusedCount.Local", 1, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardDisusedCount.Server", 5, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardDisusedCount.Server.Masked", 2, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardDisusedCount.Server.Unmasked", 3, 1);
+
+ // Validate the days-since-last-use metrics.
+ histogram_tester.ExpectTotalCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard", 12);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Local", 2);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server", 10);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Masked", 4);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Unmasked", 6);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard", 30, 6);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard", 200, 6);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Local", 30, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Local", 200, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server", 30, 5);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server", 200, 5);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Masked", 30, 2);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Masked", 200, 2);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Unmasked", 30, 3);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Unmasked", 200, 3);
+}
+
// Test that the profile count is logged correctly.
TEST_F(AutofillMetricsTest, StoredProfileCount) {
// The metric should be logged when the profiles are first loaded.
@@ -3047,6 +3174,231 @@ TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
}
}
+TEST_F(AutofillMetricsTest,
+ CreditCardSubmittedWithoutSelectingSuggestionsNoCard) {
+ EnableWalletSync();
+ // Create a local card for testing, card number is 4111111111111111.
+ personal_data_->RecreateCreditCards(
+ true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Month", "card_month", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+ test::CreateTestFormField("Year", "card_year", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ test::CreateTestFormField("Credit card", "card", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulating submission with suggestion shown, but not selected.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD,
+ 1);
+}
+
+TEST_F(AutofillMetricsTest,
+ CreditCardSubmittedWithoutSelectingSuggestionsUnknownCard) {
+ EnableWalletSync();
+ // Create a local card for testing, card number is 4111111111111111.
+ personal_data_->RecreateCreditCards(
+ true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Month", "card_month", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+ test::CreateTestFormField("Year", "card_year", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ test::CreateTestFormField("Credit card", "card", "5105105105105100", "text",
+ &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulating submission with suggestion shown, but not selected.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD,
+ 1);
+}
+
+TEST_F(AutofillMetricsTest,
+ CreditCardSubmittedWithoutSelectingSuggestionsKnownCard) {
+ EnableWalletSync();
+ // Create a local card for testing, card number is 4111111111111111.
+ personal_data_->RecreateCreditCards(
+ true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Month", "card_month", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+ test::CreateTestFormField("Year", "card_year", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ test::CreateTestFormField("Credit card", "card", "4111111111111111", "text",
+ &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulating submission with suggestion shown, but not selected.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::
+ FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD,
+ 1);
+}
+
+TEST_F(AutofillMetricsTest,
+ ShouldNotLogSubmitWithoutSelectingSuggestionsIfSuggestionFilled) {
+ EnableWalletSync();
+ // Create a local card for testing, card number is 4111111111111111.
+ personal_data_->RecreateCreditCards(
+ true /* include_local_credit_card */,
+ false /* include_masked_server_credit_card */,
+ false /* include_full_server_credit_card */);
+
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Month", "card_month", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+ test::CreateTestFormField("Year", "card_year", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ test::CreateTestFormField("Credit card", "card", "4111111111111111", "text",
+ &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NUMBER);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulating submission with suggestion shown and selected.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ std::string guid("10000000-0000-0000-0000-000000000001");
+ autofill_manager_->FillOrPreviewForm(
+ AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
+ autofill_manager_->MakeFrontendID(guid, std::string()));
+
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.CreditCard",
+ 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(
+ "Autofill.FormEvents.CreditCard",
+ AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD,
+ 0);
+}
+
+TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
+ EnableWalletSync();
+ // Create a profile.
+ personal_data_->RecreateProfile();
+ // Set up our form data.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("State", "state", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(ADDRESS_HOME_STATE);
+ test::CreateTestFormField("City", "city", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(ADDRESS_HOME_CITY);
+ test::CreateTestFormField("Street", "street", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
+
+ // Simulate having seen this form on page load.
+ // |form_structure| will be owned by |autofill_manager_|.
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulating submission with no filled data.
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
+ autofill_manager_->SubmitForm(form, TimeTicks::Now());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.FormEvents.Address",
+ AutofillMetrics::FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD,
+ 0);
+}
+
// Test that we log submitted form events for credit cards.
TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) {
EnableWalletSync();
@@ -4636,9 +4988,244 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
}
}
+TEST_F(AutofillMetricsTest, LogUserHappinessMetric_PasswordForm) {
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL,
+ PASSWORD_FIELD);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Password",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Unknown", 0);
+ }
+
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL,
+ USERNAME_FIELD);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Password",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Unknown", 0);
+ }
+}
+
+TEST_F(AutofillMetricsTest, LogUserHappinessMetric_UnknownForm) {
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL,
+ NO_GROUP);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Unknown",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Password", 0);
+ }
+
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL,
+ TRANSACTION);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Unknown",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Password", 0);
+ }
+}
+
+// Verify that nothing is logging in happiness metrics if no fields in form.
+TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_EmptyForm) {
+ // Load a fillable form.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ std::vector<FormData> forms(1, form);
+
+ // Expect a notification when the form is first seen.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->OnFormsSeen(forms, TimeTicks());
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
+ histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
+ }
+}
+
// Verify that we correctly log user happiness metrics dealing with form
// interaction.
-TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
+TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
+ // Load a fillable form.
+ FormData form;
+ form.name = ASCIIToUTF16("TestForm");
+ form.origin = GURL("http://example.com/form.html");
+ form.action = GURL("http://example.com/submit.html");
+
+ // Construct a valid credit card form with minimal fields.
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("Card Number", "card_number", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_NAME_FULL);
+ test::CreateTestFormField("Expiration", "cc_exp", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_EXP_MONTH);
+ test::CreateTestFormField("Verification", "verification", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(CREDIT_CARD_VERIFICATION_CODE);
+
+ std::vector<FormData> forms(1, form);
+
+ // Expect a notification when the form is first seen.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->OnFormsSeen(forms, TimeTicks());
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
+ AutofillMetrics::FORMS_LOADED, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::FORMS_LOADED, 1);
+ }
+
+ // Simulate typing.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_TYPE, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_TYPE, 1);
+ }
+
+ autofill_manager_->Reset();
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulate suggestions shown twice with separate popups.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true, form, field);
+ autofill_manager_->DidShowSuggestions(true, form, field);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 2);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness", AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 2);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE,
+ 1);
+ }
+
+ autofill_manager_->Reset();
+ autofill_manager_->AddSeenForm(form, field_types, field_types);
+
+ // Simulate suggestions shown twice for a single edit (i.e. multiple
+ // keystrokes in a single field).
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true, form, field);
+ autofill_manager_->DidShowSuggestions(false, form, field);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness", AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE,
+ 1);
+ }
+
+ // Simulate suggestions shown for a different field.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true, form, form.fields[1]);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 1);
+ }
+
+ // Simulate invoking autofill.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness", AutofillMetrics::USER_DID_AUTOFILL_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_AUTOFILL_ONCE,
+ 1);
+ }
+
+ // Simulate editing an autofilled field.
+ {
+ base::HistogramTester histogram_tester;
+ std::string guid("00000000-0000-0000-0000-000000000001");
+ autofill_manager_->FillOrPreviewForm(
+ AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
+ autofill_manager_->MakeFrontendID(std::string(), guid));
+ autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
+ // Simulate a second keystroke; make sure we don't log the metric twice.
+ autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE, 1);
+ }
+
+ // Simulate invoking autofill again.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ }
+
+ // Simulate editing another autofilled field.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->OnTextFieldDidChange(form, form.fields[1], gfx::RectF(),
+ TimeTicks());
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UserHappiness",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UserHappiness.CreditCard",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
+ }
+}
+
+// Verify that we correctly log user happiness metrics dealing with form
+// interaction.
+TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Load a fillable form.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -4661,6 +5248,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
autofill_manager_->OnFormsSeen(forms, TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::FORMS_LOADED, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
+ AutofillMetrics::FORMS_LOADED, 1);
}
// Simulate typing.
@@ -4670,8 +5259,28 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
gfx::RectF(), TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::USER_DID_TYPE, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_TYPE, 1);
}
+ // Simulate suggestions shown twice with separate popups.
+ {
+ base::HistogramTester histogram_tester;
+ autofill_manager_->DidShowSuggestions(true, form, field);
+ autofill_manager_->DidShowSuggestions(true, form, field);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 2);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness", AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 2);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE,
+ 1);
+ }
+
+ autofill_manager_->Reset();
+ autofill_manager_->OnFormsSeen(forms, TimeTicks());
// Simulate suggestions shown twice for a single edit (i.e. multiple
// keystrokes in a single field).
{
@@ -4682,6 +5291,11 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness", AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE,
+ 1);
}
// Simulate suggestions shown for a different field.
@@ -4690,6 +5304,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
autofill_manager_->DidShowSuggestions(true, form, form.fields[1]);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
+ AutofillMetrics::SUGGESTIONS_SHOWN, 1);
}
// Simulate invoking autofill.
@@ -4700,6 +5316,11 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
AutofillMetrics::USER_DID_AUTOFILL, 1);
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness", AutofillMetrics::USER_DID_AUTOFILL_ONCE, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_AUTOFILL_ONCE,
+ 1);
}
// Simulate editing an autofilled field.
@@ -4720,6 +5341,12 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness",
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE, 1);
}
// Simulate invoking autofill again.
@@ -4728,6 +5355,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::USER_DID_AUTOFILL, 1);
+ histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_AUTOFILL, 1);
}
// Simulate editing another autofilled field.
@@ -4738,6 +5367,9 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
histogram_tester.ExpectUniqueSample(
"Autofill.UserHappiness",
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.UserHappiness.Address",
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
}
autofill_manager_->Reset();
@@ -4755,6 +5387,16 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction) {
{UkmTextFieldDidChangeType::kHtmlFieldTypeName, HTML_TYPE_UNSPECIFIED},
{UkmTextFieldDidChangeType::kServerTypeName, NO_SERVER_DATA}},
{{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
+ {UkmTextFieldDidChangeType::kHeuristicTypeName,
+ PHONE_HOME_WHOLE_NUMBER},
+ {UkmTextFieldDidChangeType::kHtmlFieldTypeName, HTML_TYPE_UNSPECIFIED},
+ {UkmTextFieldDidChangeType::kServerTypeName, NO_SERVER_DATA}},
+ {{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
+ {UkmTextFieldDidChangeType::kHeuristicTypeName,
+ PHONE_HOME_WHOLE_NUMBER},
+ {UkmTextFieldDidChangeType::kHtmlFieldTypeName, HTML_TYPE_UNSPECIFIED},
+ {UkmTextFieldDidChangeType::kServerTypeName, NO_SERVER_DATA}},
+ {{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
{UkmTextFieldDidChangeType::kHeuristicTypeName, EMAIL_ADDRESS},
{UkmTextFieldDidChangeType::kHtmlFieldTypeName, HTML_TYPE_UNSPECIFIED},
{UkmTextFieldDidChangeType::kServerTypeName, NO_SERVER_DATA}}});
@@ -4829,7 +5471,6 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
second_form.fields[1].value = ASCIIToUTF16("theking@gmail.com");
second_form.fields[2].value = ASCIIToUTF16("12345678901");
second_form.fields[3].value = ASCIIToUTF16("51512345678");
-
// Expect only form load metrics to be logged if the form is submitted without
// user interaction.
{
@@ -4978,6 +5619,212 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
}
}
+TEST_F(AutofillMetricsTest, FormFillDurationFromInteraction_CreditCardForm) {
+ // Should log time duration with autofill for credit card form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {CREDIT_CARD_FORM}, true /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.CreditCard",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.CreditCard", 0);
+ }
+
+ // Should log time duration without autofill for credit card form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {CREDIT_CARD_FORM}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.CreditCard",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.CreditCard", 0);
+ }
+
+ // Should not log time duration for credit card form if credit card form is
+ // not detected.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {UNKNOWN_FORM_TYPE}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.CreditCard", 0);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.CreditCard", 0);
+ }
+}
+
+TEST_F(AutofillMetricsTest, FormFillDurationFromInteraction_AddressForm) {
+ // Should log time duration with autofill for address form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {ADDRESS_FORM}, true /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Address",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Address", 0);
+ }
+
+ // Should log time duration without autofill for address form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {ADDRESS_FORM}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Address",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Address", 0);
+ }
+
+ // Should not log time duration for address form if address form is not
+ // detected.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {UNKNOWN_FORM_TYPE}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Address", 0);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Address", 0);
+ }
+}
+
+TEST_F(AutofillMetricsTest, FormFillDurationFromInteraction_PasswordForm) {
+ // Should log time duration with autofill for password form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {PASSWORD_FORM}, true /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Password",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Password", 0);
+ }
+
+ // Should log time duration without autofill for password form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {PASSWORD_FORM}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Password",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Password", 0);
+ }
+
+ // Should not log time duration for password form if password form is not
+ // detected.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {UNKNOWN_FORM_TYPE}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Password", 0);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Password", 0);
+ }
+}
+
+TEST_F(AutofillMetricsTest, FormFillDurationFromInteraction_UnknownForm) {
+ // Should log time duration with autofill for unknown form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {UNKNOWN_FORM_TYPE}, true /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Unknown",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Unknown", 0);
+ }
+
+ // Should log time duration without autofill for unknown form.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {UNKNOWN_FORM_TYPE}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Unknown",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Unknown", 0);
+ }
+
+ // Should not log time duration for unknown form if unknown form is not
+ // detected.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {ADDRESS_FORM}, false /* used_autofill */,
+ base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Unknown", 0);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Unknown", 0);
+ }
+}
+
+TEST_F(AutofillMetricsTest, FormFillDurationFromInteraction_MultipleForms) {
+ // Should log time duration with autofill for all forms.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {CREDIT_CARD_FORM, ADDRESS_FORM, PASSWORD_FORM, UNKNOWN_FORM_TYPE},
+ true /* used_autofill */, base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.CreditCard",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Address",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Password",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithAutofill.Unknown",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ }
+
+ // Should log time duration without autofill for all forms.
+ {
+ base::HistogramTester histogram_tester;
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ {CREDIT_CARD_FORM, ADDRESS_FORM, PASSWORD_FORM, UNKNOWN_FORM_TYPE},
+ false /* used_autofill */, base::TimeDelta::FromMilliseconds(2000));
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.CreditCard",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Address",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Password",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ histogram_tester.ExpectTimeBucketCount(
+ "Autofill.FillDuration.FromInteraction.WithoutAutofill.Unknown",
+ base::TimeDelta::FromMilliseconds(2000), 1);
+ }
+}
+
// Verify that we correctly log metrics for profile action on form submission.
TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
base::HistogramTester histogram_tester;
@@ -5147,10 +5994,10 @@ class AutofillMetricsParseQueryResponseTest : public testing::Test {
TEST_F(AutofillMetricsParseQueryResponseTest, ServerHasData) {
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(7);
- response.add_field()->set_autofill_type(30);
- response.add_field()->set_autofill_type(9);
- response.add_field()->set_autofill_type(0);
+ response.add_field()->set_overall_type_prediction(7);
+ response.add_field()->set_overall_type_prediction(30);
+ response.add_field()->set_overall_type_prediction(9);
+ response.add_field()->set_overall_type_prediction(0);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -5166,10 +6013,10 @@ TEST_F(AutofillMetricsParseQueryResponseTest, ServerHasData) {
// logging.
TEST_F(AutofillMetricsParseQueryResponseTest, OneFormNoServerData) {
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(0);
- response.add_field()->set_autofill_type(0);
- response.add_field()->set_autofill_type(9);
- response.add_field()->set_autofill_type(0);
+ response.add_field()->set_overall_type_prediction(0);
+ response.add_field()->set_overall_type_prediction(0);
+ response.add_field()->set_overall_type_prediction(9);
+ response.add_field()->set_overall_type_prediction(0);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -5186,7 +6033,7 @@ TEST_F(AutofillMetricsParseQueryResponseTest, OneFormNoServerData) {
TEST_F(AutofillMetricsParseQueryResponseTest, AllFormsNoServerData) {
AutofillQueryResponseContents response;
for (int i = 0; i < 4; ++i) {
- response.add_field()->set_autofill_type(0);
+ response.add_field()->set_overall_type_prediction(0);
}
std::string response_string;
@@ -5203,10 +6050,10 @@ TEST_F(AutofillMetricsParseQueryResponseTest, AllFormsNoServerData) {
// UMA metric to say there is data.
TEST_F(AutofillMetricsParseQueryResponseTest, PartialNoServerData) {
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(0);
- response.add_field()->set_autofill_type(10);
- response.add_field()->set_autofill_type(0);
- response.add_field()->set_autofill_type(11);
+ response.add_field()->set_overall_type_prediction(0);
+ response.add_field()->set_overall_type_prediction(10);
+ response.add_field()->set_overall_type_prediction(0);
+ response.add_field()->set_overall_type_prediction(11);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
diff --git a/chromium/components/autofill/core/browser/autofill_profile.cc b/chromium/components/autofill/core/browser/autofill_profile.cc
index 0ad521f08f2..43b79bab2a9 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile.cc
@@ -192,19 +192,24 @@ void GetFieldsForDistinguishingProfiles(
}
// Constants for the validity bitfield.
-static const size_t validity_bits_per_type = 2;
-static const size_t number_supported_types_for_validation = 7;
+static const size_t kValidityBitsPerType = 2;
// The order is important to ensure a consistent bitfield value. New values
// should be added at the end NOT at the start or middle.
-static const ServerFieldType
- supported_types_for_validation[number_supported_types_for_validation] = {
- ADDRESS_HOME_COUNTRY,
- ADDRESS_HOME_STATE,
- ADDRESS_HOME_ZIP,
- ADDRESS_HOME_CITY,
- ADDRESS_HOME_DEPENDENT_LOCALITY,
- EMAIL_ADDRESS,
- PHONE_HOME_WHOLE_NUMBER};
+static const ServerFieldType kSupportedTypesForValidation[] = {
+ ADDRESS_HOME_COUNTRY,
+ ADDRESS_HOME_STATE,
+ ADDRESS_HOME_ZIP,
+ ADDRESS_HOME_CITY,
+ ADDRESS_HOME_DEPENDENT_LOCALITY,
+ EMAIL_ADDRESS,
+ PHONE_HOME_WHOLE_NUMBER};
+
+static const size_t kNumSupportedTypesForValidation =
+ sizeof(kSupportedTypesForValidation) /
+ sizeof(kSupportedTypesForValidation[0]);
+
+static_assert(kNumSupportedTypesForValidation * kValidityBitsPerType <= 64,
+ "Not enough bits to encode profile validity information!");
} // namespace
@@ -263,6 +268,7 @@ AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
server_id_ = profile.server_id();
has_converted_ = profile.has_converted();
+ SetValidityFromBitfieldValue(profile.GetValidityBitfieldValue());
return *this;
}
@@ -363,6 +369,7 @@ int AutofillProfile::Compare(const AutofillProfile& profile) const {
bool AutofillProfile::EqualsSansOrigin(const AutofillProfile& profile) const {
return guid() == profile.guid() &&
language_code() == profile.language_code() &&
+ GetValidityBitfieldValue() == profile.GetValidityBitfieldValue() &&
Compare(profile) == 0;
}
@@ -702,15 +709,13 @@ void AutofillProfile::RecordAndLogUse() {
}
AutofillProfile::ValidityState AutofillProfile::GetValidityState(
- ServerFieldType type) {
- // Return valid for types that autofill does not validate.
+ ServerFieldType type) const {
+ // Return UNSUPPORTED for types that autofill does not validate.
if (!IsValidationSupportedForType(type))
return UNSUPPORTED;
- if (!base::ContainsKey(validity_states_, type))
- return UNVALIDATED;
-
- return validity_states_[type];
+ auto it = validity_states_.find(type);
+ return (it == validity_states_.end()) ? UNVALIDATED : it->second;
}
void AutofillProfile::SetValidityState(ServerFieldType type,
@@ -719,36 +724,54 @@ void AutofillProfile::SetValidityState(ServerFieldType type,
if (!IsValidationSupportedForType(type))
return;
- std::map<ServerFieldType, ValidityState>::iterator it =
- validity_states_.find(type);
-
- if (it != validity_states_.end()) {
- it->second = validity;
- } else {
- validity_states_.insert(std::make_pair(type, validity));
- }
+ validity_states_[type] = validity;
}
-bool AutofillProfile::IsValidationSupportedForType(ServerFieldType type) {
- return std::find(supported_types_for_validation,
- supported_types_for_validation +
- number_supported_types_for_validation,
- type) !=
- supported_types_for_validation + number_supported_types_for_validation;
+bool AutofillProfile::IsValidationSupportedForType(ServerFieldType type) const {
+ for (auto supported_type : kSupportedTypesForValidation) {
+ if (type == supported_type)
+ return true;
+ }
+ return false;
}
-int AutofillProfile::GetValidityBitfieldValue() {
+int AutofillProfile::GetValidityBitfieldValue() const {
int validity_value = 0;
size_t field_type_shift = 0;
- for (ServerFieldType supported_type : supported_types_for_validation) {
+ for (ServerFieldType supported_type : kSupportedTypesForValidation) {
DCHECK(GetValidityState(supported_type) != UNSUPPORTED);
validity_value |= GetValidityState(supported_type) << field_type_shift;
- field_type_shift += validity_bits_per_type;
+ field_type_shift += kValidityBitsPerType;
}
+ // Check the the shift is still in range.
+ DCHECK_LE(field_type_shift, 64U);
+
return validity_value;
}
+void AutofillProfile::SetValidityFromBitfieldValue(int bitfield_value) {
+ // Compute the bitmask based on the number a bits per type. For example, this
+ // could be the two least significant bits (0b11).
+ const int kBitmask = (1 << kValidityBitsPerType) - 1;
+
+ for (ServerFieldType supported_type : kSupportedTypesForValidation) {
+ // Apply the bitmask to the bitfield value to get the validity value of the
+ // current |supported_type|.
+ int validity_value = bitfield_value & kBitmask;
+ if (validity_value < 0 || validity_value >= UNSUPPORTED) {
+ NOTREACHED();
+ continue;
+ }
+
+ SetValidityState(supported_type,
+ static_cast<ValidityState>(validity_value));
+
+ // Shift the bitfield value to access the validity of the next field type.
+ bitfield_value = bitfield_value >> kValidityBitsPerType;
+ }
+}
+
base::string16 AutofillProfile::GetInfoImpl(
const AutofillType& type,
const std::string& app_locale) const {
@@ -908,6 +931,7 @@ FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) {
bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
return origin() == profile.origin() &&
language_code() == profile.language_code() &&
+ GetValidityBitfieldValue() == profile.GetValidityBitfieldValue() &&
Compare(profile) == 0;
}
@@ -928,7 +952,8 @@ std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)) << " "
<< UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) << " "
<< profile.language_code() << " "
- << UTF16ToUTF8(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
+ << UTF16ToUTF8(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)) << " "
+ << profile.GetValidityBitfieldValue();
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile.h b/chromium/components/autofill/core/browser/autofill_profile.h
index e9f7f803dfd..6cde979ce02 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.h
+++ b/chromium/components/autofill/core/browser/autofill_profile.h
@@ -99,7 +99,7 @@ class AutofillProfile : public AutofillDataModel {
bool EqualsSansOrigin(const AutofillProfile& profile) const;
// Same as operator==, but ignores differences in guid and cares about
- // differences in usage stats.
+ // differences in usage stats and validity state.
bool EqualsForSyncPurposes(const AutofillProfile& profile) const;
// Equality operators compare GUIDs, origins, language code, and the contents
@@ -197,16 +197,20 @@ class AutofillProfile : public AutofillDataModel {
void set_has_converted(bool has_converted) { has_converted_ = has_converted; }
// Returns the validity state of the specified autofill type.
- ValidityState GetValidityState(ServerFieldType type);
+ ValidityState GetValidityState(ServerFieldType type) const;
// Sets the validity state of the specified autofill type.
void SetValidityState(ServerFieldType type, ValidityState validity);
// Returns whether autofill does the validation of the specified |type|.
- bool IsValidationSupportedForType(ServerFieldType type);
+ bool IsValidationSupportedForType(ServerFieldType type) const;
// Returns the bitfield value representing the validity state of this profile.
- int GetValidityBitfieldValue();
+ int GetValidityBitfieldValue() const;
+
+ // Sets the validity state of the profile based on the specified
+ // |bitfield_value|.
+ void SetValidityFromBitfieldValue(int bitfield_value);
private:
typedef std::vector<const FormGroup*> FormGroupList;
diff --git a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
index 07883a8ed51..56f5143c3ce 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -1302,4 +1302,199 @@ TEST(AutofillProfileTest, GetValidityBitfieldValue_Mixed) {
EXPECT_EQ(13229, profile.GetValidityBitfieldValue());
}
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_Country) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b01
+ profile.SetValidityFromBitfieldValue(1);
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+
+ // 0b10
+ profile.SetValidityFromBitfieldValue(2);
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+
+ // 0b11
+ profile.SetValidityFromBitfieldValue(3);
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_State) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b0100
+ profile.SetValidityFromBitfieldValue(4);
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+
+ // 0b1000
+ profile.SetValidityFromBitfieldValue(8);
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+
+ // 0b1100
+ profile.SetValidityFromBitfieldValue(12);
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_Zip) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b010000
+ profile.SetValidityFromBitfieldValue(16);
+ EXPECT_EQ(AutofillProfile::EMPTY, profile.GetValidityState(ADDRESS_HOME_ZIP));
+
+ // 0b100000
+ profile.SetValidityFromBitfieldValue(32);
+ EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP));
+
+ // 0b110000
+ profile.SetValidityFromBitfieldValue(48);
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_ZIP));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_City) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b01000000
+ profile.SetValidityFromBitfieldValue(64);
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_CITY));
+
+ // 0b10000000
+ profile.SetValidityFromBitfieldValue(128);
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_CITY));
+
+ // 0b11000000
+ profile.SetValidityFromBitfieldValue(192);
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_CITY));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_DependentLocality) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b0100000000
+ profile.SetValidityFromBitfieldValue(256);
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY));
+
+ // 0b1000000000
+ profile.SetValidityFromBitfieldValue(512);
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY));
+
+ // 0b1100000000
+ profile.SetValidityFromBitfieldValue(768);
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_Email) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b010000000000
+ profile.SetValidityFromBitfieldValue(1024);
+ EXPECT_EQ(AutofillProfile::EMPTY, profile.GetValidityState(EMAIL_ADDRESS));
+
+ // 0b100000000000
+ profile.SetValidityFromBitfieldValue(2048);
+ EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(EMAIL_ADDRESS));
+
+ // 0b110000000000
+ profile.SetValidityFromBitfieldValue(3072);
+ EXPECT_EQ(AutofillProfile::INVALID, profile.GetValidityState(EMAIL_ADDRESS));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_Phone) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b01000000000000
+ profile.SetValidityFromBitfieldValue(4096);
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
+
+ // 0b10000000000000
+ profile.SetValidityFromBitfieldValue(8192);
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
+
+ // 0b11000000000000
+ profile.SetValidityFromBitfieldValue(12288);
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
+}
+
+TEST(AutofillProfileTest, SetValidityFromBitfieldValue_Mixed) {
+ AutofillProfile profile;
+
+ // By default all validity statuses should be set to UNVALIDATED, thus the
+ // bitfield value should be empty.
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+
+ // 0b01110011010010
+ profile.SetValidityFromBitfieldValue(7378);
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(AutofillProfile::UNVALIDATED,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+ EXPECT_EQ(AutofillProfile::EMPTY, profile.GetValidityState(ADDRESS_HOME_ZIP));
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_CITY));
+ EXPECT_EQ(AutofillProfile::UNVALIDATED,
+ profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY));
+ EXPECT_EQ(AutofillProfile::INVALID, profile.GetValidityState(EMAIL_ADDRESS));
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
+
+ // 0b11001110101101
+ profile.SetValidityFromBitfieldValue(13229);
+ EXPECT_EQ(AutofillProfile::EMPTY,
+ profile.GetValidityState(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_STATE));
+ EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP));
+ EXPECT_EQ(AutofillProfile::VALID,
+ profile.GetValidityState(ADDRESS_HOME_CITY));
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY));
+ EXPECT_EQ(AutofillProfile::UNVALIDATED,
+ profile.GetValidityState(EMAIL_ADDRESS));
+ EXPECT_EQ(AutofillProfile::INVALID,
+ profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
+}
+
} // namespace autofill
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 52328bd1f6e..456920617a2 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_validator_unittest.cc
@@ -223,7 +223,7 @@ TEST_F(AutofillProfileValidatorTest, ValidateProfile_InvalidEmail) {
AutofillProfile profile(autofill::test::GetFullValidProfile());
profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email."));
- set_expected_status(AutofillProfile::VALID);
+ set_expected_status(AutofillProfile::INVALID);
validator_->ValidateProfile(&profile, std::move(onvalidated_cb_));
}
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index aa3b5952e4b..e0543b1eaf8 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -7,6 +7,8 @@
#include <string>
#include "base/guid.h"
+#include "base/rand_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_manager.h"
@@ -26,12 +28,26 @@
#include "components/signin/core/browser/account_fetcher_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/common/signin_pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
namespace autofill {
namespace test {
+namespace {
+
+std::string GetRandomCardNumber() {
+ const size_t length = 16;
+ std::string value;
+ value.reserve(length);
+ for (size_t i = 0; i < length; ++i)
+ value.push_back(static_cast<char>(base::RandInt('0', '9')));
+ return value;
+}
+
+} // namespace
+
std::unique_ptr<PrefService> PrefServiceForTesting() {
scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
new user_prefs::PrefRegistrySyncable());
@@ -63,7 +79,7 @@ std::unique_ptr<PrefService> PrefServiceForTesting(
registry->RegisterInt64Pref(AccountFetcherService::kLastUpdatePref, 0);
PrefServiceFactory factory;
- factory.set_user_prefs(make_scoped_refptr(new TestingPrefStore()));
+ factory.set_user_prefs(base::MakeRefCounted<TestingPrefStore>());
return factory.Create(registry);
}
@@ -294,6 +310,39 @@ CreditCard GetMaskedServerCardAmex() {
return credit_card;
}
+CreditCard GetRandomCreditCard(CreditCard::RecordType record_type) {
+ static const char* const kNetworks[] = {
+ kAmericanExpressCard,
+ kDinersCard,
+ kDiscoverCard,
+ kEloCard,
+ kGenericCard,
+ kJCBCard,
+ kMasterCard,
+ kMirCard,
+ kUnionPay,
+ kVisaCard,
+ };
+ constexpr size_t kNumNetworks = sizeof(kNetworks) / sizeof(kNetworks[0]);
+ base::Time::Exploded now;
+ base::Time::Now().LocalExplode(&now);
+
+ CreditCard credit_card =
+ (record_type == CreditCard::LOCAL_CARD)
+ ? CreditCard(base::GenerateGUID(), "http://www.example.com")
+ : CreditCard(record_type, base::GenerateGUID().substr(24));
+ test::SetCreditCardInfo(
+ &credit_card, "Justin Thyme", GetRandomCardNumber().c_str(),
+ base::StringPrintf("%d", base::RandInt(1, 12)).c_str(),
+ base::StringPrintf("%d", now.year + base::RandInt(1, 4)).c_str(), "1");
+ if (record_type == CreditCard::MASKED_SERVER_CARD) {
+ credit_card.SetNetworkForMaskedCard(
+ kNetworks[base::RandInt(0, kNumNetworks - 1)]);
+ }
+
+ return credit_card;
+}
+
void SetProfileInfo(AutofillProfile* profile,
const char* first_name, const char* middle_name,
const char* last_name, const char* email, const char* company,
@@ -362,8 +411,7 @@ void SetServerCreditCards(AutofillTable* table,
for (const CreditCard& card : cards) {
if (card.record_type() != CreditCard::FULL_SERVER_CARD)
continue;
-
- table->UnmaskServerCreditCard(card, card.number());
+ ASSERT_TRUE(table->UnmaskServerCreditCard(card, card.number()));
}
}
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.h b/chromium/components/autofill/core/browser/autofill_test_utils.h
index 708f3a640be..9bb13adcb24 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
@@ -22,7 +23,6 @@ namespace autofill {
class AutofillProfile;
class AutofillTable;
-class CreditCard;
struct FormData;
struct FormFieldData;
@@ -102,6 +102,10 @@ CreditCard GetVerifiedCreditCard2();
CreditCard GetMaskedServerCard();
CreditCard GetMaskedServerCardAmex();
+// Returns a randomly generated credit card of |record_type|. Note that the
+// card is not guaranteed to be valid/sane from a card validation standpoint.
+CreditCard GetRandomCreditCard(CreditCard::RecordType record_Type);
+
// A unit testing utility that is common to a number of the Autofill unit
// tests. |SetProfileInfo| provides a quick way to populate a profile with
// c-strings.
diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc
index 76ea54a319f..66de467ae8a 100644
--- a/chromium/components/autofill/core/browser/credit_card.cc
+++ b/chromium/components/autofill/core/browser/credit_card.cc
@@ -12,6 +12,7 @@
#include <string>
#include "base/guid.h"
+#include "base/i18n/string_search.h"
#include "base/i18n/time_formatting.h"
#include "base/i18n/unicodestring.h"
#include "base/logging.h"
@@ -31,7 +32,6 @@
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_clock.h"
-#include "components/autofill/core/common/autofill_l10n_util.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/grit/components_scaled_resources.h"
@@ -916,34 +916,36 @@ bool CreditCard::ConvertMonth(const base::string16& month,
return false;
// Otherwise, try parsing the |month| as a named month, e.g. "January" or
- // "Jan".
- l10n::CaseInsensitiveCompare compare;
+ // "Jan" in the user's locale.
UErrorCode status = U_ZERO_ERROR;
icu::Locale locale(app_locale.c_str());
icu::DateFormatSymbols date_format_symbols(locale, status);
DCHECK(status == U_ZERO_ERROR || status == U_USING_FALLBACK_WARNING ||
status == U_USING_DEFAULT_WARNING);
-
+ // Full months (January, Janvier, etc.)
int32_t num_months;
const icu::UnicodeString* months = date_format_symbols.getMonths(num_months);
for (int32_t i = 0; i < num_months; ++i) {
const base::string16 icu_month(
base::i18n::UnicodeStringToString16(months[i]));
- if (compare.StringsEqual(icu_month, month)) {
+ // We look for the ICU-defined month in |month|.
+ if (base::i18n::StringSearchIgnoringCaseAndAccents(icu_month, month,
+ nullptr, nullptr)) {
*num = i + 1; // Adjust from 0-indexed to 1-indexed.
return true;
}
}
-
+ // Abbreviated months (jan., janv., fév.) Some abbreviations have . at the end
+ // (e.g., "janv." in French). The period is removed.
months = date_format_symbols.getShortMonths(num_months);
- // Some abbreviations have . at the end (e.g., "janv." in French). We don't
- // care about matching that.
base::string16 trimmed_month;
base::TrimString(month, ASCIIToUTF16("."), &trimmed_month);
for (int32_t i = 0; i < num_months; ++i) {
base::string16 icu_month(base::i18n::UnicodeStringToString16(months[i]));
base::TrimString(icu_month, ASCIIToUTF16("."), &icu_month);
- if (compare.StringsEqual(icu_month, trimmed_month)) {
+ // We look for the ICU-defined month in |trimmed_month|.
+ if (base::i18n::StringSearchIgnoringCaseAndAccents(icu_month, trimmed_month,
+ nullptr, nullptr)) {
*num = i + 1; // Adjust from 0-indexed to 1-indexed.
return true;
}
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index 531a20758c1..98393571074 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -277,7 +277,7 @@ std::ostream& operator<<(
const autofill::AutofillQueryResponseContents& response) {
out << "upload_required: " << response.upload_required();
for (const auto& field : response.field()) {
- out << "\nautofill_type: " << field.autofill_type();
+ out << "\nautofill_type: " << field.overall_type_prediction();
}
return out;
}
@@ -500,8 +500,8 @@ void FormStructure::ParseQueryResponse(
if (current_field == response.field().end())
break;
- ServerFieldType field_type =
- static_cast<ServerFieldType>(current_field->autofill_type());
+ ServerFieldType field_type = static_cast<ServerFieldType>(
+ current_field->overall_type_prediction());
query_response_has_no_server_data &= field_type == NO_SERVER_DATA;
// UNKNOWN_TYPE is reserved for use by the client.
@@ -511,7 +511,19 @@ void FormStructure::ParseQueryResponse(
if (heuristic_type != UNKNOWN_TYPE)
heuristics_detected_fillable_field = true;
- field->set_server_type(field_type);
+ field->set_overall_server_type(field_type);
+ std::vector<AutofillQueryResponseContents::Field::FieldPrediction>
+ server_predictions;
+ if (current_field->predictions_size() == 0) {
+ AutofillQueryResponseContents::Field::FieldPrediction field_prediction;
+ field_prediction.set_type(field_type);
+ server_predictions.push_back(field_prediction);
+ } else {
+ server_predictions.assign(current_field->predictions().begin(),
+ current_field->predictions().end());
+ }
+ field->set_server_predictions(std::move(server_predictions));
+
if (heuristic_type != field->Type().GetStorableType())
query_response_overrode_heuristics = true;
@@ -552,6 +564,7 @@ std::vector<FormDataPredictions> FormStructure::GetFieldTypePredictions(
form.data.origin = form_structure->source_url_;
form.data.action = form_structure->target_url_;
form.data.is_form_tag = form_structure->is_form_tag_;
+ form.data.is_formless_checkout = form_structure->is_formless_checkout_;
form.signature = form_structure->FormSignatureAsStr();
for (const auto& field : form_structure->fields_) {
@@ -562,7 +575,7 @@ std::vector<FormDataPredictions> FormStructure::GetFieldTypePredictions(
annotated_field.heuristic_type =
AutofillType(field->heuristic_type()).ToString();
annotated_field.server_type =
- AutofillType(field->server_type()).ToString();
+ AutofillType(field->overall_server_type()).ToString();
annotated_field.overall_type = field->Type().ToString();
annotated_field.parseable_name =
base::UTF16ToUTF8(field->parseable_name());
@@ -665,7 +678,8 @@ void FormStructure::UpdateFromCache(const FormStructure& cached_form,
// Transfer attributes of the cached AutofillField to the newly created
// AutofillField.
field->set_heuristic_type(cached_field->second->heuristic_type());
- field->set_server_type(cached_field->second->server_type());
+ field->set_overall_server_type(
+ cached_field->second->overall_server_type());
field->SetHtmlType(cached_field->second->html_type(),
cached_field->second->html_mode());
if (apply_is_autofilled) {
@@ -713,10 +727,9 @@ void FormStructure::LogQualityMetrics(
for (size_t i = 0; i < field_count(); ++i) {
auto* const field = this->field(i);
-
if (IsUPIVirtualPaymentAddress(field->value)) {
AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_ENTER_UPI_VPA);
+ AutofillMetrics::USER_DID_ENTER_UPI_VPA, field->Type().group());
}
form_interactions_ukm_logger->LogFieldFillStatus(*this, *field,
@@ -774,8 +787,7 @@ void FormStructure::LogQualityMetrics(
DCHECK(!submission_time.is_null());
// The |load_time| might be unset, in the case that the form was
- // dynamically
- // added to the DOM.
+ // dynamically added to the DOM.
if (!load_time.is_null()) {
// Submission should always chronologically follow form load.
DCHECK(submission_time > load_time);
@@ -792,13 +804,8 @@ void FormStructure::LogQualityMetrics(
// Submission should always chronologically follow interaction.
DCHECK(submission_time > interaction_time);
base::TimeDelta elapsed = submission_time - interaction_time;
- if (did_autofill_some_possible_fields) {
- AutofillMetrics::LogFormFillDurationFromInteractionWithAutofill(
- elapsed);
- } else {
- AutofillMetrics::LogFormFillDurationFromInteractionWithoutAutofill(
- elapsed);
- }
+ AutofillMetrics::LogFormFillDurationFromInteraction(
+ GetFormTypes(), did_autofill_some_possible_fields, elapsed);
}
}
if (form_interactions_ukm_logger->url() != source_url())
@@ -1421,4 +1428,13 @@ base::string16 FormStructure::FindLongestCommonPrefix(
return filtered_strings[0];
}
+std::set<FormType> FormStructure::GetFormTypes() const {
+ std::set<FormType> form_types;
+ for (const auto& field : fields_) {
+ form_types.insert(
+ FormTypes::FieldTypeGroupToFormType(field->Type().group()));
+ }
+ return form_types;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index a1094eb7d95..d02b31beeab 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -21,6 +21,7 @@
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/form_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "url/gurl.h"
@@ -243,6 +244,9 @@ class FormStructure {
// Returns a FormData containing the data this form structure knows about.
FormData ToFormData() const;
+ // Returns the possible form types.
+ std::set<FormType> GetFormTypes() const;
+
bool operator==(const FormData& form) const;
bool operator!=(const FormData& form) const;
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index ff6cd263868..3548474f66b 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -943,8 +943,8 @@ TEST_F(FormStructureTest,
EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(0)->heuristic_type());
EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(1)->heuristic_type());
- EXPECT_EQ(NO_SERVER_DATA, form_structure->field(0)->server_type());
- EXPECT_EQ(NO_SERVER_DATA, form_structure->field(1)->server_type());
+ EXPECT_EQ(NO_SERVER_DATA, form_structure->field(0)->overall_server_type());
+ EXPECT_EQ(NO_SERVER_DATA, form_structure->field(1)->overall_server_type());
}
// Tests the heuristics and server predictions are not run for forms with less
@@ -978,8 +978,8 @@ TEST_F(FormStructureTest,
EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(0)->heuristic_type());
EXPECT_EQ(UNKNOWN_TYPE, form_structure->field(1)->heuristic_type());
- EXPECT_EQ(NO_SERVER_DATA, form_structure->field(0)->server_type());
- EXPECT_EQ(NO_SERVER_DATA, form_structure->field(1)->server_type());
+ EXPECT_EQ(NO_SERVER_DATA, form_structure->field(0)->overall_server_type());
+ EXPECT_EQ(NO_SERVER_DATA, form_structure->field(1)->overall_server_type());
}
// Even with an 'autocomplete' attribute set, ShouldBeCrowdsourced() should
@@ -3768,10 +3768,17 @@ TEST_F(FormStructureTest, ParseQueryResponse) {
forms.push_back(&form_structure2);
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(7);
- response.add_field()->set_autofill_type(30);
- response.add_field()->set_autofill_type(9);
- response.add_field()->set_autofill_type(0);
+ AutofillQueryResponseContents_Field* field0 = response.add_field();
+ field0->set_overall_type_prediction(7);
+ AutofillQueryResponseContents_Field_FieldPrediction* field_prediction0 =
+ field0->add_predictions();
+ field_prediction0->set_type(7);
+ AutofillQueryResponseContents_Field_FieldPrediction* field_prediction1 =
+ field0->add_predictions();
+ field_prediction1->set_type(22);
+ response.add_field()->set_overall_type_prediction(30);
+ response.add_field()->set_overall_type_prediction(9);
+ response.add_field()->set_overall_type_prediction(0);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -3779,10 +3786,19 @@ TEST_F(FormStructureTest, ParseQueryResponse) {
ASSERT_GE(forms[0]->field_count(), 2U);
ASSERT_GE(forms[1]->field_count(), 2U);
- EXPECT_EQ(7, forms[0]->field(0)->server_type());
- EXPECT_EQ(30, forms[0]->field(1)->server_type());
- EXPECT_EQ(9, forms[1]->field(0)->server_type());
- EXPECT_EQ(0, forms[1]->field(1)->server_type());
+ EXPECT_EQ(7, forms[0]->field(0)->overall_server_type());
+ ASSERT_EQ(2U, forms[0]->field(0)->server_predictions().size());
+ EXPECT_EQ(7U, forms[0]->field(0)->server_predictions()[0].type());
+ EXPECT_EQ(22U, forms[0]->field(0)->server_predictions()[1].type());
+ EXPECT_EQ(30, forms[0]->field(1)->overall_server_type());
+ ASSERT_EQ(1U, forms[0]->field(1)->server_predictions().size());
+ EXPECT_EQ(30U, forms[0]->field(1)->server_predictions()[0].type());
+ EXPECT_EQ(9, forms[1]->field(0)->overall_server_type());
+ ASSERT_EQ(1U, forms[1]->field(0)->server_predictions().size());
+ EXPECT_EQ(9U, forms[1]->field(0)->server_predictions()[0].type());
+ EXPECT_EQ(0, forms[1]->field(1)->overall_server_type());
+ ASSERT_EQ(1U, forms[1]->field(1)->server_predictions().size());
+ EXPECT_EQ(0U, forms[1]->field(1)->server_predictions()[0].type());
}
TEST_F(FormStructureTest, ParseQueryResponseAuthorDefinedTypes) {
@@ -3808,8 +3824,8 @@ TEST_F(FormStructureTest, ParseQueryResponseAuthorDefinedTypes) {
forms.front()->DetermineHeuristicTypes(nullptr /* ukm_service */);
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(EMAIL_ADDRESS);
- response.add_field()->set_autofill_type(ACCOUNT_CREATION_PASSWORD);
+ response.add_field()->set_overall_type_prediction(EMAIL_ADDRESS);
+ response.add_field()->set_overall_type_prediction(ACCOUNT_CREATION_PASSWORD);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -3817,9 +3833,10 @@ TEST_F(FormStructureTest, ParseQueryResponseAuthorDefinedTypes) {
ASSERT_GE(forms[0]->field_count(), 2U);
// Server type is parsed from the response and is the end result type.
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(0)->server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(0)->overall_server_type());
EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(0)->Type().GetStorableType());
- EXPECT_EQ(ACCOUNT_CREATION_PASSWORD, forms[0]->field(1)->server_type());
+ EXPECT_EQ(ACCOUNT_CREATION_PASSWORD,
+ forms[0]->field(1)->overall_server_type());
// TODO(crbug.com/613666): Should be a properly defined type, and not
// UNKNOWN_TYPE.
EXPECT_EQ(UNKNOWN_TYPE, forms[0]->field(1)->Type().GetStorableType());
@@ -3852,10 +3869,11 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeLoneField) {
forms.push_back(&form_structure);
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(NAME_FULL);
- response.add_field()->set_autofill_type(ADDRESS_HOME_LINE1);
- response.add_field()->set_autofill_type(CREDIT_CARD_EXP_MONTH); // Uh-oh!
- response.add_field()->set_autofill_type(EMAIL_ADDRESS);
+ response.add_field()->set_overall_type_prediction(NAME_FULL);
+ response.add_field()->set_overall_type_prediction(ADDRESS_HOME_LINE1);
+ response.add_field()->set_overall_type_prediction(
+ CREDIT_CARD_EXP_MONTH); // Uh-oh!
+ response.add_field()->set_overall_type_prediction(EMAIL_ADDRESS);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -3869,10 +3887,10 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeLoneField) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(NAME_FULL, forms[0]->field(0)->server_type());
- EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->server_type());
- EXPECT_EQ(NO_SERVER_DATA, forms[0]->field(2)->server_type());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->server_type());
+ EXPECT_EQ(NAME_FULL, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->overall_server_type());
+ EXPECT_EQ(NO_SERVER_DATA, forms[0]->field(2)->overall_server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->overall_server_type());
}
// Sanity check that the enable/disabled works.
@@ -3884,10 +3902,10 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeLoneField) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(NAME_FULL, forms[0]->field(0)->server_type());
- EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(2)->server_type());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->server_type());
+ EXPECT_EQ(NAME_FULL, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(2)->overall_server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(3)->overall_server_type());
}
}
@@ -3914,9 +3932,9 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
forms.push_back(&form_structure);
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(CREDIT_CARD_NAME_FIRST);
- response.add_field()->set_autofill_type(CREDIT_CARD_NAME_LAST);
- response.add_field()->set_autofill_type(EMAIL_ADDRESS);
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_FIRST);
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_LAST);
+ response.add_field()->set_overall_type_prediction(EMAIL_ADDRESS);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -3930,9 +3948,9 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(3U, forms[0]->field_count());
- EXPECT_EQ(NAME_FIRST, forms[0]->field(0)->server_type());
- EXPECT_EQ(NAME_LAST, forms[0]->field(1)->server_type());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->server_type());
+ EXPECT_EQ(NAME_FIRST, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(NAME_LAST, forms[0]->field(1)->overall_server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->overall_server_type());
}
// Sanity check that the enable/disabled works.
@@ -3944,9 +3962,10 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeCCName) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(3U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FIRST, forms[0]->field(0)->server_type());
- EXPECT_EQ(CREDIT_CARD_NAME_LAST, forms[0]->field(1)->server_type());
- EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->server_type());
+ EXPECT_EQ(CREDIT_CARD_NAME_FIRST,
+ forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_NAME_LAST, forms[0]->field(1)->overall_server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, forms[0]->field(2)->overall_server_type());
}
}
@@ -3981,11 +4000,13 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
forms.push_back(&form_structure);
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(CREDIT_CARD_NAME_FULL);
- response.add_field()->set_autofill_type(CREDIT_CARD_NUMBER);
- response.add_field()->set_autofill_type(CREDIT_CARD_EXP_MONTH);
- response.add_field()->set_autofill_type(CREDIT_CARD_EXP_2_DIGIT_YEAR);
- response.add_field()->set_autofill_type(CREDIT_CARD_EXP_MONTH); // Uh-oh!
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_FULL);
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_NUMBER);
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_EXP_MONTH);
+ response.add_field()->set_overall_type_prediction(
+ CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ response.add_field()->set_overall_type_prediction(
+ CREDIT_CARD_EXP_MONTH); // Uh-oh!
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -3999,11 +4020,12 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(5U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->server_type());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(2)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR, forms[0]->field(3)->server_type());
- EXPECT_EQ(NO_SERVER_DATA, forms[0]->field(4)->server_type());
+ EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(2)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ forms[0]->field(3)->overall_server_type());
+ EXPECT_EQ(NO_SERVER_DATA, forms[0]->field(4)->overall_server_type());
}
// Sanity check that the enable/disabled works.
@@ -4015,11 +4037,12 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_1) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(5U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->server_type());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(2)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR, forms[0]->field(3)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(4)->server_type());
+ EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(2)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ forms[0]->field(3)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(4)->overall_server_type());
}
}
@@ -4050,10 +4073,12 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
forms.push_back(&form_structure);
AutofillQueryResponseContents response;
- response.add_field()->set_autofill_type(CREDIT_CARD_NAME_FULL);
- response.add_field()->set_autofill_type(CREDIT_CARD_NUMBER);
- response.add_field()->set_autofill_type(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
- response.add_field()->set_autofill_type(CREDIT_CARD_EXP_MONTH); // Uh-oh!
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_FULL);
+ response.add_field()->set_overall_type_prediction(CREDIT_CARD_NUMBER);
+ response.add_field()->set_overall_type_prediction(
+ CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
+ response.add_field()->set_overall_type_prediction(
+ CREDIT_CARD_EXP_MONTH); // Uh-oh!
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
@@ -4066,11 +4091,11 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->server_type());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->server_type());
+ EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->overall_server_type());
EXPECT_EQ(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
- forms[0]->field(2)->server_type());
- EXPECT_EQ(NO_SERVER_DATA, forms[0]->field(3)->server_type());
+ forms[0]->field(2)->overall_server_type());
+ EXPECT_EQ(NO_SERVER_DATA, forms[0]->field(3)->overall_server_type());
}
// Sanity check that the enable/disabled works.
@@ -4081,11 +4106,11 @@ TEST_F(FormStructureTest, ParseQueryResponse_RationalizeMultiMonth_2) {
FormStructure::ParseQueryResponse(response_string, forms);
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
- EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->server_type());
- EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->server_type());
+ EXPECT_EQ(CREDIT_CARD_NAME_FULL, forms[0]->field(0)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_NUMBER, forms[0]->field(1)->overall_server_type());
EXPECT_EQ(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
- forms[0]->field(2)->server_type());
- EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(3)->server_type());
+ forms[0]->field(2)->overall_server_type());
+ EXPECT_EQ(CREDIT_CARD_EXP_MONTH, forms[0]->field(3)->overall_server_type());
}
}
diff --git a/chromium/components/autofill/core/browser/form_types.cc b/chromium/components/autofill/core/browser/form_types.cc
new file mode 100644
index 00000000000..86f694cc7f7
--- /dev/null
+++ b/chromium/components/autofill/core/browser/form_types.cc
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/form_types.h"
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+
+// static
+FormType FormTypes::FieldTypeGroupToFormType(FieldTypeGroup field_type_group) {
+ switch (field_type_group) {
+ case CREDIT_CARD:
+ return CREDIT_CARD_FORM;
+ case USERNAME_FIELD:
+ case PASSWORD_FIELD:
+ return PASSWORD_FORM;
+ case NO_GROUP:
+ case TRANSACTION:
+ return UNKNOWN_FORM_TYPE;
+ default:
+ // Assuming it's an address form by process of elimination.
+ return ADDRESS_FORM;
+ }
+}
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_types.h b/chromium/components/autofill/core/browser/form_types.h
new file mode 100644
index 00000000000..2c36914c826
--- /dev/null
+++ b/chromium/components/autofill/core/browser/form_types.h
@@ -0,0 +1,26 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_TYPES_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_TYPES_H_
+
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+
+enum FormType : int {
+ UNKNOWN_FORM_TYPE,
+ ADDRESS_FORM,
+ CREDIT_CARD_FORM,
+ PASSWORD_FORM
+};
+
+class FormTypes {
+ public:
+ static FormType FieldTypeGroupToFormType(FieldTypeGroup field_type_group);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_TYPES_H_
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index f2af614cd3c..4916d3a18ab 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -16,10 +16,10 @@
#include "base/i18n/case_conversion.h"
#include "base/i18n/timezone.h"
#include "base/memory/ptr_util.h"
-#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/address_i18n.h"
@@ -63,21 +63,34 @@ const int LOCAL_GUID_LENGTH = 36;
constexpr base::TimeDelta kDisusedProfileTimeDelta =
base::TimeDelta::FromDays(180);
+constexpr base::TimeDelta kDisusedCreditCardTimeDelta =
+ base::TimeDelta::FromDays(180);
+constexpr base::TimeDelta kDisusedCreditCardDeletionTimeDelta =
+ base::TimeDelta::FromDays(395);
+constexpr base::TimeDelta kDisusedAddressDeletionTimeDelta =
+ base::TimeDelta::FromDays(395);
+
+// Time delta to create test data.
+base::TimeDelta DeletableUseDateDelta() {
+ static base::TimeDelta delta =
+ kDisusedCreditCardDeletionTimeDelta + base::TimeDelta::FromDays(5);
+ return delta;
+}
+base::TimeDelta DeletableExpiryDateDelta() {
+ static base::TimeDelta delta =
+ kDisusedCreditCardDeletionTimeDelta + base::TimeDelta::FromDays(45);
+ return delta;
+}
-template<typename T>
+template <typename T>
class FormGroupMatchesByGUIDFunctor {
public:
explicit FormGroupMatchesByGUIDFunctor(const std::string& guid)
- : guid_(guid) {
- }
+ : guid_(guid) {}
- bool operator()(const T& form_group) {
- return form_group.guid() == guid_;
- }
+ bool operator()(const T& form_group) { return form_group.guid() == guid_; }
- bool operator()(const T* form_group) {
- return form_group->guid() == guid_;
- }
+ bool operator()(const T* form_group) { return form_group->guid() == guid_; }
bool operator()(const std::unique_ptr<T>& form_group) {
return form_group->guid() == guid_;
@@ -87,25 +100,23 @@ class FormGroupMatchesByGUIDFunctor {
const std::string guid_;
};
-template<typename T, typename C>
+template <typename T, typename C>
typename C::const_iterator FindElementByGUID(const C& container,
const std::string& guid) {
- return std::find_if(container.begin(),
- container.end(),
+ return std::find_if(container.begin(), container.end(),
FormGroupMatchesByGUIDFunctor<T>(guid));
}
-template<typename T, typename C>
+template <typename T, typename C>
bool FindByGUID(const C& container, const std::string& guid) {
return FindElementByGUID<T>(container, guid) != container.end();
}
-template<typename T>
+template <typename T>
class IsEmptyFunctor {
public:
explicit IsEmptyFunctor(const std::string& app_locale)
- : app_locale_(app_locale) {
- }
+ : app_locale_(app_locale) {}
bool operator()(const T& form_group) {
return form_group.IsEmpty(app_locale_);
@@ -115,6 +126,12 @@ class IsEmptyFunctor {
const std::string app_locale_;
};
+bool IsSyncEnabledFor(const syncer::SyncService* sync_service,
+ syncer::ModelType model_type) {
+ return sync_service != nullptr && sync_service->CanSyncStart() &&
+ sync_service->GetPreferredDataTypes().Has(model_type);
+}
+
// Returns true if minimum requirements for import of a given |profile| have
// been met. An address submitted via a form must have at least the fields
// required as determined by its country code.
@@ -156,8 +173,7 @@ bool IsValidFieldTypeAndValue(const std::set<ServerFieldType>& types_seen,
// Make an exception for PHONE_HOME_NUMBER however as both prefix and
// suffix are stored against this type, and for EMAIL_ADDRESS because it is
// common to see second 'confirm email address' fields on forms.
- if (types_seen.count(field_type) &&
- field_type != PHONE_HOME_NUMBER &&
+ if (types_seen.count(field_type) && field_type != PHONE_HOME_NUMBER &&
field_type != EMAIL_ADDRESS)
return false;
@@ -258,6 +274,129 @@ bool IsValidSuggestionForFieldContents(base::string16 suggestion_canon,
return false;
}
+AutofillProfile CreateBasicTestAddress(const std::string& locale) {
+ const base::Time use_date =
+ AutofillClock::Now() - base::TimeDelta::FromDays(20);
+ AutofillProfile profile;
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("John McTester"), locale);
+ profile.SetInfo(COMPANY_NAME, base::UTF8ToUTF16("Test Inc."), locale);
+ profile.SetInfo(EMAIL_ADDRESS,
+ base::UTF8ToUTF16("jmctester@fake.chromium.org"), locale);
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("123 Invented Street"),
+ locale);
+ profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Suite A"), locale);
+ profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Mountain View"),
+ locale);
+ profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("California"), locale);
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("94043"), locale);
+ profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), locale);
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0173"),
+ locale);
+ profile.set_use_date(use_date);
+ return profile;
+}
+
+AutofillProfile CreateDisusedTestAddress(const std::string& locale) {
+ const base::Time use_date =
+ AutofillClock::Now() - base::TimeDelta::FromDays(185);
+ AutofillProfile profile;
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("Polly Disused"), locale);
+ profile.SetInfo(COMPANY_NAME,
+ base::UTF8ToUTF16(base::StringPrintf(
+ "%lld Inc.", static_cast<long long>(use_date.ToTimeT()))),
+ locale);
+ profile.SetInfo(EMAIL_ADDRESS,
+ base::UTF8ToUTF16("polly.disused@fake.chromium.org"), locale);
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("456 Disused Lane"),
+ locale);
+ profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Apt. B"), locale);
+ profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Austin"), locale);
+ profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Texas"), locale);
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("73301"), locale);
+ profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), locale);
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0174"),
+ locale);
+ profile.set_use_date(use_date);
+ return profile;
+}
+
+AutofillProfile CreateDisusedDeletableTestAddress(const std::string& locale) {
+ const base::Time use_date =
+ AutofillClock::Now() - base::TimeDelta::FromDays(400);
+ AutofillProfile profile;
+ profile.SetInfo(NAME_FULL, base::UTF8ToUTF16("Polly Deletable"), locale);
+ profile.SetInfo(COMPANY_NAME,
+ base::UTF8ToUTF16(base::StringPrintf(
+ "%lld Inc.", static_cast<long long>(use_date.ToTimeT()))),
+ locale);
+ profile.SetInfo(EMAIL_ADDRESS,
+ base::UTF8ToUTF16("polly.deletable@fake.chromium.org"),
+ locale);
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::UTF8ToUTF16("459 Deletable Lane"),
+ locale);
+ profile.SetInfo(ADDRESS_HOME_LINE2, base::UTF8ToUTF16("Apt. B"), locale);
+ profile.SetInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16("Austin"), locale);
+ profile.SetInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Texas"), locale);
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("73301"), locale);
+ profile.SetInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16("US"), locale);
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::UTF8ToUTF16("844-555-0274"),
+ locale);
+ profile.set_use_date(use_date);
+ return profile;
+}
+
+// Create a card expiring 500 days from now which was last used 10 days ago.
+CreditCard CreateBasicTestCreditCard(const std::string& locale) {
+ const base::Time now = AutofillClock::Now();
+ const base::Time use_date = now - base::TimeDelta::FromDays(10);
+ base::Time::Exploded expiry_date;
+ (now + base::TimeDelta::FromDays(500)).LocalExplode(&expiry_date);
+
+ CreditCard credit_card;
+ credit_card.SetInfo(CREDIT_CARD_NAME_FULL,
+ base::UTF8ToUTF16("Alice Testerson"), locale);
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("4545454545454545"),
+ locale);
+ credit_card.SetExpirationMonth(expiry_date.month);
+ credit_card.SetExpirationYear(expiry_date.year);
+ credit_card.set_use_date(use_date);
+ return credit_card;
+}
+
+CreditCard CreateDisusedTestCreditCard(const std::string& locale) {
+ const base::Time now = AutofillClock::Now();
+ const base::Time use_date = now - base::TimeDelta::FromDays(185);
+ base::Time::Exploded expiry_date;
+ (now - base::TimeDelta::FromDays(200)).LocalExplode(&expiry_date);
+
+ CreditCard credit_card;
+ credit_card.SetInfo(CREDIT_CARD_NAME_FULL, base::UTF8ToUTF16("Bob Disused"),
+ locale);
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("4111111111111111"),
+ locale);
+ credit_card.SetExpirationMonth(expiry_date.month);
+ credit_card.SetExpirationYear(expiry_date.year);
+ credit_card.set_use_date(use_date);
+ return credit_card;
+}
+
+CreditCard CreateDisusedDeletableTestCreditCard(const std::string& locale) {
+ const base::Time now = AutofillClock::Now();
+ const base::Time use_date = now - DeletableUseDateDelta();
+ base::Time::Exploded expiry_date;
+ (now - DeletableExpiryDateDelta()).LocalExplode(&expiry_date);
+
+ CreditCard credit_card;
+ credit_card.SetInfo(CREDIT_CARD_NAME_FULL,
+ base::UTF8ToUTF16("Charlie Deletable"), locale);
+ credit_card.SetInfo(CREDIT_CARD_NUMBER, base::UTF8ToUTF16("378282246310005"),
+ locale);
+ credit_card.SetExpirationMonth(expiry_date.month);
+ credit_card.SetExpirationYear(expiry_date.year);
+ credit_card.set_use_date(use_date);
+ return credit_card;
+}
+
} // namespace
const char kFrecencyFieldTrialName[] = "AutofillProfileOrderByFrecency";
@@ -275,8 +414,7 @@ PersonalDataManager::PersonalDataManager(const std::string& app_locale)
account_tracker_(nullptr),
is_off_the_record_(false),
has_logged_stored_profile_metrics_(false),
- has_logged_local_credit_card_count_(false),
- has_logged_server_credit_card_counts_(false) {}
+ has_logged_stored_credit_card_metrics_(false) {}
void PersonalDataManager::Init(scoped_refptr<AutofillWebDataService> database,
PrefService* pref_service,
@@ -325,28 +463,23 @@ PersonalDataManager::~PersonalDataManager() {
void PersonalDataManager::OnSyncServiceInitialized(
syncer::SyncService* sync_service) {
- // We want to know when, if at all, we need to run autofill profile de-
- // duplication: now or after waiting until sync has started.
- if (!is_autofill_profile_cleanup_pending_) {
- // De-duplication isn't enabled.
- return;
+ // If the sync service is not enabled for autofill address profiles then run
+ // address cleanup/startup code here. Otherwise, defer until after sync has
+ // started.
+ if (!IsSyncEnabledFor(sync_service, syncer::AUTOFILL_PROFILE)) {
+ ApplyProfileUseDatesFix(); // One-time fix, otherwise NOP.
+ ApplyDedupingRoutine(); // Once per major version, otherwise NOP.
+ DeleteDisusedAddresses(); // Once per major version, otherwise NOP.
+ CreateTestAddresses(); // Once per user profile startup.
}
- // If the sync service is configured to start and to sync autofill profiles,
- // then we can just let the notification that sync has started trigger the
- // de-duplication.
- if (sync_service && sync_service->CanSyncStart() &&
- sync_service->GetPreferredDataTypes().Has(syncer::AUTOFILL_PROFILE)) {
- return;
+ // Similarly, if the sync service is not enabled for autofill credit cards
+ // then run credit card address cleanup/startup code here. Otherwise, defer
+ // until after sync has started.
+ if (!IsSyncEnabledFor(sync_service, syncer::AUTOFILL_WALLET_DATA)) {
+ DeleteDisusedCreditCards(); // Once per major version, otherwise NOP.
+ CreateTestCreditCards(); // Once per user profile startup.
}
-
- // This runs as a one-time fix, tracked in syncable prefs. If it has already
- // run, it is a NOP (other than checking the pref).
- ApplyProfileUseDatesFix();
-
- // This runs at most once per major version, tracked in syncable prefs. If it
- // has already run for this version, it's a NOP, other than checking the pref.
- ApplyDedupingRoutine();
}
void PersonalDataManager::OnWebDataServiceRequestDone(
@@ -355,12 +488,6 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
DCHECK(pending_profiles_query_ || pending_server_profiles_query_ ||
pending_creditcards_query_ || pending_server_creditcards_query_);
- // TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
- // fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "422460 PersonalDataManager::OnWebDataServiceRequestDone"));
-
if (!result) {
// Error from the web database.
if (h == pending_creditcards_query_)
@@ -371,48 +498,45 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
pending_server_creditcards_query_ = 0;
else if (h == pending_server_profiles_query_)
pending_server_profiles_query_ = 0;
- return;
- }
-
- switch (result->GetType()) {
- case AUTOFILL_PROFILES_RESULT:
- if (h == pending_profiles_query_) {
- ReceiveLoadedDbValues(h, result.get(), &pending_profiles_query_,
- &web_profiles_);
- LogStoredProfileMetrics(); // This only logs local profiles.
- } else {
- ReceiveLoadedDbValues(h, result.get(), &pending_server_profiles_query_,
- &server_profiles_);
- }
- break;
- case AUTOFILL_CREDITCARDS_RESULT:
- if (h == pending_creditcards_query_) {
- ReceiveLoadedDbValues(h, result.get(), &pending_creditcards_query_,
- &local_credit_cards_);
- LogLocalCreditCardCount();
- } else {
- ReceiveLoadedDbValues(h, result.get(),
- &pending_server_creditcards_query_,
- &server_credit_cards_);
-
- // If the user has a saved unmasked server card and the experiment is
- // disabled, force mask all cards back to the unsaved state.
- if (!OfferStoreUnmaskedCards())
- ResetFullServerCards();
-
- LogServerCreditCardCounts();
- }
- break;
- default:
- NOTREACHED();
+ } else {
+ switch (result->GetType()) {
+ case AUTOFILL_PROFILES_RESULT:
+ if (h == pending_profiles_query_) {
+ ReceiveLoadedDbValues(h, result.get(), &pending_profiles_query_,
+ &web_profiles_);
+ } else {
+ ReceiveLoadedDbValues(h, result.get(),
+ &pending_server_profiles_query_,
+ &server_profiles_);
+ }
+ break;
+ case AUTOFILL_CREDITCARDS_RESULT:
+ if (h == pending_creditcards_query_) {
+ ReceiveLoadedDbValues(h, result.get(), &pending_creditcards_query_,
+ &local_credit_cards_);
+ } else {
+ ReceiveLoadedDbValues(h, result.get(),
+ &pending_server_creditcards_query_,
+ &server_credit_cards_);
+
+ // If the user has a saved unmasked server card and the experiment is
+ // disabled, force mask all cards back to the unsaved state.
+ if (!OfferStoreUnmaskedCards())
+ ResetFullServerCards();
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
}
// If all requests have responded, then all personal data is loaded.
- if (pending_profiles_query_ == 0 &&
- pending_creditcards_query_ == 0 &&
+ if (pending_profiles_query_ == 0 && pending_creditcards_query_ == 0 &&
pending_server_profiles_query_ == 0 &&
pending_server_creditcards_query_ == 0) {
is_data_loaded_ = true;
+ LogStoredProfileMetrics();
+ LogStoredCreditCardMetrics();
NotifyPersonalDataChanged();
}
}
@@ -423,16 +547,20 @@ void PersonalDataManager::AutofillMultipleChanged() {
}
void PersonalDataManager::SyncStarted(syncer::ModelType model_type) {
- if (model_type == syncer::AUTOFILL_PROFILE &&
- is_autofill_profile_cleanup_pending_) {
- // This runs as a one-time fix, tracked in syncable prefs. If it has already
- // run, it is a NOP (other than checking the pref).
- ApplyProfileUseDatesFix();
+ // Run deferred autofill address profile startup code.
+ // See: OnSyncServiceInitialized
+ if (model_type == syncer::AUTOFILL_PROFILE) {
+ ApplyProfileUseDatesFix(); // One-time fix, otherwise NOP.
+ ApplyDedupingRoutine(); // Once per major version, otherwise NOP.
+ DeleteDisusedAddresses(); // Once per major version, otherwise NOP.
+ CreateTestAddresses(); // Once per user profile startup.
+ }
- // This runs at most once per major version, tracked in syncable prefs. If
- // it has already run for this version, it's a NOP, other than checking the
- // pref.
- ApplyDedupingRoutine();
+ // Run deferred credit card startup code.
+ // See: OnSyncServiceInitialized
+ if (model_type == syncer::AUTOFILL_WALLET_DATA) {
+ DeleteDisusedCreditCards(); // Once per major version, otherwise NOP.
+ CreateTestCreditCards(); // Once per user profile startup.
}
}
@@ -447,6 +575,7 @@ void PersonalDataManager::RemoveObserver(
bool PersonalDataManager::ImportFormData(
const FormStructure& form,
+ bool credit_card_enabled,
bool should_return_local_card,
std::unique_ptr<CreditCard>* imported_credit_card,
bool* imported_credit_card_matches_masked_server_credit_card) {
@@ -455,9 +584,12 @@ bool PersonalDataManager::ImportFormData(
// |imported_credit_card| with an extracted card. See .h for details of
// |should_return_local_card| and
// |imported_credit_card_matches_masked_server_credit_card|.
- bool cc_import =
- ImportCreditCard(form, should_return_local_card, imported_credit_card,
- imported_credit_card_matches_masked_server_credit_card);
+ bool cc_import = false;
+ if (credit_card_enabled) {
+ cc_import = ImportCreditCard(
+ form, should_return_local_card, imported_credit_card,
+ imported_credit_card_matches_masked_server_credit_card);
+ }
// - ImportAddressProfiles may eventually save or update one or more address
// profiles.
bool address_import = ImportAddressProfiles(form);
@@ -662,8 +794,7 @@ void PersonalDataManager::UpdateServerCreditCard(
DCHECK_NE(existing_credit_card->record_type(), credit_card.record_type());
DCHECK_EQ(existing_credit_card->Label(), credit_card.Label());
if (existing_credit_card->record_type() == CreditCard::MASKED_SERVER_CARD) {
- database_->UnmaskServerCreditCard(credit_card,
- credit_card.number());
+ database_->UnmaskServerCreditCard(credit_card, credit_card.number());
} else {
database_->MaskServerCreditCard(credit_card.server_id());
}
@@ -726,13 +857,31 @@ void PersonalDataManager::AddServerCreditCardForTest(
server_credit_cards_.push_back(std::move(credit_card));
}
+void PersonalDataManager::
+ RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(
+ const std::string& guid) {
+ database_->RemoveAutofillProfile(guid);
+
+ // Reset the billing_address_id of any card that refered to this profile.
+ for (CreditCard* credit_card : GetCreditCards()) {
+ if (credit_card->billing_address_id() == guid) {
+ credit_card->set_billing_address_id("");
+
+ if (credit_card->record_type() == CreditCard::LOCAL_CARD)
+ database_->UpdateCreditCard(*credit_card);
+ else
+ database_->UpdateServerCardMetadata(*credit_card);
+ }
+ }
+}
+
void PersonalDataManager::RemoveByGUID(const std::string& guid) {
if (is_off_the_record_)
return;
bool is_credit_card = FindByGUID<CreditCard>(local_credit_cards_, guid);
- bool is_profile = !is_credit_card &&
- FindByGUID<AutofillProfile>(web_profiles_, guid);
+ bool is_profile =
+ !is_credit_card && FindByGUID<AutofillProfile>(web_profiles_, guid);
if (!is_credit_card && !is_profile)
return;
@@ -742,19 +891,7 @@ void PersonalDataManager::RemoveByGUID(const std::string& guid) {
if (is_credit_card) {
database_->RemoveCreditCard(guid);
} else {
- database_->RemoveAutofillProfile(guid);
-
- // Reset the billing_address_id of any card that refered to this profile.
- for (CreditCard* credit_card : GetCreditCards()) {
- if (credit_card->billing_address_id() == guid) {
- credit_card->set_billing_address_id("");
-
- if (credit_card->record_type() == CreditCard::LOCAL_CARD)
- database_->UpdateCreditCard(*credit_card);
- else
- database_->UpdateServerCardMetadata(*credit_card);
- }
- }
+ RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(guid);
}
// Refresh our local cache and send notifications to observers.
@@ -792,12 +929,9 @@ bool PersonalDataManager::IsDataLoaded() const {
return is_data_loaded_;
}
-const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles() const {
- return GetProfiles(false);
-}
-
-std::vector<AutofillProfile*> PersonalDataManager::web_profiles() const {
+std::vector<AutofillProfile*> PersonalDataManager::GetProfiles() const {
std::vector<AutofillProfile*> result;
+ result.reserve(web_profiles_.size());
for (const auto& profile : web_profiles_)
result.push_back(profile.get());
return result;
@@ -805,6 +939,7 @@ std::vector<AutofillProfile*> PersonalDataManager::web_profiles() const {
std::vector<AutofillProfile*> PersonalDataManager::GetServerProfiles() const {
std::vector<AutofillProfile*> result;
+ result.reserve(server_profiles_.size());
for (const auto& profile : server_profiles_)
result.push_back(profile.get());
return result;
@@ -812,20 +947,24 @@ std::vector<AutofillProfile*> PersonalDataManager::GetServerProfiles() const {
std::vector<CreditCard*> PersonalDataManager::GetLocalCreditCards() const {
std::vector<CreditCard*> result;
+ result.reserve(local_credit_cards_.size());
for (const auto& card : local_credit_cards_)
result.push_back(card.get());
return result;
}
-const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
- credit_cards_.clear();
- for (const auto& card : local_credit_cards_)
- credit_cards_.push_back(card.get());
- if (pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
- for (const auto& card : server_credit_cards_)
- credit_cards_.push_back(card.get());
+std::vector<CreditCard*> PersonalDataManager::GetCreditCards() const {
+ std::vector<CreditCard*> result;
+ result.reserve(local_credit_cards_.size() + server_credit_cards_.size());
+ if (pref_service_->GetBoolean(prefs::kAutofillCreditCardEnabled)) {
+ for (const auto& card : local_credit_cards_)
+ result.push_back(card.get());
+ if (pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
+ for (const auto& card : server_credit_cards_)
+ result.push_back(card.get());
+ }
}
- return credit_cards_;
+ return result;
}
void PersonalDataManager::Refresh() {
@@ -835,7 +974,7 @@ void PersonalDataManager::Refresh() {
std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest()
const {
- std::vector<AutofillProfile*> profiles = GetProfiles(true);
+ std::vector<AutofillProfile*> profiles = GetProfiles();
// Rank the suggestions by frecency (see AutofillDataModel for details).
const base::Time comparison_time = AutofillClock::Now();
@@ -1004,14 +1143,43 @@ const std::vector<CreditCard*> PersonalDataManager::GetCreditCardsToSuggest()
return cards_to_suggest;
}
+// static
+void PersonalDataManager::RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ base::Time comparison_time,
+ base::Time min_last_used,
+ std::vector<CreditCard*>* cards) {
+ const size_t original_size = cards->size();
+ // Split the vector into [unexpired-or-expired-but-after-timestamp,
+ // expired-and-before-timestamp], then delete the latter.
+ cards->erase(std::stable_partition(
+ cards->begin(), cards->end(),
+ [comparison_time, min_last_used](const CreditCard* c) {
+ return !c->IsExpired(comparison_time) ||
+ c->use_date() > min_last_used;
+ }),
+ cards->end());
+ const size_t num_cards_supressed = original_size - cards->size();
+ AutofillMetrics::LogNumberOfCreditCardsSuppressedForDisuse(
+ num_cards_supressed);
+}
+
std::vector<Suggestion> PersonalDataManager::GetCreditCardSuggestions(
const AutofillType& type,
const base::string16& field_contents) {
if (IsInAutofillSuggestionsDisabledExperiment())
return std::vector<Suggestion>();
+ std::vector<CreditCard*> cards = GetCreditCardsToSuggest();
+ // If enabled, suppress disused address profiles when triggered from an empty
+ // field.
+ if (field_contents.empty() &&
+ base::FeatureList::IsEnabled(kAutofillSuppressDisusedCreditCards)) {
+ const base::Time min_last_used =
+ AutofillClock::Now() - kDisusedCreditCardTimeDelta;
+ RemoveExpiredCreditCardsNotUsedSinceTimestamp(AutofillClock::Now(),
+ min_last_used, &cards);
+ }
- return GetSuggestionsForCards(type, field_contents,
- GetCreditCardsToSuggest());
+ return GetSuggestionsForCards(type, field_contents, cards);
}
bool PersonalDataManager::IsAutofillEnabled() const {
@@ -1025,14 +1193,18 @@ std::string PersonalDataManager::CountryCodeForCurrentTimezone() const {
void PersonalDataManager::SetPrefService(PrefService* pref_service) {
enabled_pref_.reset(new BooleanPrefMember);
wallet_enabled_pref_.reset(new BooleanPrefMember);
+ credit_card_enabled_pref_.reset(new BooleanPrefMember);
pref_service_ = pref_service;
// |pref_service_| can be nullptr in tests.
if (pref_service_) {
+ credit_card_enabled_pref_->Init(
+ prefs::kAutofillCreditCardEnabled, pref_service_,
+ base::Bind(&PersonalDataManager::Refresh, base::Unretained(this)));
enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
- base::Bind(&PersonalDataManager::EnabledPrefChanged,
- base::Unretained(this)));
- wallet_enabled_pref_->Init(prefs::kAutofillWalletImportEnabled,
- pref_service_,
+ base::Bind(&PersonalDataManager::EnabledPrefChanged,
+ base::Unretained(this)));
+ wallet_enabled_pref_->Init(
+ prefs::kAutofillWalletImportEnabled, pref_service_,
base::Bind(&PersonalDataManager::EnabledPrefChanged,
base::Unretained(this)));
}
@@ -1125,15 +1297,15 @@ std::string PersonalDataManager::MergeProfile(
return guid;
}
-bool PersonalDataManager::IsCountryOfInterest(const std::string& country_code)
- const {
+bool PersonalDataManager::IsCountryOfInterest(
+ const std::string& country_code) const {
DCHECK_EQ(2U, country_code.size());
- const std::vector<AutofillProfile*>& profiles = web_profiles();
+ const std::vector<AutofillProfile*>& profiles = GetProfiles();
std::list<std::string> country_codes;
for (size_t i = 0; i < profiles.size(); ++i) {
- country_codes.push_back(base::ToLowerASCII(base::UTF16ToASCII(
- profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
+ country_codes.push_back(base::ToLowerASCII(
+ base::UTF16ToASCII(profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY))));
}
std::string timezone_country = CountryCodeForCurrentTimezone();
@@ -1394,26 +1566,13 @@ void PersonalDataManager::LogStoredProfileMetrics() const {
}
}
-void PersonalDataManager::LogLocalCreditCardCount() const {
- if (!has_logged_local_credit_card_count_) {
- AutofillMetrics::LogStoredLocalCreditCardCount(local_credit_cards_.size());
- has_logged_local_credit_card_count_ = true;
- }
-}
+void PersonalDataManager::LogStoredCreditCardMetrics() const {
+ if (!has_logged_stored_credit_card_metrics_) {
+ AutofillMetrics::LogStoredCreditCardMetrics(
+ local_credit_cards_, server_credit_cards_, kDisusedProfileTimeDelta);
-void PersonalDataManager::LogServerCreditCardCounts() const {
- if (!has_logged_server_credit_card_counts_) {
- size_t unmasked_cards = 0, masked_cards = 0;
- for (const auto& card : server_credit_cards_) {
- if (card->record_type() == CreditCard::MASKED_SERVER_CARD) {
- masked_cards++;
- } else if (card->record_type() == CreditCard::FULL_SERVER_CARD) {
- unmasked_cards++;
- }
- }
- AutofillMetrics::LogStoredServerCreditCardCounts(masked_cards,
- unmasked_cards);
- has_logged_server_credit_card_counts_ = true;
+ // Only log this info once per chrome user profile load.
+ has_logged_stored_credit_card_metrics_ = true;
}
}
@@ -1425,12 +1584,12 @@ std::string PersonalDataManager::MostCommonCountryCodeFromProfiles() const {
std::map<std::string, int> votes;
// TODO(estade): can we make this GetProfiles() instead? It seems to cause
// errors in tests on mac trybots. See http://crbug.com/57221
- const std::vector<AutofillProfile*>& profiles = web_profiles();
+ const std::vector<AutofillProfile*>& profiles = GetProfiles();
const std::vector<std::string>& country_codes =
CountryDataMap::GetInstance()->country_codes();
for (size_t i = 0; i < profiles.size(); ++i) {
- std::string country_code = base::ToUpperASCII(base::UTF16ToASCII(
- profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
+ std::string country_code = base::ToUpperASCII(
+ base::UTF16ToASCII(profiles[i]->GetRawInfo(ADDRESS_HOME_COUNTRY)));
if (base::ContainsValue(country_codes, country_code)) {
// Verified profiles count 100x more than unverified ones.
@@ -1569,16 +1728,17 @@ bool PersonalDataManager::ImportAddressProfileForSection(
return true;
}
-bool PersonalDataManager::ImportCreditCard(
+CreditCard PersonalDataManager::ExtractCreditCardFromForm(
+ const FormStructure& form) {
+ bool has_duplicate_field_type;
+ return ExtractCreditCardFromForm(form, &has_duplicate_field_type);
+}
+
+CreditCard PersonalDataManager::ExtractCreditCardFromForm(
const FormStructure& form,
- bool should_return_local_card,
- std::unique_ptr<CreditCard>* imported_credit_card,
- bool* imported_credit_card_matches_masked_server_credit_card) {
- DCHECK(!imported_credit_card->get());
- *imported_credit_card_matches_masked_server_credit_card = false;
+ bool* has_duplicate_field_type) {
+ *has_duplicate_field_type = false;
- // The candidate for credit card import. There are many ways for the candidate
- // to be rejected (see everywhere this function returns false, below).
CreditCard candidate_credit_card;
candidate_credit_card.set_origin(form.source_url().spec());
@@ -1599,12 +1759,13 @@ bool PersonalDataManager::ImportCreditCard(
continue;
// If we've seen the same credit card field type twice in the same form,
- // abort credit card import/update.
+ // set |has_duplicate_field_type| to true.
ServerFieldType server_field_type = field_type.GetStorableType();
- if (types_seen.count(server_field_type))
- return false;
- types_seen.insert(server_field_type);
-
+ if (types_seen.count(server_field_type)) {
+ *has_duplicate_field_type = true;
+ } else {
+ types_seen.insert(server_field_type);
+ }
// If |field| is an HTML5 month input, handle it as a special case.
if (base::LowerCaseEqualsASCII(field->form_control_type, "month")) {
DCHECK_EQ(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, server_field_type);
@@ -1629,6 +1790,28 @@ bool PersonalDataManager::ImportCreditCard(
}
}
+ return candidate_credit_card;
+}
+
+bool PersonalDataManager::ImportCreditCard(
+ const FormStructure& form,
+ bool should_return_local_card,
+ std::unique_ptr<CreditCard>* imported_credit_card,
+ bool* imported_credit_card_matches_masked_server_credit_card) {
+ DCHECK(!imported_credit_card->get());
+ *imported_credit_card_matches_masked_server_credit_card = false;
+
+ // The candidate for credit card import. There are many ways for the candidate
+ // to be rejected (see everywhere this function returns false, below).
+ bool has_duplicate_field_type;
+ CreditCard candidate_credit_card =
+ ExtractCreditCardFromForm(form, &has_duplicate_field_type);
+
+ // If we've seen the same credit card field type twice in the same form,
+ // abort credit card import/update.
+ if (has_duplicate_field_type)
+ return false;
+
// Reject the credit card if we did not detect enough filled credit card
// fields (such as valid number, month, year).
if (!candidate_credit_card.IsValid())
@@ -1644,8 +1827,7 @@ bool PersonalDataManager::ImportCreditCard(
// Make a local copy so that the data in |local_credit_cards_| isn't
// modified directly by the UpdateFromImportedCard() call.
CreditCard card_copy(*card);
- if (card_copy.UpdateFromImportedCard(candidate_credit_card,
- app_locale_)) {
+ if (card_copy.UpdateFromImportedCard(candidate_credit_card, app_locale_)) {
UpdateCreditCard(card_copy);
// If we should not return the local card, return that we merged it,
// without setting |imported_credit_card|.
@@ -1699,12 +1881,30 @@ bool PersonalDataManager::ImportCreditCard(
return true;
}
-const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles(
- bool record_metrics) const {
- profiles_.clear();
- for (const auto& profile : web_profiles_)
- profiles_.push_back(profile.get());
- return profiles_;
+bool PersonalDataManager::IsKnownCard(const CreditCard& credit_card) {
+ const auto stripped_pan = CreditCard::StripSeparators(credit_card.number());
+ for (const auto& card : local_credit_cards_) {
+ if (stripped_pan == CreditCard::StripSeparators(card->number()))
+ return true;
+ }
+
+ const auto masked_info = credit_card.NetworkAndLastFourDigits();
+ for (const auto& card : server_credit_cards_) {
+ switch (card->record_type()) {
+ case CreditCard::FULL_SERVER_CARD:
+ if (stripped_pan == CreditCard::StripSeparators(card->number()))
+ return true;
+ break;
+ case CreditCard::MASKED_SERVER_CARD:
+ if (masked_info == card->NetworkAndLastFourDigits())
+ return true;
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
+
+ return false;
}
std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards(
@@ -1794,7 +1994,7 @@ void PersonalDataManager::ApplyProfileUseDatesFix() {
std::vector<AutofillProfile> profiles;
bool has_changed_data = false;
- for (AutofillProfile* profile : web_profiles()) {
+ for (AutofillProfile* profile : GetProfiles()) {
if (profile->use_date() == base::Time()) {
profile->set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(14));
@@ -2155,4 +2355,155 @@ std::string PersonalDataManager::MergeServerAddressesIntoProfiles(
return guid;
}
+void PersonalDataManager::CreateTestAddresses() {
+ if (has_created_test_addresses_)
+ return;
+
+ has_created_test_addresses_ = true;
+ if (!base::FeatureList::IsEnabled(kAutofillCreateDataForTest))
+ return;
+
+ AddProfile(CreateBasicTestAddress(app_locale_));
+ AddProfile(CreateDisusedTestAddress(app_locale_));
+ AddProfile(CreateDisusedDeletableTestAddress(app_locale_));
+}
+
+void PersonalDataManager::CreateTestCreditCards() {
+ if (has_created_test_credit_cards_)
+ return;
+
+ has_created_test_credit_cards_ = true;
+ if (!base::FeatureList::IsEnabled(kAutofillCreateDataForTest))
+ return;
+
+ AddCreditCard(CreateBasicTestCreditCard(app_locale_));
+ AddCreditCard(CreateDisusedTestCreditCard(app_locale_));
+ AddCreditCard(CreateDisusedDeletableTestCreditCard(app_locale_));
+}
+
+bool PersonalDataManager::IsCreditCardDeletable(CreditCard* card) {
+ const base::Time deletion_threshold =
+ AutofillClock::Now() - kDisusedCreditCardDeletionTimeDelta;
+
+ return card->use_date() < deletion_threshold &&
+ card->IsExpired(deletion_threshold);
+}
+
+bool PersonalDataManager::DeleteDisusedCreditCards() {
+ if (!base::FeatureList::IsEnabled(kAutofillDeleteDisusedCreditCards)) {
+ return false;
+ }
+
+ // Check if credit cards deletion has already been performed this major
+ // version.
+ int current_major_version = atoi(version_info::GetVersionNumber().c_str());
+ if (pref_service_->GetInteger(
+ prefs::kAutofillLastVersionDisusedCreditCardsDeleted) >=
+ current_major_version) {
+ DVLOG(1)
+ << "Autofill credit cards deletion already performed for this version";
+ return false;
+ }
+
+ // Set the pref to the current major version.
+ pref_service_->SetInteger(
+ prefs::kAutofillLastVersionDisusedCreditCardsDeleted,
+ current_major_version);
+
+ // Only delete local cards, as server cards are managed by Payments.
+ auto cards = GetLocalCreditCards();
+
+ // Early exit when there is no local cards.
+ if (cards.empty()) {
+ return true;
+ }
+
+ std::vector<std::string> guid_to_delete;
+ for (CreditCard* card : cards) {
+ if (IsCreditCardDeletable(card)) {
+ guid_to_delete.push_back(card->guid());
+ }
+ }
+
+ size_t num_deleted_cards = guid_to_delete.size();
+
+ for (auto const guid : guid_to_delete) {
+ database_->RemoveCreditCard(guid);
+ }
+
+ if (num_deleted_cards > 0) {
+ Refresh();
+ }
+
+ AutofillMetrics::LogNumberOfCreditCardsDeletedForDisuse(num_deleted_cards);
+
+ return true;
+}
+
+bool PersonalDataManager::IsAddressDeletable(
+ AutofillProfile* profile,
+ std::unordered_set<std::string> const& used_billing_address_guids) {
+ const base::Time deletion_threshold =
+ AutofillClock::Now() - kDisusedAddressDeletionTimeDelta;
+
+ return profile->use_date() < deletion_threshold && !profile->IsVerified() &&
+ used_billing_address_guids.find(profile->guid()) ==
+ used_billing_address_guids.end();
+}
+
+bool PersonalDataManager::DeleteDisusedAddresses() {
+ if (!base::FeatureList::IsEnabled(kAutofillDeleteDisusedAddresses)) {
+ return false;
+ }
+
+ // Check if address deletion has already been performed this major version.
+ int current_major_version = atoi(version_info::GetVersionNumber().c_str());
+ if (pref_service_->GetInteger(
+ prefs::kAutofillLastVersionDisusedAddressesDeleted) >=
+ current_major_version) {
+ DVLOG(1)
+ << "Autofill addresses deletion already performed for this version";
+ return false;
+ }
+
+ // Set the pref to the current major version.
+ pref_service_->SetInteger(prefs::kAutofillLastVersionDisusedAddressesDeleted,
+ current_major_version);
+
+ const std::vector<AutofillProfile*>& profiles = GetProfiles();
+
+ // Early exit when there are no profiles.
+ if (profiles.empty()) {
+ return true;
+ }
+
+ std::unordered_set<std::string> used_billing_address_guids;
+ for (CreditCard* card : GetCreditCards()) {
+ if (!IsCreditCardDeletable(card)) {
+ used_billing_address_guids.insert(card->billing_address_id());
+ }
+ }
+
+ std::vector<std::string> guids_to_delete;
+ for (AutofillProfile* profile : profiles) {
+ if (IsAddressDeletable(profile, used_billing_address_guids)) {
+ guids_to_delete.push_back(profile->guid());
+ }
+ }
+
+ size_t num_deleted_addresses = guids_to_delete.size();
+
+ for (auto const guid : guids_to_delete) {
+ RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(guid);
+ }
+
+ if (num_deleted_addresses > 0) {
+ Refresh();
+ }
+
+ AutofillMetrics::LogNumberOfAddressesDeletedForDisuse(num_deleted_addresses);
+
+ return true;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index a28c4f24a2f..a259c802d42 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -25,6 +25,7 @@
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
#include "components/webdata/common/web_data_service_consumer.h"
#include "net/url_request/url_request_context_getter.h"
@@ -99,18 +100,19 @@ class PersonalDataManager : public KeyedService,
// Scans the given |form| for importable Autofill data. If the form includes
// sufficient address data for a new profile, it is immediately imported. If
- // the form includes sufficient credit card data for a new credit card, it is
+ // the form includes sufficient credit card data for a new credit card and
+ // |credit_card_enabled| is set to |true|, it is stored into
+ // |imported_credit_card| so that we can prompt the user whether to save this
+ // data. If the form contains credit card data already present in a local
+ // credit card entry *and* |should_return_local_card| is true, the data is
// stored into |imported_credit_card| so that we can prompt the user whether
- // to save this data. If the form contains credit card data already present in
- // a local credit card entry *and* |should_return_local_card| is true, the
- // data is stored into |imported_credit_card| so that we can prompt the user
- // whether to upload it.
- // |imported_credit_card_matches_masked_server_credit_card| is set to |true|
- // if the |TypeAndLastFourDigits| in |imported_credit_card| matches the
- // |TypeAndLastFourDigits| in a saved masked server card. Returns |true| if
- // sufficient address or credit card data was found.
+ // to upload it. |imported_credit_card_matches_masked_server_credit_card| is
+ // set to |true| if the |TypeAndLastFourDigits| in |imported_credit_card|
+ // matches the |TypeAndLastFourDigits| in a saved masked server card. Returns
+ // |true| if sufficient address or credit card data was found.
bool ImportFormData(
const FormStructure& form,
+ bool credit_card_enabled,
bool should_return_local_card,
std::unique_ptr<CreditCard>* imported_credit_card,
bool* imported_credit_card_matches_masked_server_credit_card);
@@ -200,16 +202,13 @@ class PersonalDataManager : public KeyedService,
// This PersonalDataManager owns these profiles and credit cards. Their
// lifetime is until the web database is updated with new profile and credit
// card information, respectively.
- // TODO(crbug.com/687352): Remove one of these since they do the same thing.
- // |GetProfiles()| and |web_profiles()| returns only local profiles.
- virtual const std::vector<AutofillProfile*>& GetProfiles() const;
- virtual std::vector<AutofillProfile*> web_profiles() const;
+ virtual std::vector<AutofillProfile*> GetProfiles() const;
// Returns just SERVER_PROFILES.
virtual std::vector<AutofillProfile*> GetServerProfiles() const;
// Returns just LOCAL_CARD cards.
virtual std::vector<CreditCard*> GetLocalCreditCards() const;
// Returns all credit cards, server and local.
- virtual const std::vector<CreditCard*>& GetCreditCards() const;
+ virtual std::vector<CreditCard*> GetCreditCards() const;
// Returns the profiles to suggest to the user, ordered by frecency.
std::vector<AutofillProfile*> GetProfilesToSuggest() const;
@@ -230,11 +229,23 @@ class PersonalDataManager : public KeyedService,
bool field_is_autofilled,
const std::vector<ServerFieldType>& other_field_types);
+ // Tries to delete disused addresses once per major version if the
+ // feature is enabled.
+ bool DeleteDisusedAddresses();
+
// Returns the credit cards to suggest to the user. Those have been deduped
// and ordered by frecency with the expired cards put at the end of the
// vector.
const std::vector<CreditCard*> GetCreditCardsToSuggest() const;
+ // Remove credit cards that are expired at |comparison_time| and not used
+ // since |min_last_used| from |cards|. The relative ordering of |cards| is
+ // maintained.
+ static void RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ base::Time comparison_time,
+ base::Time min_last_used,
+ std::vector<CreditCard*>* cards);
+
// Gets credit cards that can suggest data for |type|. See
// GetProfileSuggestions for argument descriptions. The variant in each
// GUID pair should be ignored.
@@ -242,6 +253,10 @@ class PersonalDataManager : public KeyedService,
const AutofillType& type,
const base::string16& field_contents);
+ // Tries to delete disused credit cards once per major version if the
+ // feature is enabled.
+ bool DeleteDisusedCreditCards();
+
// Re-loads profiles and credit cards from the WebDatabase asynchronously.
// In the general case, this is a no-op and will re-create the same
// in-memory model as existed prior to the call. If any change occurred to
@@ -286,9 +301,7 @@ class PersonalDataManager : public KeyedService,
std::list<CreditCard*>* cards_to_suggest);
// Notifies test observers that personal data has changed.
- void NotifyPersonalDataChangedForTest() {
- NotifyPersonalDataChanged();
- }
+ void NotifyPersonalDataChangedForTest() { NotifyPersonalDataChanged(); }
// Sets the URL request context getter to be used when normalizing addresses
// with libaddressinput's address validator.
@@ -302,6 +315,16 @@ class PersonalDataManager : public KeyedService,
return context_getter_.get();
}
+ // Extract credit card from the form structure. This function allows for
+ // duplicated field types in the form.
+ CreditCard ExtractCreditCardFromForm(const FormStructure& form);
+
+ // This function assumes |credit_card| contains the full PAN. Returns |true|
+ // if the card number of |credit_card| is equal to any local card or any
+ // unmasked server card known by the browser, or |TypeAndLastFourDigits| of
+ // |credit_card| is equal to any masked server card known by the browser.
+ bool IsKnownCard(const CreditCard& credit_card);
+
protected:
// Only PersonalDataManagerFactory and certain tests can create instances of
// PersonalDataManager.
@@ -351,6 +374,16 @@ class PersonalDataManager : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(
PersonalDataManagerTest,
ConvertWalletAddressesAndUpdateWalletCards_MultipleSimilarWalletAddresses); // NOLINT
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ DeleteDisusedCreditCards_OncePerVersion);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ DeleteDisusedCreditCards_DoNothingWhenDisabled);
+ FRIEND_TEST_ALL_PREFIXES(
+ PersonalDataManagerTest,
+ DeleteDisusedCreditCards_OnlyDeleteExpiredDisusedLocalCards);
+ FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
+ GetCreditCardSuggestions_CreditCardAutofillDisabled);
+
friend class autofill::AutofillInteractiveTest;
friend class autofill::AutofillTest;
friend class autofill::PersonalDataManagerFactory;
@@ -361,11 +394,13 @@ class PersonalDataManager : public KeyedService,
friend class ::RemoveAutofillTester;
friend std::default_delete<PersonalDataManager>;
friend void autofill_helper::SetProfiles(
- int, std::vector<autofill::AutofillProfile>*);
+ int,
+ std::vector<autofill::AutofillProfile>*);
friend void autofill_helper::SetCreditCards(
- int, std::vector<autofill::CreditCard>*);
- friend void SetTestProfiles(
- Browser* browser, std::vector<AutofillProfile>* profiles);
+ int,
+ std::vector<autofill::CreditCard>*);
+ friend void SetTestProfiles(Browser* browser,
+ std::vector<AutofillProfile>* profiles);
// Sets |web_profiles_| to the contents of |profiles| and updates the web
// database by adding, updating and removing profiles.
@@ -396,18 +431,13 @@ class PersonalDataManager : public KeyedService,
// Notifies observers that personal data has changed.
void NotifyPersonalDataChanged();
- // The first time this is called, logs a UMA metrics about the user's profile.
- // On subsequent calls, does nothing.
+ // The first time this is called, logs a UMA metrics about the user's autofill
+ // addresses. On subsequent calls, does nothing.
void LogStoredProfileMetrics() const;
- // The first time this is called, logs an UMA metric for the number of local
- // credit cards the user has. On subsequent calls, does nothing.
- void LogLocalCreditCardCount() const;
-
- // The first time this is called, logs an UMA metric for the number of server
- // credit cards the user has (both masked and unmasked). On subsequent calls,
- // does nothing.
- void LogServerCreditCardCounts() const;
+ // The first time this is called, logs an UMA metric about the user's autofill
+ // credit cardss. On subsequent calls, does nothing.
+ void LogStoredCreditCardMetrics() const;
// Returns the value of the AutofillEnabled pref.
virtual bool IsAutofillEnabled() const;
@@ -452,10 +482,6 @@ class PersonalDataManager : public KeyedService,
std::vector<std::unique_ptr<CreditCard>> local_credit_cards_;
std::vector<std::unique_ptr<CreditCard>> server_credit_cards_;
- // A combination of local and server credit cards. The pointers are owned
- // by the local/server_credit_cards_ vectors.
- mutable std::vector<CreditCard*> credit_cards_;
-
// When the manager makes a request from WebDataServiceBase, the database
// is queried on another sequence, we record the query handle until we
// get called back. We store handles for both profile and credit card queries
@@ -501,11 +527,10 @@ class PersonalDataManager : public KeyedService,
std::unique_ptr<CreditCard>* imported_credit_card,
bool* imported_credit_card_matches_masked_server_credit_card);
- // Functionally equivalent to GetProfiles(), but also records metrics if
- // |record_metrics| is true. Metrics should be recorded when the returned
- // profiles will be used to populate the fields shown in an Autofill popup.
- virtual const std::vector<AutofillProfile*>& GetProfiles(
- bool record_metrics) const;
+ // Extracts credit card from the form structure. |hasDuplicateFieldType| will
+ // be set as true if there are duplicated field types in the form.
+ CreditCard ExtractCreditCardFromForm(const FormStructure& form,
+ bool* hasDuplicateFieldType);
// Returns credit card suggestions based on the |cards_to_suggest| and the
// |type| and |field_contents| of the credit card field.
@@ -514,6 +539,10 @@ class PersonalDataManager : public KeyedService,
const base::string16& field_contents,
const std::vector<CreditCard*>& cards_to_suggest) const;
+ // Returns true if the given credit card can be deleted in a major version
+ // upgrade. The card will need to be local and disused, to be deletable.
+ bool IsCreditCardDeletable(CreditCard* card);
+
// Runs the Autofill use date fix routine if it's never been done. Returns
// whether the routine was run.
void ApplyProfileUseDatesFix();
@@ -579,6 +608,30 @@ class PersonalDataManager : public KeyedService,
const AutofillProfile& server_address,
std::vector<AutofillProfile>* existing_profiles);
+ // Removes profile from web database according to |guid| and resets credit
+ // card's billing address if that address is used by any credit cards.
+ // The method does not refresh, this allows multiple removal with one
+ // refreshing in the end.
+ void RemoveAutofillProfileByGUIDAndBlankCreditCardReferecne(
+ const std::string& guid);
+
+ // Returns true if an address can be deleted in a major version upgrade.
+ // An address is deletable if it is unverified, and not used by a valid
+ // credit card as billing address, and not used for a long time(13 months).
+ bool IsAddressDeletable(
+ AutofillProfile* profile,
+ const std::unordered_set<std::string>& used_billing_address_guids);
+
+ // If the AutofillCreateDataForTest feature is enabled, this helper creates
+ // autofill address data that would otherwise be difficult to create
+ // manually using the UI.
+ void CreateTestAddresses();
+
+ // If the AutofillCreateDataForTest feature is enabled, this helper creates
+ // autofill credit card data that would otherwise be difficult to create
+ // manually using the UI.
+ void CreateTestCreditCards();
+
const std::string app_locale_;
// The default country code for new addresses.
@@ -601,13 +654,11 @@ class PersonalDataManager : public KeyedService,
// Whether we have already logged the stored profile metrics this session.
mutable bool has_logged_stored_profile_metrics_;
- // Whether we have already logged the number of local credit cards this
- // session.
- mutable bool has_logged_local_credit_card_count_;
+ // Whether we have already logged the stored credit card metrics this session.
+ mutable bool has_logged_stored_credit_card_metrics_;
- // Whether we have already logged the number of server credit cards this
- // session.
- mutable bool has_logged_server_credit_card_counts_;
+ // An observer to listen for changes to prefs::kAutofillCreditCardEnabled.
+ std::unique_ptr<BooleanPrefMember> credit_card_enabled_pref_;
// An observer to listen for changes to prefs::kAutofillEnabled.
std::unique_ptr<BooleanPrefMember> enabled_pref_;
@@ -621,6 +672,10 @@ class PersonalDataManager : public KeyedService,
// Whether new information was received from the sync server.
bool has_synced_new_data_ = false;
+ // True if test data has been created this session.
+ bool has_created_test_addresses_ = false;
+ bool has_created_test_credit_cards_ = false;
+
// The context for the request to be used to fetch libaddressinput's address
// validation rules.
scoped_refptr<net::URLRequestContextGetter> context_getter_;
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 3974e1e5678..c3b2060d630 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -104,15 +104,14 @@ void ExpectSameElements(const std::vector<T*>& expectations,
ASSERT_EQ(expectations.size(), results.size());
std::vector<T*> expectations_copy = expectations;
- std::sort(
- expectations_copy.begin(), expectations_copy.end(), CompareElements<T>);
+ 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,
+ EXPECT_EQ(std::mismatch(results_copy.begin(), results_copy.end(),
+ expectations_copy.begin(), ElementsEqual<T>)
+ .first,
results_copy.end());
}
@@ -127,9 +126,7 @@ class PersonalDataManagerTestBase {
personal_data_.reset(new PersonalDataManager("en"));
personal_data_->Init(
scoped_refptr<AutofillWebDataService>(autofill_database_service_),
- prefs_.get(),
- account_tracker_.get(),
- signin_manager_.get(),
+ prefs_.get(), account_tracker_.get(), signin_manager_.get(),
is_incognito);
personal_data_->AddObserver(&personal_data_observer_);
personal_data_->OnSyncServiceInitialized(nullptr);
@@ -245,6 +242,35 @@ class PersonalDataManagerTestBase {
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
}
+ // Helper method to create a local card that was expired 400 days ago,
+ // and has not been used in last 400 days. This card is supposed to be
+ // deleted during a major version upgrade.
+ void CreateDeletableExpiredAndDisusedCreditCard() {
+ CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
+ "378282246310005" /* American Express */, "04",
+ "1999", "1");
+ credit_card1.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(400));
+
+ personal_data_->AddCreditCard(credit_card1);
+
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+ }
+
+ // Helper method to create a profile that was last used 400 days ago.
+ // This profile is supposed to be deleted during a major version upgrade.
+ void CreateDeletableDisusedProfile() {
+ AutofillProfile profile0(test::GetFullProfile());
+ profile0.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(400));
+ personal_data_->AddProfile(profile0);
+
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
+ }
+
// Helper methods that simply forward the call to the private member (to avoid
// having to friend every test that needs to access the private
// PersonalDataManager::ImportAddressProfile or ImportCreditCard).
@@ -455,22 +481,19 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileSetModificationDate) {
TEST_F(PersonalDataManagerTest, AddUpdateRemoveProfiles) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile0,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile0, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile1,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
- "US", "19482937549");
+ test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL,
+ "Orlando", "FL", "32801", "US", "19482937549");
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile2,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
- "32801", "US", "19482937549");
+ test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
+ "Orlando", "FL", "32801", "US", "19482937549");
// Add two test profiles to the database.
personal_data_->AddProfile(profile0);
@@ -621,10 +644,9 @@ TEST_F(PersonalDataManagerTest, AddCreditCard_BasicInformation) {
TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
// Start with unverified data.
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/");
- test::SetProfileInfo(&profile,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
EXPECT_FALSE(profile.IsVerified());
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com/");
@@ -692,8 +714,8 @@ TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
// Makes sure that full cards are re-masked when full PAN storage is off.
TEST_F(PersonalDataManagerTest, RefuseToStoreFullCard) {
- // On Linux this should be disabled automatically. Elsewhere, only if the
- // flag is passed.
+// On Linux this should be disabled automatically. Elsewhere, only if the
+// flag is passed.
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
EXPECT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableOfferStoreUnmaskedWalletCards));
@@ -844,16 +866,14 @@ TEST_F(PersonalDataManagerTest, SavesServerCardType) {
TEST_F(PersonalDataManagerTest, AddProfilesAndCreditCards) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile0,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile0, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile1,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
- "US", "19482937549");
+ test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL,
+ "Orlando", "FL", "32801", "US", "19482937549");
CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card0, "John Dillinger",
@@ -900,8 +920,8 @@ TEST_F(PersonalDataManagerTest, AddProfilesAndCreditCards) {
// correctly on load.
TEST_F(PersonalDataManagerTest, PopulateUniqueIDsOnLoad) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile0,
- "y", "", "", "", "", "", "", "", "", "", "", "");
+ test::SetProfileInfo(&profile0, "y", "", "", "", "", "", "", "", "", "", "",
+ "");
// Add the profile0 to the db.
personal_data_->AddProfile(profile0);
@@ -915,8 +935,8 @@ TEST_F(PersonalDataManagerTest, PopulateUniqueIDsOnLoad) {
// Add a new profile.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile1,
- "z", "", "", "", "", "", "", "", "", "", "", "");
+ test::SetProfileInfo(&profile1, "z", "", "", "", "", "", "", "", "", "", "",
+ "");
personal_data_->AddProfile(profile1);
WaitForOnPersonalDataChanged();
@@ -968,8 +988,8 @@ TEST_F(PersonalDataManagerTest, SetUniqueCreditCardLabels) {
TEST_F(PersonalDataManagerTest, SetEmptyProfile) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile0,
- "", "", "", "", "", "", "", "", "", "", "", "");
+ test::SetProfileInfo(&profile0, "", "", "", "", "", "", "", "", "", "", "",
+ "");
// Add the empty profile to the database.
personal_data_->AddProfile(profile0);
@@ -1005,16 +1025,14 @@ TEST_F(PersonalDataManagerTest, SetEmptyCreditCard) {
TEST_F(PersonalDataManagerTest, Refresh) {
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile0,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile0, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile1,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
- "US", "19482937549");
+ test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL,
+ "Orlando", "FL", "32801", "US", "19482937549");
// Add the test profiles to the database.
personal_data_->AddProfile(profile0);
@@ -1028,10 +1046,9 @@ TEST_F(PersonalDataManagerTest, Refresh) {
ExpectSameElements(profiles, personal_data_->GetProfiles());
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile2,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
- "32801", "US", "19482937549");
+ test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
+ "Orlando", "FL", "32801", "US", "19482937549");
autofill_database_service_->AddAutofillProfile(profile2);
@@ -1071,17 +1088,17 @@ TEST_F(PersonalDataManagerTest, Refresh) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "21 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
@@ -1096,9 +1113,9 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles) {
WaitForOnPersonalDataChanged();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected, "George", NULL,
- "Washington", "theprez@gmail.com", NULL, "21 Laussat St", NULL,
- "San Francisco", "California", "94102", NULL, NULL);
+ test::SetProfileInfo(&expected, "George", NULL, "Washington",
+ "theprez@gmail.com", NULL, "21 Laussat St", NULL,
+ "San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
@@ -1107,16 +1124,16 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_BadEmail) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("Email:", "email", "bogus", "text", &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "21 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
@@ -1135,11 +1152,11 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_BadEmail) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoEmails) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "Name:", "name", "George Washington", "text", &field);
+ test::CreateTestFormField("Name:", "name", "George Washington", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "21 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
@@ -1147,11 +1164,11 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoEmails) {
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "example@example.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "example@example.com", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Confirm email:", "confirm_email", "example@example.com", "text", &field);
+ test::CreateTestFormField("Confirm email:", "confirm_email",
+ "example@example.com", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
@@ -1166,11 +1183,11 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoEmails) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoDifferentEmails) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "Name:", "name", "George Washington", "text", &field);
+ test::CreateTestFormField("Name:", "name", "George Washington", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "21 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
@@ -1178,11 +1195,11 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoDifferentEmails) {
form.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "example@example.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "example@example.com", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email2", "example2@example.com", "text", &field);
+ test::CreateTestFormField("Email:", "email2", "example2@example.com", "text",
+ &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
@@ -1195,14 +1212,14 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_TwoDifferentEmails) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_NotEnoughFilledFields) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Card number:", "card_number", "4111 1111 1111 1111", "text", &field);
+ test::CreateTestFormField("Card number:", "card_number",
+ "4111 1111 1111 1111", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
@@ -1219,8 +1236,8 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressUSA) {
FormFieldData field;
test::CreateTestFormField("Name:", "name", "Barack Obama", "text", &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address", "1600 Pennsylvania Avenue", "text", &field);
+ test::CreateTestFormField("Address:", "address", "1600 Pennsylvania Avenue",
+ "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Washington", "text", &field);
form.fields.push_back(field);
@@ -1246,16 +1263,16 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressGB) {
FormFieldData field;
test::CreateTestFormField("Name:", "name", "David Cameron", "text", &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address", "10 Downing Street", "text", &field);
+ test::CreateTestFormField("Address:", "address", "10 Downing Street", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "London", "text", &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Postcode:", "postcode", "SW1A 2AA", "text", &field);
+ test::CreateTestFormField("Postcode:", "postcode", "SW1A 2AA", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Country:", "country", "United Kingdom", "text", &field);
+ test::CreateTestFormField("Country:", "country", "United Kingdom", "text",
+ &field);
form.fields.push_back(field);
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
@@ -1271,11 +1288,11 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MinimumAddressGI) {
// There are no cities or provinces and no postal/zip code system.
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "Name:", "name", "Sir Adrian Johns", "text", &field);
+ test::CreateTestFormField("Name:", "name", "Sir Adrian Johns", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address", "The Convent, Main Street", "text", &field);
+ test::CreateTestFormField("Address:", "address", "The Convent, Main Street",
+ "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Country:", "country", "Gibraltar", "text", &field);
form.fields.push_back(field);
@@ -1292,26 +1309,26 @@ TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_PhoneNumberSplitAcrossMultipleFields) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Phone #:", "home_phone_area_code", "650", "text", &field);
+ test::CreateTestFormField("Phone #:", "home_phone_area_code", "650", "text",
+ &field);
field.max_length = 3;
form.fields.push_back(field);
- test::CreateTestFormField(
- "Phone #:", "home_phone_prefix", "555", "text", &field);
+ test::CreateTestFormField("Phone #:", "home_phone_prefix", "555", "text",
+ &field);
field.max_length = 3;
form.fields.push_back(field);
- test::CreateTestFormField(
- "Phone #:", "home_phone_suffix", "0000", "text", &field);
+ test::CreateTestFormField("Phone #:", "home_phone_suffix", "0000", "text",
+ &field);
field.max_length = 4;
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "21 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
@@ -1326,9 +1343,9 @@ TEST_F(PersonalDataManagerTest,
WaitForOnPersonalDataChanged();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected, "George", NULL,
- "Washington", NULL, NULL, "21 Laussat St", NULL,
- "San Francisco", "California", "94102", NULL, "(650) 555-0000");
+ test::SetProfileInfo(&expected, "George", NULL, "Washington", NULL, NULL,
+ "21 Laussat St", NULL, "San Francisco", "California",
+ "94102", NULL, "(650) 555-0000");
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
@@ -1337,22 +1354,19 @@ TEST_F(PersonalDataManagerTest,
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MultilineAddress) {
FormData form;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form.fields.push_back(field);
- test::CreateTestFormField(
- "Address:",
- "street_address",
- "21 Laussat St\n"
- "Apt. #42",
- "textarea",
- &field);
+ test::CreateTestFormField("Address:", "street_address",
+ "21 Laussat St\n"
+ "Apt. #42",
+ "textarea", &field);
form.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form.fields.push_back(field);
@@ -1367,9 +1381,9 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MultilineAddress) {
WaitForOnPersonalDataChanged();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected, "George", NULL,
- "Washington", "theprez@gmail.com", NULL, "21 Laussat St", "Apt. #42",
- "San Francisco", "California", "94102", NULL, NULL);
+ test::SetProfileInfo(&expected, "George", NULL, "Washington",
+ "theprez@gmail.com", NULL, "21 Laussat St", "Apt. #42",
+ "San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles();
ASSERT_EQ(1U, results.size());
EXPECT_EQ(0, expected.Compare(*results[0]));
@@ -1379,17 +1393,17 @@ TEST_F(PersonalDataManagerTest,
ImportAddressProfiles_TwoValidProfilesDifferentForms) {
FormData form1;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "21 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form1.fields.push_back(field);
@@ -1405,26 +1419,25 @@ TEST_F(PersonalDataManagerTest,
WaitForOnPersonalDataChanged();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected, "George", NULL,
- "Washington", "theprez@gmail.com", NULL, "21 Laussat St", NULL,
- "San Francisco", "California", "94102", NULL, NULL);
+ test::SetProfileInfo(&expected, "George", NULL, "Washington",
+ "theprez@gmail.com", NULL, "21 Laussat St", NULL,
+ "San Francisco", "California", "94102", NULL, NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Now create a completely different profile.
FormData form2;
- test::CreateTestFormField(
- "First name:", "first_name", "John", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "John", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Adams", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Adams", "text", &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "second@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "second@gmail.com", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address1", "22 Laussat St", "text", &field);
+ test::CreateTestFormField("Address:", "address1", "22 Laussat St", "text",
+ &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form2.fields.push_back(field);
@@ -1440,9 +1453,9 @@ TEST_F(PersonalDataManagerTest,
WaitForOnPersonalDataChanged();
AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected2, "John", NULL,
- "Adams", "second@gmail.com", NULL, "22 Laussat St", NULL,
- "San Francisco", "California", "94102", NULL, NULL);
+ test::SetProfileInfo(&expected2, "John", NULL, "Adams", "second@gmail.com",
+ NULL, "22 Laussat St", NULL, "San Francisco",
+ "California", "94102", NULL, NULL);
std::vector<AutofillProfile*> profiles;
profiles.push_back(&expected);
profiles.push_back(&expected2);
@@ -1540,8 +1553,7 @@ TEST_F(PersonalDataManagerTest,
// There is an empty but hidden form section (this has been observed on sites
// where users can choose which form section they choose by unhiding it).
- test::CreateTestFormField("First name:", "first_name", "", "text",
- &field);
+ test::CreateTestFormField("First name:", "first_name", "", "text", &field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("Last name:", "last_name", "", "text", &field);
@@ -1673,17 +1685,17 @@ TEST_F(PersonalDataManagerTest,
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) {
FormData form1;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address", "1600 Pennsylvania Avenue", "text", &field);
+ test::CreateTestFormField("Address:", "address", "1600 Pennsylvania Avenue",
+ "text", &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 2:", "address2", "Suite A", "text", &field);
+ test::CreateTestFormField("Address Line 2:", "address2", "Suite A", "text",
+ &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form1.fields.push_back(field);
@@ -1691,8 +1703,8 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) {
form1.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form1.fields.push_back(field);
test::CreateTestFormField("Phone:", "phone", "6505556666", "text", &field);
form1.fields.push_back(field);
@@ -1714,17 +1726,17 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) {
// Now create an updated profile.
FormData form2;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Address:", "address", "1600 Pennsylvania Avenue", "text", &field);
+ test::CreateTestFormField("Address:", "address", "1600 Pennsylvania Avenue",
+ "text", &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 2:", "address2", "Suite A", "text", &field);
+ test::CreateTestFormField("Address Line 2:", "address2", "Suite A", "text",
+ &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
form2.fields.push_back(field);
@@ -1732,8 +1744,8 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) {
form2.fields.push_back(field);
test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form2.fields.push_back(field);
// Country gets added.
test::CreateTestFormField("Country:", "country", "USA", "text", &field);
@@ -1762,14 +1774,14 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_SameProfileWithConflict) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInOld) {
FormData form1;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 1:", "address", "190 High Street", "text", &field);
+ test::CreateTestFormField("Address Line 1:", "address", "190 High Street",
+ "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form1.fields.push_back(field);
@@ -1785,26 +1797,26 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInOld) {
WaitForOnPersonalDataChanged();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected, "George", NULL,
- "Washington", NULL, NULL, "190 High Street", NULL,
- "Philadelphia", "Pennsylvania", "19106", NULL, NULL);
+ test::SetProfileInfo(&expected, "George", NULL, "Washington", NULL, NULL,
+ "190 High Street", NULL, "Philadelphia", "Pennsylvania",
+ "19106", NULL, NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Submit a form with new data for the first profile.
FormData form2;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 1:", "address", "190 High Street", "text", &field);
+ test::CreateTestFormField("Address Line 1:", "address", "190 High Street",
+ "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form2.fields.push_back(field);
@@ -1822,9 +1834,9 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInOld) {
const std::vector<AutofillProfile*>& results2 = personal_data_->GetProfiles();
AutofillProfile expected2(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected2, "George", NULL,
- "Washington", "theprez@gmail.com", NULL, "190 High Street", NULL,
- "Philadelphia", "Pennsylvania", "19106", NULL, NULL);
+ test::SetProfileInfo(&expected2, "George", NULL, "Washington",
+ "theprez@gmail.com", NULL, "190 High Street", NULL,
+ "Philadelphia", "Pennsylvania", "19106", NULL, NULL);
expected2.SetRawInfo(NAME_FULL, base::ASCIIToUTF16("George Washington"));
ASSERT_EQ(1U, results2.size());
EXPECT_EQ(0, expected2.Compare(*results2[0]));
@@ -1833,20 +1845,20 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInOld) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInNew) {
FormData form1;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Company:", "company", "Government", "text", &field);
+ test::CreateTestFormField("Company:", "company", "Government", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 1:", "address", "190 High Street", "text", &field);
+ test::CreateTestFormField("Address Line 1:", "address", "190 High Street",
+ "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form1.fields.push_back(field);
@@ -1862,27 +1874,28 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInNew) {
WaitForOnPersonalDataChanged();
AutofillProfile expected(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&expected, "George", NULL,
- "Washington", "theprez@gmail.com", "Government", "190 High Street", NULL,
- "Philadelphia", "Pennsylvania", "19106", NULL, NULL);
+ test::SetProfileInfo(&expected, "George", NULL, "Washington",
+ "theprez@gmail.com", "Government", "190 High Street",
+ NULL, "Philadelphia", "Pennsylvania", "19106", NULL,
+ NULL);
const std::vector<AutofillProfile*>& results1 = personal_data_->GetProfiles();
ASSERT_EQ(1U, results1.size());
EXPECT_EQ(0, expected.Compare(*results1[0]));
// Submit a form with new data for the first profile.
FormData form2;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form2.fields.push_back(field);
// Note missing Company field.
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form2.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 1:", "address", "190 High Street", "text", &field);
+ test::CreateTestFormField("Address Line 1:", "address", "190 High Street",
+ "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form2.fields.push_back(field);
@@ -1908,20 +1921,20 @@ TEST_F(PersonalDataManagerTest, ImportAddressProfiles_MissingInfoInNew) {
TEST_F(PersonalDataManagerTest, ImportAddressProfiles_InsufficientAddress) {
FormData form1;
FormFieldData field;
- test::CreateTestFormField(
- "First name:", "first_name", "George", "text", &field);
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Last name:", "last_name", "Washington", "text", &field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Company:", "company", "Government", "text", &field);
+ test::CreateTestFormField("Company:", "company", "Government", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Email:", "email", "theprez@gmail.com", "text", &field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
form1.fields.push_back(field);
- test::CreateTestFormField(
- "Address Line 1:", "address", "190 High Street", "text", &field);
+ test::CreateTestFormField("Address Line 1:", "address", "190 High Street",
+ "text", &field);
form1.fields.push_back(field);
test::CreateTestFormField("City:", "city", "Philadelphia", "text", &field);
form1.fields.push_back(field);
@@ -2868,7 +2881,7 @@ TEST_F(PersonalDataManagerTest, ImportFormData_OneAddressOneCreditCard) {
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_TRUE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
ASSERT_TRUE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -2947,7 +2960,7 @@ TEST_F(PersonalDataManagerTest, ImportFormData_TwoAddressesOneCreditCard) {
bool imported_credit_card_matches_masked_server_credit_card;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
ASSERT_TRUE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -2967,15 +2980,69 @@ TEST_F(PersonalDataManagerTest, ImportFormData_TwoAddressesOneCreditCard) {
EXPECT_EQ(0, expected_card.Compare(*results[0]));
}
+TEST_F(PersonalDataManagerTest, ImportFormData_OneAddressCreditCardDisabled) {
+ FormData form;
+ FormFieldData field;
+ // Address section.
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Address:", "address1", "21 Laussat St", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("State:", "state", "California", "text", &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
+ form.fields.push_back(field);
+
+ // Credit card section.
+ AddFullCreditCardForm(&form, "Biggie Smalls", "4111-1111-1111-1111", "01",
+ "2999");
+
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes(nullptr /* ukm_service */);
+ std::unique_ptr<CreditCard> imported_credit_card;
+ bool imported_credit_card_matches_masked_server_credit_card;
+ EXPECT_TRUE(personal_data_->ImportFormData(
+ form_structure, false, false, &imported_credit_card,
+ &imported_credit_card_matches_masked_server_credit_card));
+ ASSERT_FALSE(imported_credit_card);
+
+ WaitForOnPersonalDataChanged();
+
+ // Test that the address has been saved.
+ AutofillProfile expected_address(base::GenerateGUID(),
+ "https://www.example.com");
+ test::SetProfileInfo(&expected_address, "George", NULL, "Washington",
+ "theprez@gmail.com", NULL, "21 Laussat St", NULL,
+ "San Francisco", "California", "94102", NULL, NULL);
+ const std::vector<AutofillProfile*>& results_addr =
+ personal_data_->GetProfiles();
+ ASSERT_EQ(1U, results_addr.size());
+ EXPECT_EQ(0, expected_address.Compare(*results_addr[0]));
+
+ // Test that the credit card was not saved.
+ const std::vector<CreditCard*>& results_cards =
+ personal_data_->GetCreditCards();
+ ASSERT_EQ(0U, results_cards.size());
+}
+
// Ensure that verified profiles can be saved via SaveImportedProfile,
// overwriting existing unverified profiles.
TEST_F(PersonalDataManagerTest, SaveImportedProfileWithVerifiedData) {
// Start with an unverified profile.
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
EXPECT_FALSE(profile.IsVerified());
// Add the profile to the database.
@@ -3048,10 +3115,9 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
// Test with one profile stored.
AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile0,
- "Marion", NULL, "Morrison",
- "johnwayne@me.xyz", NULL, "123 Zoo St.", NULL, "Hollywood", "CA",
- "91601", "US", "14155678910");
+ test::SetProfileInfo(&profile0, "Marion", NULL, "Morrison",
+ "johnwayne@me.xyz", NULL, "123 Zoo St.", NULL,
+ "Hollywood", "CA", "91601", "US", "14155678910");
personal_data_->AddProfile(profile0);
@@ -3079,16 +3145,14 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) {
// Test with multiple profiles stored.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile1,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL, "Orlando", "FL", "32801",
- "US", "16502937549");
+ test::SetProfileInfo(&profile1, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "903 Apple Ct.", NULL,
+ "Orlando", "FL", "32801", "US", "16502937549");
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile2,
- "Josephine", "Alicia", "Saenz",
- "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5", "Orlando", "FL",
- "32801", "US", "16502937549");
+ test::SetProfileInfo(&profile2, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
+ "Orlando", "FL", "32801", "US", "16502937549");
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
@@ -3166,8 +3230,8 @@ TEST_F(PersonalDataManagerTest, IncognitoReadOnly) {
AutofillProfile steve_jobs(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&steve_jobs, "Steven", "Paul", "Jobs", "sjobs@apple.com",
- "Apple Computer, Inc.", "1 Infinite Loop", "", "Cupertino", "CA", "95014",
- "US", "(800) 275-2273");
+ "Apple Computer, Inc.", "1 Infinite Loop", "",
+ "Cupertino", "CA", "95014", "US", "(800) 275-2273");
personal_data_->AddProfile(steve_jobs);
CreditCard bill_gates(base::GenerateGUID(), "https://www.example.com");
@@ -3242,9 +3306,9 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeIsCached) {
EXPECT_EQ(2U, default_country.size());
AutofillProfile moose(base::GenerateGUID(), kSettingsOrigin);
- test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com",
- "", "1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2",
- "CA", "(800) 555-9000");
+ test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com", "",
+ "1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2", "CA",
+ "(800) 555-9000");
personal_data_->AddProfile(moose);
// Make sure everything is set up correctly.
@@ -3272,22 +3336,22 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeIsCached) {
TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
AutofillProfile moose(base::GenerateGUID(), kSettingsOrigin);
- test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com",
- "", "1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2",
- "CA", "(800) 555-9000");
+ test::SetProfileInfo(&moose, "Moose", "P", "McMahon", "mpm@example.com", "",
+ "1 Taiga TKTR", "", "Calgary", "AB", "T2B 2K2", "CA",
+ "(800) 555-9000");
personal_data_->AddProfile(moose);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("CA", personal_data_->GetDefaultCountryCodeForNewAddress());
// Multiple profiles cast votes.
AutofillProfile armadillo(base::GenerateGUID(), kSettingsOrigin);
- test::SetProfileInfo(&armadillo, "Armin", "Dill", "Oh", "ado@example.com",
- "", "1 Speed Bump", "", "Lubbock", "TX", "77500",
- "MX", "(800) 555-9000");
+ test::SetProfileInfo(&armadillo, "Armin", "Dill", "Oh", "ado@example.com", "",
+ "1 Speed Bump", "", "Lubbock", "TX", "77500", "MX",
+ "(800) 555-9000");
AutofillProfile armadillo2(base::GenerateGUID(), kSettingsOrigin);
test::SetProfileInfo(&armadillo2, "Armin", "Dill", "Oh", "ado@example.com",
- "", "2 Speed Bump", "", "Lubbock", "TX", "77500",
- "MX", "(800) 555-9000");
+ "", "2 Speed Bump", "", "Lubbock", "TX", "77500", "MX",
+ "(800) 555-9000");
personal_data_->AddProfile(armadillo);
personal_data_->AddProfile(armadillo2);
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -3316,9 +3380,9 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
personal_data_->RemoveByGUID(armadillo.guid());
personal_data_->RemoveByGUID(moose.guid());
AutofillProfile space_invader(base::GenerateGUID(), kSettingsOrigin);
- test::SetProfileInfo(&space_invader, "Marty", "", "Martian",
- "mm@example.com", "", "1 Flying Object", "", "Valles Marineris", "",
- "", "XX", "");
+ test::SetProfileInfo(&space_invader, "Marty", "", "Martian", "mm@example.com",
+ "", "1 Flying Object", "", "Valles Marineris", "", "",
+ "XX", "");
personal_data_->AddProfile(moose);
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_EQ("MX", personal_data_->GetDefaultCountryCodeForNewAddress());
@@ -3326,15 +3390,14 @@ TEST_F(PersonalDataManagerTest, DefaultCountryCodeComesFromProfiles) {
TEST_F(PersonalDataManagerTest, UpdateLanguageCodeInProfile) {
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile);
// Make sure everything is set up correctly.
WaitForOnPersonalDataChanged();
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetProfiles().size());
profile.set_language_code("en");
@@ -3350,11 +3413,10 @@ TEST_F(PersonalDataManagerTest, UpdateLanguageCodeInProfile) {
TEST_F(PersonalDataManagerTest, GetProfileSuggestions) {
AutofillProfile profile(base::GenerateGUID(), "https://www.example.com");
- test::SetProfileInfo(&profile,
- "Marion", "Mitchell", "Morrison",
- "johnwayne@me.xyz", "Fox",
- "123 Zoo St.\nSecond Line\nThird line", "unit 5", "Hollywood", "CA",
- "91601", "US", "12345678910");
+ test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
+ "johnwayne@me.xyz", "Fox",
+ "123 Zoo St.\nSecond Line\nThird line", "unit 5",
+ "Hollywood", "CA", "91601", "US", "12345678910");
personal_data_->AddProfile(profile);
ResetPersonalDataManager(USER_MODE_NORMAL);
@@ -3605,6 +3667,103 @@ TEST_F(PersonalDataManagerTest,
}
}
+TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesMaskedServerCard) {
+ // Add a masked server card.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
+ "2110" /* last 4 digits */, "12", "2999", "1");
+ server_cards.back().SetNetworkForMaskedCard(kVisaCard);
+
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(base::ASCIIToUTF16("4234 5678 9012 2110") /* Visa */);
+ ASSERT_TRUE(personal_data_->IsKnownCard(cardToCompare));
+}
+
+TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesFullServerCard) {
+ // Add a full server card.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b459"));
+ test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
+ "4234567890122110" /* Visa */, "12", "2999", "1");
+
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(base::ASCIIToUTF16("4234 5678 9012 2110") /* Visa */);
+ ASSERT_TRUE(personal_data_->IsKnownCard(cardToCompare));
+}
+
+TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesLocalCard) {
+ EnableWalletCardImport();
+ // Add a local card.
+ CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
+ "4234 5678 9012 2110" /* Visa */, "04", "2999", "1");
+ personal_data_->AddCreditCard(credit_card0);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(base::ASCIIToUTF16("4234567890122110") /* Visa */);
+ ASSERT_TRUE(personal_data_->IsKnownCard(cardToCompare));
+}
+
+TEST_F(PersonalDataManagerTest, IsKnownCard_TypeDoesNotMatch) {
+ EnableWalletCardImport();
+ // Add a local card.
+ CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
+ "4234 5678 9012 2110" /* Visa */, "04", "2999", "1");
+ personal_data_->AddCreditCard(credit_card0);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(
+ base::ASCIIToUTF16("5105 1051 0510 2110") /* American Express */);
+ ASSERT_FALSE(personal_data_->IsKnownCard(cardToCompare));
+}
+
+TEST_F(PersonalDataManagerTest, IsKnownCard_LastFourDoesNotMatch) {
+ EnableWalletCardImport();
+ // Add a local card.
+ CreditCard credit_card0("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
+ "4234 5678 9012 2110" /* Visa */, "04", "2999", "1");
+ personal_data_->AddCreditCard(credit_card0);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ CreditCard cardToCompare;
+ cardToCompare.SetNumber(base::ASCIIToUTF16("4234 5678 9012 0000") /* Visa */);
+ ASSERT_FALSE(personal_data_->IsKnownCard(cardToCompare));
+}
+
// Test that a masked server card is not suggested if more that six numbers have
// been typed in the field.
TEST_F(PersonalDataManagerTest,
@@ -3701,6 +3860,48 @@ TEST_F(PersonalDataManagerTest,
EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[4].value);
}
+// Test that local and server cards are not shown if
+// |kAutofillCreditCardEnabled| is set to |false|.
+TEST_F(PersonalDataManagerTest,
+ GetCreditCardSuggestions_CreditCardAutofillDisabled) {
+ EnableWalletCardImport();
+ SetUpReferenceLocalCreditCards();
+
+ // Add some server cards.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
+ "2999", "1");
+ server_cards.back().set_use_count(2);
+ server_cards.back().set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
+ server_cards.back().SetNetworkForMaskedCard(kVisaCard);
+
+ server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b460"));
+ test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
+ "2999", "1");
+ server_cards.back().set_use_count(6);
+ server_cards.back().set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
+
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Disable Credit card autofill.
+ personal_data_->pref_service_->SetBoolean(prefs::kAutofillCreditCardEnabled,
+ false);
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+
+ // Expect no autofilled values or suggestions.
+ EXPECT_EQ(0U, personal_data_->GetCreditCards().size());
+
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NAME_FULL),
+ /* field_contents= */ base::string16());
+ ASSERT_EQ(0U, suggestions.size());
+}
+
// Test that expired cards are ordered by frecency and are always suggested
// after non expired cards even if they have a higher frecency score.
TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ExpiredCards) {
@@ -3753,6 +3954,139 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ExpiredCards) {
EXPECT_EQ(base::ASCIIToUTF16("John Dillinger"), suggestions[2].value);
}
+// Test cards that are expired AND disused are suppressed when supression is
+// enabled and the input field is empty.
+TEST_F(PersonalDataManagerTest,
+ GetCreditCardSuggestions_SuppressDisusedCreditCardsOnEmptyField) {
+ ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
+
+ // Add a never used non expired local credit card.
+ CreditCard credit_card0("002149C1-EE28-4213-A3B9-DA243FFF021B",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card0, "Bonnie Parker",
+ "5105105105105100" /* Mastercard */, "04", "2999",
+ "1");
+ personal_data_->AddCreditCard(credit_card0);
+
+ auto now = AutofillClock::Now();
+
+ // Add an expired unmasked card last used 10 days ago
+ CreditCard credit_card1(CreditCard::FULL_SERVER_CARD, "c789");
+ test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
+ "4234567890123456" /* Visa */, "04", "1999", "1");
+ credit_card1.set_use_date(now - base::TimeDelta::FromDays(10));
+
+ // Add an expired masked card last used 180 days ago.
+ CreditCard credit_card2(CreditCard::MASKED_SERVER_CARD, "c987");
+ test::SetCreditCardInfo(&credit_card2, "Jane Doe", "6543", "01", "1998", "1");
+ credit_card2.set_use_date(now - base::TimeDelta::FromDays(181));
+ credit_card2.SetNetworkForMaskedCard(kVisaCard);
+
+ // Save the server cards and set used_date to desired dates.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(credit_card1);
+ server_cards.push_back(credit_card2);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+ personal_data_->UpdateServerCardMetadata(credit_card1);
+ personal_data_->UpdateServerCardMetadata(credit_card2);
+
+ // Add an expired local card last used 180 days ago.
+ CreditCard credit_card3("1141084B-72D7-4B73-90CF-3D6AC154673B",
+ "https://www.example.com");
+ credit_card3.set_use_date(now - base::TimeDelta::FromDays(182));
+ test::SetCreditCardInfo(&credit_card3, "John Dillinger",
+ "378282246310005" /* American Express */, "01",
+ "1998", "1");
+ personal_data_->AddCreditCard(credit_card3);
+
+ // Make sure everything is set up correctly.
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+ ASSERT_EQ(4U, personal_data_->GetCreditCards().size());
+
+ // Verify credit card suppression is disabled by default.
+ {
+ ASSERT_FALSE(
+ base::FeatureList::IsEnabled(kAutofillSuppressDisusedCreditCards));
+ }
+
+ // Verify no suppression if feature is disabled.
+ {
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndDisableFeature(kAutofillSuppressDisusedCreditCards);
+
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NAME_FULL), base::string16());
+ EXPECT_EQ(4U, suggestions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[0].value);
+ EXPECT_EQ(base::ASCIIToUTF16("Clyde Barrow"), suggestions[1].value);
+ EXPECT_EQ(base::ASCIIToUTF16("Jane Doe"), suggestions[2].value);
+ EXPECT_EQ(base::ASCIIToUTF16("John Dillinger"), suggestions[3].value);
+ }
+
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndEnableFeature(kAutofillSuppressDisusedCreditCards);
+
+ // Query with empty string only returns card0 and card1. Note expired
+ // masked card2 is not suggested on empty fields.
+ {
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NAME_FULL), base::string16());
+ EXPECT_EQ(2U, suggestions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[0].value);
+ EXPECT_EQ(base::ASCIIToUTF16("Clyde Barrow"), suggestions[1].value);
+ }
+
+ // Query with name prefix for card0 returns card0.
+ {
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NAME_FULL), base::ASCIIToUTF16("B"));
+
+ ASSERT_EQ(1U, suggestions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[0].value);
+ }
+
+ // Query with name prefix for card1 returns card1.
+ {
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NAME_FULL), base::ASCIIToUTF16("Cl"));
+
+ ASSERT_EQ(1U, suggestions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("Clyde Barrow"), suggestions[0].value);
+ }
+
+ // Query with name prefix for card2 returns card2.
+ {
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NAME_FULL), base::ASCIIToUTF16("Jo"));
+
+ ASSERT_EQ(1U, suggestions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("John Dillinger"), suggestions[0].value);
+ }
+
+ // Query with card number prefix for card1 returns card1 and card2.
+ // Expired masked card2 is shown when user starts to type credit card
+ // number because we are not sure if it is the masked card that they want.
+ {
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ AutofillType(CREDIT_CARD_NUMBER), base::ASCIIToUTF16("4234"));
+
+ ASSERT_EQ(2U, suggestions.size());
+ EXPECT_EQ(
+ base::UTF8ToUTF16(std::string("Visa") + kUTF8MidlineEllipsis + "3456"),
+ suggestions[0].value);
+ EXPECT_EQ(
+ base::UTF8ToUTF16(std::string("Visa") + kUTF8MidlineEllipsis + "6543"),
+ suggestions[1].value);
+ }
+}
+
// Test that a card that doesn't have a number is not shown in the suggestions
// when querying credit cards by their number.
TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_NumberMissing) {
@@ -4215,8 +4549,8 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
CreditCard* unmasked_card = &server_cards.front();
unmasked_card->set_record_type(CreditCard::FULL_SERVER_CARD);
unmasked_card->SetNumber(base::ASCIIToUTF16("4234567890123456"));
- EXPECT_NE(0, unmasked_card->Compare(
- *personal_data_->GetCreditCards().front()));
+ EXPECT_NE(0,
+ unmasked_card->Compare(*personal_data_->GetCreditCards().front()));
personal_data_->UpdateServerCreditCard(*unmasked_card);
WaitForOnPersonalDataChanged();
@@ -4355,7 +4689,7 @@ TEST_F(PersonalDataManagerTest, AllowDuplicateMaskedServerCardIfFlagEnabled) {
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_TRUE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
ASSERT_TRUE(imported_credit_card);
EXPECT_TRUE(imported_credit_card_matches_masked_server_credit_card);
@@ -4415,7 +4749,7 @@ TEST_F(PersonalDataManagerTest, DontDuplicateMaskedServerCard) {
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
ASSERT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -4463,7 +4797,7 @@ TEST_F(PersonalDataManagerTest, DontDuplicateFullServerCard) {
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -4506,7 +4840,7 @@ TEST_F(PersonalDataManagerTest,
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -4553,7 +4887,7 @@ TEST_F(PersonalDataManagerTest,
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -4600,7 +4934,7 @@ TEST_F(PersonalDataManagerTest,
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -4648,7 +4982,7 @@ TEST_F(PersonalDataManagerTest,
std::unique_ptr<CreditCard> imported_credit_card;
bool imported_credit_card_matches_masked_server_credit_card;
EXPECT_FALSE(personal_data_->ImportFormData(
- form_structure, false, &imported_credit_card,
+ form_structure, true, false, &imported_credit_card,
&imported_credit_card_matches_masked_server_credit_card));
EXPECT_FALSE(imported_credit_card);
EXPECT_FALSE(imported_credit_card_matches_masked_server_credit_card);
@@ -6163,6 +6497,268 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_OncePerVersion) {
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
}
+// Tests that DeleteDisusedAddresses is not run if the feature is disabled.
+TEST_F(PersonalDataManagerTest, DeleteDisusedAddresses_DoNothingWhenDisabled) {
+ // Make sure feature is disabled by default.
+ EXPECT_FALSE(base::FeatureList::IsEnabled(kAutofillDeleteDisusedAddresses));
+
+ CreateDeletableDisusedProfile();
+
+ // DeleteDisusedCreditCards should return false to indicate it was not run.
+ EXPECT_FALSE(personal_data_->DeleteDisusedAddresses());
+
+ personal_data_->Refresh();
+
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
+}
+
+// Tests that DeleteDisusedAddresses is not run a second time on the same
+// major version.
+TEST_F(PersonalDataManagerTest, DeleteDisusedAddresses_OncePerVersion) {
+ // Enable the feature.
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedAddresses);
+
+ CreateDeletableDisusedProfile();
+
+ EXPECT_TRUE(personal_data_->DeleteDisusedAddresses());
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(0U, personal_data_->GetProfiles().size());
+
+ // Add the profile back.
+ CreateDeletableDisusedProfile();
+
+ // DeleteDisusedAddresses should return false to indicate it was not run.
+ EXPECT_FALSE(personal_data_->DeleteDisusedAddresses());
+
+ personal_data_->Refresh();
+
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
+}
+
+// Tests that DeleteDisusedAddresses only deletes the addresses that are
+// supposed to be deleted.
+TEST_F(PersonalDataManagerTest,
+ DeleteDisusedAddresses_DeleteDesiredAddressesOnly) {
+ // Enable the feature.
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedAddresses);
+
+ auto now = AutofillClock::Now();
+
+ // Create unverified/disused/not-used-by-valid-credit-card
+ // address(deletable).
+ AutofillProfile profile0(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile0, "Alice", "", "Delete", "", "ACME",
+ "1234 Evergreen Terrace", "Bld. 6", "Springfield", "IL",
+ "32801", "US", "15151231234");
+ profile0.set_use_date(now - base::TimeDelta::FromDays(400));
+ personal_data_->AddProfile(profile0);
+
+ // Create unverified/disused/used-by-expired-credit-card address(deletable).
+ AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile1, "Bob", "", "Delete", "", "ACME",
+ "1234 Evergreen Terrace", "Bld. 7", "Springfield", "IL",
+ "32801", "US", "15151231234");
+ profile1.set_use_date(now - base::TimeDelta::FromDays(400));
+ CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card0, "Bob",
+ "5105105105105100" /* Mastercard */, "04", "1999",
+ "1");
+ credit_card0.set_use_date(now - base::TimeDelta::FromDays(400));
+ credit_card0.set_billing_address_id(profile1.guid());
+ personal_data_->AddProfile(profile1);
+ personal_data_->AddCreditCard(credit_card0);
+
+ // Create verified/disused/not-used-by-valid-credit-card address(not
+ // deletable).
+ AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile2, "Charlie", "", "Keep", "", "ACME",
+ "1234 Evergreen Terrace", "Bld. 8", "Springfield", "IL",
+ "32801", "US", "15151231234");
+ profile2.set_origin(kSettingsOrigin);
+ profile2.set_use_date(now - base::TimeDelta::FromDays(400));
+ personal_data_->AddProfile(profile2);
+
+ // Create unverified/recently-used/not-used-by-valid-credit-card address(not
+ // deletable).
+ AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile3, "Dave", "", "Keep", "", "ACME",
+ "1234 Evergreen Terrace", "Bld. 9", "Springfield", "IL",
+ "32801", "US", "15151231234");
+ profile3.set_use_date(now - base::TimeDelta::FromDays(4));
+ personal_data_->AddProfile(profile3);
+
+ // Create unverified/disused/used-by-valid-credit-card address(not deletable).
+ AutofillProfile profile4(base::GenerateGUID(), "https://www.example.com");
+ test::SetProfileInfo(&profile4, "Emma", "", "Keep", "", "ACME",
+ "1234 Evergreen Terrace", "Bld. 10", "Springfield", "IL",
+ "32801", "US", "15151231234");
+ profile4.set_use_date(now - base::TimeDelta::FromDays(400));
+ CreditCard credit_card1(CreditCard::MASKED_SERVER_CARD, "c987");
+ test::SetCreditCardInfo(&credit_card1, "Emma", "6543", "01", "2999", "1");
+ credit_card1.SetNetworkForMaskedCard(kVisaCard);
+ credit_card1.set_billing_address_id(profile4.guid());
+ credit_card1.set_use_date(now - base::TimeDelta::FromDays(1));
+ personal_data_->AddProfile(profile4);
+ personal_data_->AddCreditCard(credit_card1);
+
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(5U, personal_data_->GetProfiles().size());
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ // DeleteDisusedAddresses should return true.
+ EXPECT_TRUE(personal_data_->DeleteDisusedAddresses());
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(3U, personal_data_->GetProfiles().size());
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+ EXPECT_EQ(base::UTF8ToUTF16("Keep"),
+ personal_data_->GetProfiles()[0]->GetRawInfo(NAME_LAST));
+ EXPECT_EQ(base::UTF8ToUTF16("Keep"),
+ personal_data_->GetProfiles()[1]->GetRawInfo(NAME_LAST));
+ EXPECT_EQ(base::UTF8ToUTF16("Keep"),
+ personal_data_->GetProfiles()[2]->GetRawInfo(NAME_LAST));
+}
+
+// Tests that DeleteDisusedCreditCards is not run if the feature is disabled.
+TEST_F(PersonalDataManagerTest,
+ DeleteDisusedCreditCards_DoNothingWhenDisabled) {
+ // Make sure feature is disabled by default.
+ EXPECT_FALSE(base::FeatureList::IsEnabled(kAutofillDeleteDisusedCreditCards));
+
+ CreateDeletableExpiredAndDisusedCreditCard();
+
+ // DeleteDisusedCreditCards should return false to indicate it was not run.
+ EXPECT_FALSE(personal_data_->DeleteDisusedCreditCards());
+
+ personal_data_->Refresh();
+
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+}
+
+// Tests that DeleteDisusedCreditCards is not run a second time on the same
+// major version.
+TEST_F(PersonalDataManagerTest, DeleteDisusedCreditCards_OncePerVersion) {
+ // Enable the feature.
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedCreditCards);
+
+ CreateDeletableExpiredAndDisusedCreditCard();
+
+ // The deletion should be run a first time.
+ EXPECT_TRUE(personal_data_->DeleteDisusedCreditCards());
+ WaitForOnPersonalDataChanged();
+
+ // The profiles should have been deleted.
+ EXPECT_EQ(0U, personal_data_->GetCreditCards().size());
+
+ // Add the card back.
+ CreateDeletableExpiredAndDisusedCreditCard();
+
+ // The cleanup should not be run.
+ EXPECT_FALSE(personal_data_->DeleteDisusedCreditCards());
+
+ // The card should still be present.
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+}
+
+// Tests that DeleteDisusedCreditCards deletes desired credit cards only.
+TEST_F(PersonalDataManagerTest,
+ DeleteDisusedCreditCards_OnlyDeleteExpiredDisusedLocalCards) {
+ // Enable the feature.
+ base::test::ScopedFeatureList scoped_features;
+ scoped_features.InitAndEnableFeature(kAutofillDeleteDisusedCreditCards);
+
+ const char kHistogramName[] = "Autofill.CreditCardsDeletedForDisuse";
+ auto now = AutofillClock::Now();
+
+ // Create a recently used local card, it is expected to remain.
+ CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card1, "Alice",
+ "378282246310005" /* American Express */, "04",
+ "2999", "1");
+ credit_card1.set_use_date(now - base::TimeDelta::FromDays(4));
+
+ // Create a local card that was expired 400 days ago, but recently used.
+ // It is expected to remain.
+ CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card2, "Bob",
+ "378282246310006" /* American Express */, "04",
+ "1999", "1");
+ credit_card2.set_use_date(now - base::TimeDelta::FromDays(4));
+
+ // Create a local card expired recently, and last used 400 days ago.
+ // It is expected to remain.
+ CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card3, "Clyde", "4111111111111111" /* Visa */,
+ "04", "2017", "1");
+ credit_card3.set_use_date(now - base::TimeDelta::FromDays(400));
+
+ // Create a local card expired 400 days ago, and last used 400 days ago.
+ // It is expected to be deleted.
+ CreditCard credit_card4(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card4, "David",
+ "5105105105105100" /* Mastercard */, "04", "1999",
+ "1");
+ credit_card4.set_use_date(now - base::TimeDelta::FromDays(400));
+ personal_data_->AddCreditCard(credit_card1);
+ personal_data_->AddCreditCard(credit_card2);
+ personal_data_->AddCreditCard(credit_card3);
+ personal_data_->AddCreditCard(credit_card4);
+
+ // Create a unmasked server card expired 400 days ago, and last used 400
+ // days ago.
+ // It is expected to remain because we do not delete server cards.
+ CreditCard credit_card5(CreditCard::FULL_SERVER_CARD, "c789");
+ test::SetCreditCardInfo(&credit_card5, "Emma", "4234567890123456" /* Visa */,
+ "04", "1999", "1");
+ credit_card5.set_use_date(now - base::TimeDelta::FromDays(400));
+
+ // Create masked server card expired 400 days ago, and last used 400 days ago.
+ // It is expected to remain because we do not delete server cards.
+ CreditCard credit_card6(CreditCard::MASKED_SERVER_CARD, "c987");
+ test::SetCreditCardInfo(&credit_card6, "Frank", "6543", "01", "1998", "1");
+ credit_card6.set_use_date(now - base::TimeDelta::FromDays(400));
+ credit_card6.SetNetworkForMaskedCard(kVisaCard);
+
+ // Save the server cards and set used_date to desired dates.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(credit_card5);
+ server_cards.push_back(credit_card6);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+ personal_data_->UpdateServerCardMetadata(credit_card5);
+ personal_data_->UpdateServerCardMetadata(credit_card6);
+
+ WaitForOnPersonalDataChanged();
+ EXPECT_EQ(6U, personal_data_->GetCreditCards().size());
+
+ // Setup histograms capturing.
+ base::HistogramTester histogram_tester;
+
+ // DeleteDisusedCreditCards should return true to indicate it was run.
+ EXPECT_TRUE(personal_data_->DeleteDisusedCreditCards());
+
+ // Wait for the data to be refreshed.
+ WaitForOnPersonalDataChanged();
+
+ EXPECT_EQ(5U, personal_data_->GetCreditCards().size());
+ std::unordered_set<base::string16> expectedToRemain = {
+ base::UTF8ToUTF16("Alice"), base::UTF8ToUTF16("Bob"),
+ base::UTF8ToUTF16("Clyde"), base::UTF8ToUTF16("Emma"),
+ base::UTF8ToUTF16("Frank")};
+ for (auto* card : personal_data_->GetCreditCards()) {
+ EXPECT_NE(expectedToRemain.end(),
+ expectedToRemain.find(card->GetRawInfo(CREDIT_CARD_NAME_FULL)));
+ }
+
+ // Verify histograms are logged.
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectBucketCount(kHistogramName, 1, 1);
+}
+
// Tests that a new local profile is created if no existing one is a duplicate
// of the server address. Also tests that the billing address relationship was
// transferred to the converted address.
@@ -6222,7 +6818,7 @@ TEST_F(PersonalDataManagerTest,
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
@@ -6237,7 +6833,7 @@ TEST_F(PersonalDataManagerTest,
WaitForOnPersonalDataChanged();
// The Wallet address should have been added as a new local profile.
- EXPECT_EQ(2U, personal_data_->web_profiles().size());
+ EXPECT_EQ(2U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
histogram_tester.ExpectUniqueSample("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_ADDED,
@@ -6327,7 +6923,7 @@ TEST_F(PersonalDataManagerTest,
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
@@ -6342,7 +6938,7 @@ TEST_F(PersonalDataManagerTest,
WaitForOnPersonalDataChanged();
// The Wallet address should have been merged with the existing local profile.
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
histogram_tester.ExpectUniqueSample("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_MERGED,
@@ -6399,7 +6995,7 @@ TEST_F(PersonalDataManagerTest,
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- EXPECT_EQ(0U, personal_data_->web_profiles().size());
+ EXPECT_EQ(0U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
///////////////////////////////////////////////////////////////////////
@@ -6418,7 +7014,7 @@ TEST_F(PersonalDataManagerTest,
WaitForOnPersonalDataChanged();
// There should be no local profiles added.
- EXPECT_EQ(0U, personal_data_->web_profiles().size());
+ EXPECT_EQ(0U, personal_data_->GetProfiles().size());
EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
}
@@ -6495,7 +7091,7 @@ TEST_F(
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetServerProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
@@ -6511,7 +7107,7 @@ TEST_F(
// The first Wallet address should have been added as a new local profile and
// the second one should have merged with the first.
- EXPECT_EQ(2U, personal_data_->web_profiles().size());
+ EXPECT_EQ(2U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetServerProfiles().size());
histogram_tester.ExpectBucketCount("Autofill.WalletAddressConversionType",
AutofillMetrics::CONVERTED_ADDRESS_ADDED,
@@ -6597,7 +7193,7 @@ TEST_F(
WaitForOnPersonalDataChanged();
// The Wallet address should have been converted to a new local profile.
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
// The conversion should be recorded in the Wallet address.
EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
@@ -6622,7 +7218,7 @@ TEST_F(
// Make sure everything is set up correctly.
personal_data_->Refresh();
WaitForOnPersonalDataChanged();
- EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetProfiles().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
///////////////////////////////////////////////////////////////////////
@@ -6924,4 +7520,335 @@ TEST_F(PersonalDataManagerTest, RemoveProfilesNotUsedSinceTimestamp) {
}
}
+TEST_F(PersonalDataManagerTest, LogStoredCreditCardMetrics) {
+ EnableWalletCardImport();
+ ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
+
+ // Helper timestamps for setting up the test data.
+ base::Time now = AutofillClock::Now();
+ base::Time one_month_ago = now - base::TimeDelta::FromDays(30);
+ base::Time::Exploded now_exploded;
+ base::Time::Exploded one_month_ago_exploded;
+ now.LocalExplode(&now_exploded);
+ one_month_ago.LocalExplode(&one_month_ago_exploded);
+
+ std::vector<CreditCard> server_cards;
+ server_cards.reserve(10);
+
+ // Create in-use and in-disuse cards of each record type.
+ const std::vector<CreditCard::RecordType> record_types{
+ CreditCard::LOCAL_CARD, CreditCard::MASKED_SERVER_CARD,
+ CreditCard::FULL_SERVER_CARD};
+ for (auto record_type : record_types) {
+ // Create a card that's still in active use.
+ CreditCard card_in_use = test::GetRandomCreditCard(record_type);
+ card_in_use.set_use_date(now - base::TimeDelta::FromDays(30));
+ card_in_use.set_use_count(10);
+
+ // Create a card that's not in active use.
+ CreditCard card_in_disuse = test::GetRandomCreditCard(record_type);
+ card_in_disuse.SetExpirationYear(one_month_ago_exploded.year);
+ card_in_disuse.SetExpirationMonth(one_month_ago_exploded.month);
+ card_in_disuse.set_use_date(now - base::TimeDelta::FromDays(200));
+ card_in_disuse.set_use_count(10);
+
+ // Add the cards to the personal data manager in the appropriate way.
+ if (record_type == CreditCard::LOCAL_CARD) {
+ personal_data_->AddCreditCard(card_in_use);
+ personal_data_->AddCreditCard(card_in_disuse);
+ } else {
+ server_cards.push_back(std::move(card_in_use));
+ server_cards.push_back(std::move(card_in_disuse));
+ }
+ }
+
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // test::SetServerCreditCards modifies the metadata (use_count and use_date)
+ // of unmasked cards. Reset the server card metadata to match the data set
+ // up above.
+ for (const auto& card : server_cards)
+ autofill_table_->UpdateServerCardMetadata(card);
+
+ personal_data_->Refresh();
+ WaitForOnPersonalDataChanged();
+
+ ASSERT_EQ(6U, personal_data_->GetCreditCards().size());
+
+ // Reload the database, which will log the stored profile counts.
+ base::HistogramTester histogram_tester;
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+
+ ASSERT_EQ(6U, personal_data_->GetCreditCards().size());
+
+ // Validate the basic count metrics for both local and server cards. Deep
+ // validation of the metrics is done in:
+ // AutofillMetricsTest::LogStoredCreditCardMetrics
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount", 1);
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Local", 1);
+ histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Server", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardCount.Server.Masked", 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardCount.Server.Unmasked", 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount", 6, 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Local", 2,
+ 1);
+ histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Server", 4,
+ 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardCount.Server.Masked", 2, 1);
+ histogram_tester.ExpectBucketCount(
+ "Autofill.StoredCreditCardCount.Server.Unmasked", 2, 1);
+}
+
+TEST_F(PersonalDataManagerTest, RemoveExpiredCreditCardsNotUsedSinceTimestamp) {
+ const char kHistogramName[] = "Autofill.CreditCardsSuppressedForDisuse";
+ const base::Time kNow = AutofillClock::Now();
+ constexpr size_t kNumCards = 10;
+
+ // We construct a card vector as below, number indicate days of last used
+ // from |kNow|:
+ // [30, 90, 150, 210, 270, 0, 60, 120, 180, 240]
+ // |expires at 2999 |, |expired at 2001 |
+ std::vector<CreditCard> all_card_data;
+ std::vector<CreditCard*> all_card_ptrs;
+ all_card_data.reserve(kNumCards);
+ all_card_ptrs.reserve(kNumCards);
+ for (size_t i = 0; i < kNumCards; ++i) {
+ constexpr base::TimeDelta k30Days = base::TimeDelta::FromDays(30);
+ all_card_data.emplace_back(base::GenerateGUID(), "https://example.com");
+ if (i < 5) {
+ all_card_data.back().set_use_date(kNow - (i + i + 1) * k30Days);
+ test::SetCreditCardInfo(&all_card_data.back(), "Clyde Barrow",
+ "378282246310005" /* American Express */, "04",
+ "2999", "1");
+ } else {
+ all_card_data.back().set_use_date(kNow - (i + i - 10) * k30Days);
+ test::SetCreditCardInfo(&all_card_data.back(), "John Dillinger",
+ "4234567890123456" /* Visa */, "04", "2001", "1");
+ }
+ all_card_ptrs.push_back(&all_card_data.back());
+ }
+
+ // Verify that only expired disused card are removed. Note that only the last
+ // two cards have use dates more than 175 days ago and are expired.
+ {
+ // Create a working copy of the card pointers.
+ std::vector<CreditCard*> cards(all_card_ptrs);
+
+ // The first 8 are either not expired or having use dates more recent
+ // than 175 days ago.
+ std::vector<CreditCard*> expected_cards(cards.begin(), cards.begin() + 8);
+
+ // Filter the cards while capturing histograms.
+ base::HistogramTester histogram_tester;
+ PersonalDataManager::RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ kNow, kNow - base::TimeDelta::FromDays(175), &cards);
+
+ // Validate that we get the expected filtered cards and histograms.
+ EXPECT_EQ(expected_cards, cards);
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectBucketCount(kHistogramName, 2, 1);
+ }
+
+ // Reverse the card order and verify that only expired and disused cards
+ // are removed. Note that the first three cards, post reversal,
+ // have use dates more then 115 days ago.
+ {
+ // Create a reversed working copy of the card pointers.
+ std::vector<CreditCard*> cards(all_card_ptrs.rbegin(),
+ all_card_ptrs.rend());
+
+ // The last 7 cards have use dates more recent than 115 days ago.
+ std::vector<CreditCard*> expected_cards(cards.begin() + 3, cards.end());
+
+ // Filter the cards while capturing histograms.
+ base::HistogramTester histogram_tester;
+ PersonalDataManager::RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ kNow, kNow - base::TimeDelta::FromDays(115), &cards);
+
+ // Validate that we get the expected filtered cards and histograms.
+ EXPECT_EQ(expected_cards, cards);
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectBucketCount(kHistogramName, 3, 1);
+ }
+ // Randomize the card order and validate that the filtered list retains
+ // that order. Note that the three cards have use dates more then 115
+ // days ago and are expired.
+ {
+ // A handy constant.
+ const base::Time k115DaysAgo = kNow - base::TimeDelta::FromDays(115);
+
+ // Created a shuffled master copy of the card pointers.
+ std::vector<CreditCard*> shuffled_cards(all_card_ptrs);
+ std::random_shuffle(shuffled_cards.begin(), shuffled_cards.end());
+
+ // Copy the shuffled card pointer collections to use as the working
+ // set.
+ std::vector<CreditCard*> cards(shuffled_cards);
+
+ // Filter the cards while capturing histograms.
+ base::HistogramTester histogram_tester;
+ PersonalDataManager::RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ kNow, k115DaysAgo, &cards);
+
+ // Validate that we have the right cards. Iterate of the the shuffled
+ // master copy and the filtered copy at the same time. making sure that
+ // the elements in the filtered copy occur in the same order as the shuffled
+ // master. Along the way, validate that the elements in and out of the
+ // filtered copy have appropriate use dates and expiration states.
+ EXPECT_EQ(7u, cards.size());
+ auto it = shuffled_cards.begin();
+ for (const CreditCard* card : cards) {
+ for (; it != shuffled_cards.end() && (*it) != card; ++it) {
+ EXPECT_LT((*it)->use_date(), k115DaysAgo);
+ ASSERT_TRUE((*it)->IsExpired(kNow));
+ }
+ ASSERT_TRUE(it != shuffled_cards.end());
+ ASSERT_TRUE(card->use_date() > k115DaysAgo || !card->IsExpired(kNow));
+ ++it;
+ }
+ for (; it != shuffled_cards.end(); ++it) {
+ EXPECT_LT((*it)->use_date(), k115DaysAgo);
+ ASSERT_TRUE((*it)->IsExpired(kNow));
+ }
+
+ // Validate the histograms.
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectBucketCount(kHistogramName, 3, 1);
+ }
+
+ // Verify all cards are retained if they're sufficiently recently
+ // used.
+ {
+ // Create a working copy of the card pointers.
+ std::vector<CreditCard*> cards(all_card_ptrs);
+
+ // Filter the cards while capturing histograms.
+ base::HistogramTester histogram_tester;
+ PersonalDataManager::RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ kNow, kNow - base::TimeDelta::FromDays(720), &cards);
+
+ // Validate that we get the expected filtered cards and histograms.
+ EXPECT_EQ(all_card_ptrs, cards);
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectBucketCount(kHistogramName, 0, 1);
+ }
+
+ // Verify all cards are removed if they're all disused and expired.
+ {
+ // Create a working copy of the card pointers.
+ std::vector<CreditCard*> cards(all_card_ptrs);
+ for (auto it = all_card_ptrs.begin(); it < all_card_ptrs.end(); it++) {
+ (*it)->SetExpirationYear(2001);
+ }
+
+ // Filter the cards while capturing histograms.
+ base::HistogramTester histogram_tester;
+ PersonalDataManager::RemoveExpiredCreditCardsNotUsedSinceTimestamp(
+ kNow, kNow + base::TimeDelta::FromDays(1), &cards);
+
+ // Validate that we get the expected filtered cards and histograms.
+ EXPECT_TRUE(cards.empty());
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectBucketCount(kHistogramName, kNumCards, 1);
+ }
+}
+
+TEST_F(PersonalDataManagerTest, CreateDataForTest) {
+ // By default, the creation of test data is disabled.
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+ ASSERT_EQ(0U, personal_data_->GetProfiles().size());
+ ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
+
+ // Turn on test data creation for the rest of this scope.
+ base::test::ScopedFeatureList enabled;
+ enabled.InitAndEnableFeature(kAutofillCreateDataForTest);
+
+ // Reloading the test profile should result in test data being created.
+ ResetPersonalDataManager(USER_MODE_NORMAL);
+ const std::vector<AutofillProfile*> addresses = personal_data_->GetProfiles();
+ const std::vector<CreditCard*> credit_cards =
+ personal_data_->GetCreditCards();
+ ASSERT_EQ(3U, addresses.size());
+ ASSERT_EQ(3U, credit_cards.size());
+
+ const base::Time disused_threshold =
+ AutofillClock::Now() - base::TimeDelta::FromDays(180);
+ const base::Time deletion_threshold =
+ AutofillClock::Now() - base::TimeDelta::FromDays(395);
+
+ // Verify that there was a valid address created.
+ {
+ auto it = std::find_if(
+ addresses.begin(), addresses.end(), [this](const AutofillProfile* p) {
+ return p->GetInfo(NAME_FULL, this->personal_data_->app_locale()) ==
+ base::UTF8ToUTF16("John McTester");
+ });
+ ASSERT_TRUE(it != addresses.end());
+ EXPECT_GT((*it)->use_date(), disused_threshold);
+ }
+
+ // Verify that there was a disused address created.
+ {
+ auto it = std::find_if(
+ addresses.begin(), addresses.end(), [this](const AutofillProfile* p) {
+ return p->GetInfo(NAME_FULL, this->personal_data_->app_locale()) ==
+ base::UTF8ToUTF16("Polly Disused");
+ });
+ ASSERT_TRUE(it != addresses.end());
+ EXPECT_LT((*it)->use_date(), disused_threshold);
+ }
+
+ // Verify that there was a disused deletable address created.
+ {
+ auto it = std::find_if(
+ addresses.begin(), addresses.end(), [this](const AutofillProfile* p) {
+ return p->GetInfo(NAME_FULL, this->personal_data_->app_locale()) ==
+ base::UTF8ToUTF16("Polly Deletable");
+ });
+ ASSERT_TRUE(it != addresses.end());
+ EXPECT_LT((*it)->use_date(), deletion_threshold);
+ EXPECT_FALSE((*it)->IsVerified());
+ }
+
+ // Verify that there was a valid credit card created.
+ {
+ auto it = std::find_if(
+ credit_cards.begin(), credit_cards.end(), [this](const CreditCard* cc) {
+ return cc->GetInfo(CREDIT_CARD_NAME_FULL,
+ this->personal_data_->app_locale()) ==
+ base::UTF8ToUTF16("Alice Testerson");
+ });
+ ASSERT_TRUE(it != credit_cards.end());
+ EXPECT_GT((*it)->use_date(), disused_threshold);
+ }
+
+ // Verify that there was a disused credit card created.
+ {
+ auto it = std::find_if(
+ credit_cards.begin(), credit_cards.end(), [this](const CreditCard* cc) {
+ return cc->GetInfo(CREDIT_CARD_NAME_FULL,
+ this->personal_data_->app_locale()) ==
+ base::UTF8ToUTF16("Bob Disused");
+ });
+ ASSERT_TRUE(it != credit_cards.end());
+ EXPECT_LT((*it)->use_date(), disused_threshold);
+ }
+
+ // Verify that there was a disused deletable credit card created.
+ {
+ auto it = std::find_if(
+ credit_cards.begin(), credit_cards.end(), [this](const CreditCard* cc) {
+ return cc->GetInfo(CREDIT_CARD_NAME_FULL,
+ this->personal_data_->app_locale()) ==
+ base::UTF8ToUTF16("Charlie Deletable");
+ });
+ ASSERT_TRUE(it != credit_cards.end());
+ EXPECT_LT((*it)->use_date(), deletion_threshold);
+ EXPECT_TRUE((*it)->IsExpired(deletion_threshold));
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/phone_email_validation_util.cc b/chromium/components/autofill/core/browser/phone_email_validation_util.cc
index 72d0b2781ac..ab81829b22f 100644
--- a/chromium/components/autofill/core/browser/phone_email_validation_util.cc
+++ b/chromium/components/autofill/core/browser/phone_email_validation_util.cc
@@ -23,10 +23,9 @@ namespace phone_email_validation_util {
AutofillProfile::ValidityState ValidateEmailAddress(
const base::string16& email) {
- if (email.empty()) {
- // Not every profile needs an email address.
- return AutofillProfile::VALID;
- }
+ if (email.empty())
+ return AutofillProfile::EMPTY;
+
return (autofill::IsValidEmailAddress(email) ? AutofillProfile::VALID
: AutofillProfile::INVALID);
}
@@ -34,10 +33,9 @@ AutofillProfile::ValidityState ValidateEmailAddress(
AutofillProfile::ValidityState ValidatePhoneNumber(
const std::string& phone_number,
const std::string& country_code) {
- if (phone_number.empty()) {
- // Every profile needs a phone number.
- return AutofillProfile::INVALID;
- }
+ if (phone_number.empty())
+ return AutofillProfile::EMPTY;
+
if (!base::ContainsValue(CountryDataMap::GetInstance()->country_codes(),
country_code)) {
// If the country code is not in the database, the phone number cannot be
@@ -51,19 +49,22 @@ AutofillProfile::ValidityState ValidatePhoneNumber(
}
AutofillProfile::ValidityState ValidatePhoneAndEmail(AutofillProfile* profile) {
- if (!profile)
- return AutofillProfile::UNVALIDATED;
+ DCHECK(profile);
AutofillProfile::ValidityState phone_validity = ValidatePhoneNumber(
base::UTF16ToUTF8(profile->GetRawInfo(PHONE_HOME_WHOLE_NUMBER)),
base::UTF16ToUTF8(profile->GetRawInfo(ADDRESS_HOME_COUNTRY)));
-
profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, phone_validity);
- profile->SetValidityState(
- EMAIL_ADDRESS, ValidateEmailAddress(profile->GetRawInfo(EMAIL_ADDRESS)));
+ AutofillProfile::ValidityState email_validity =
+ ValidateEmailAddress(profile->GetRawInfo(EMAIL_ADDRESS));
+ profile->SetValidityState(EMAIL_ADDRESS, email_validity);
- return phone_validity; // payment request doesn't care about email1 validity.
+ if (phone_validity == AutofillProfile::VALID &&
+ email_validity == AutofillProfile::VALID) {
+ return AutofillProfile::VALID;
+ }
+ return AutofillProfile::INVALID;
}
} // namespace phone_email_validation_util
diff --git a/chromium/components/autofill/core/browser/phone_email_validation_util_unittest.cc b/chromium/components/autofill/core/browser/phone_email_validation_util_unittest.cc
index 0060acc79c3..9340519eaa0 100644
--- a/chromium/components/autofill/core/browser/phone_email_validation_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/phone_email_validation_util_unittest.cc
@@ -27,10 +27,6 @@ class AutofillPhoneValidationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(AutofillPhoneValidationTest);
};
-TEST_F(AutofillPhoneValidationTest, ValidateNULLProfile) {
- EXPECT_EQ(AutofillProfile::UNVALIDATED, ValidatePhoneAndEmailTest(nullptr));
-}
-
TEST_F(AutofillPhoneValidationTest, ValidateFullValidProfile) {
// This is a full valid profile:
// Country Code: "CA", Phone Number: "15141112233",
@@ -43,12 +39,10 @@ TEST_F(AutofillPhoneValidationTest, ValidateFullValidProfile) {
}
TEST_F(AutofillPhoneValidationTest, ValidateEmptyPhoneNumber) {
- // This is a profile with empty phone number. Since phone number field is
- // always required, it is considered as invalid.
AutofillProfile profile(autofill::test::GetFullValidProfile());
profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16());
EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
- EXPECT_EQ(AutofillProfile::INVALID,
+ EXPECT_EQ(AutofillProfile::EMPTY,
profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(EMAIL_ADDRESS));
}
@@ -59,7 +53,7 @@ TEST_F(AutofillPhoneValidationTest, ValidateValidPhone_CountryCodeNotExist) {
const std::string country_code = "PP";
AutofillProfile profile(autofill::test::GetFullValidProfile());
profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
- EXPECT_EQ(AutofillProfile::UNVALIDATED, ValidatePhoneAndEmailTest(&profile));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
EXPECT_EQ(AutofillProfile::UNVALIDATED,
profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(EMAIL_ADDRESS));
@@ -73,7 +67,7 @@ TEST_F(AutofillPhoneValidationTest, ValidateEmptyPhone_CountryCodeNotExist) {
profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16());
EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
- EXPECT_EQ(AutofillProfile::INVALID,
+ EXPECT_EQ(AutofillProfile::EMPTY,
profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(EMAIL_ADDRESS));
}
@@ -160,33 +154,31 @@ TEST_F(AutofillPhoneValidationTest, ValidateValidPhoneNumber) {
}
TEST_F(AutofillPhoneValidationTest, ValidateEmptyEmailAddress) {
- // This is a profile with empty email address. Since email field is
- // not required, it is considered as valid.
AutofillProfile profile(autofill::test::GetFullValidProfile());
profile.SetRawInfo(EMAIL_ADDRESS, base::string16());
- EXPECT_EQ(AutofillProfile::VALID, ValidatePhoneAndEmailTest(&profile));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
EXPECT_EQ(AutofillProfile::VALID,
profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER));
- EXPECT_EQ(AutofillProfile::VALID, profile.GetValidityState(EMAIL_ADDRESS));
+ EXPECT_EQ(AutofillProfile::EMPTY, profile.GetValidityState(EMAIL_ADDRESS));
}
TEST_F(AutofillPhoneValidationTest, ValidateInvalidEmailAddress) {
AutofillProfile profile(autofill::test::GetFullValidProfile());
profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Hello!"));
- EXPECT_EQ(AutofillProfile::VALID, ValidatePhoneAndEmailTest(&profile));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
EXPECT_EQ(AutofillProfile::INVALID, profile.GetValidityState(EMAIL_ADDRESS));
profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice.wonderland"));
- EXPECT_EQ(AutofillProfile::VALID, ValidatePhoneAndEmailTest(&profile));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
EXPECT_EQ(AutofillProfile::INVALID, profile.GetValidityState(EMAIL_ADDRESS));
profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@"));
- EXPECT_EQ(AutofillProfile::VALID, ValidatePhoneAndEmailTest(&profile));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
EXPECT_EQ(AutofillProfile::INVALID, profile.GetValidityState(EMAIL_ADDRESS));
profile.SetRawInfo(EMAIL_ADDRESS,
base::ASCIIToUTF16("alice@=wonderland.com"));
- EXPECT_EQ(AutofillProfile::VALID, ValidatePhoneAndEmailTest(&profile));
+ EXPECT_EQ(AutofillProfile::INVALID, ValidatePhoneAndEmailTest(&profile));
EXPECT_EQ(AutofillProfile::INVALID, profile.GetValidityState(EMAIL_ADDRESS));
}
diff --git a/chromium/components/autofill/core/browser/phone_number_i18n.cc b/chromium/components/autofill/core/browser/phone_number_i18n.cc
index 66fe9faac56..63954a0235a 100644
--- a/chromium/components/autofill/core/browser/phone_number_i18n.cc
+++ b/chromium/components/autofill/core/browser/phone_number_i18n.cc
@@ -11,15 +11,34 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/validation.h"
#include "third_party/libphonenumber/phonenumber_api.h"
-using i18n::phonenumbers::PhoneNumber;
-using i18n::phonenumbers::PhoneNumberUtil;
-
namespace autofill {
namespace {
+using ::i18n::phonenumbers::PhoneNumberUtil;
+
+// Formats the |phone_number| to the specified |format|. Returns the original
+// number if the operation is not possible.
+std::string FormatPhoneNumber(const std::string& phone_number,
+ const std::string& country_code,
+ PhoneNumberUtil::PhoneNumberFormat format) {
+ ::i18n::phonenumbers::PhoneNumber parsed_number;
+ PhoneNumberUtil* phone_number_util = PhoneNumberUtil::GetInstance();
+ if (phone_number_util->Parse(phone_number, country_code, &parsed_number) !=
+ PhoneNumberUtil::NO_PARSING_ERROR) {
+ return phone_number;
+ }
+
+ std::string formatted_number;
+ phone_number_util->Format(parsed_number, format, &formatted_number);
+ return formatted_number;
+}
+
std::string SanitizeRegion(const std::string& region,
const std::string& app_locale) {
if (region.length() == 2)
@@ -29,7 +48,7 @@ std::string SanitizeRegion(const std::string& region,
}
// Returns true if |phone_number| is valid.
-bool IsValidPhoneNumber(const PhoneNumber& phone_number) {
+bool IsValidPhoneNumber(const ::i18n::phonenumbers::PhoneNumber& phone_number) {
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
if (!phone_util->IsPossibleNumber(phone_number))
return false;
@@ -52,7 +71,7 @@ bool IsValidPhoneNumber(const PhoneNumber& phone_number) {
// whether to format in the national or in the international format, is passed
// in explicitly, as |number| might have an implicit country code set, even
// though the original input lacked a country code.
-void FormatValidatedNumber(const PhoneNumber& number,
+void FormatValidatedNumber(const ::i18n::phonenumbers::PhoneNumber& number,
const base::string16& country_code,
base::string16* formatted_number,
base::string16* normalized_number) {
@@ -101,11 +120,11 @@ bool ParsePhoneNumber(const base::string16& value,
base::string16* city_code,
base::string16* number,
std::string* inferred_region,
- PhoneNumber* i18n_number) {
+ ::i18n::phonenumbers::PhoneNumber* i18n_number) {
country_code->clear();
city_code->clear();
number->clear();
- *i18n_number = PhoneNumber();
+ *i18n_number = ::i18n::phonenumbers::PhoneNumber();
std::string number_text(base::UTF16ToUTF8(value));
@@ -150,7 +169,8 @@ bool ParsePhoneNumber(const base::string16& value,
// Check if parsed number has a country code that was not inferred from the
// region.
if (i18n_number->has_country_code() &&
- i18n_number->country_code_source() != PhoneNumber::FROM_DEFAULT_COUNTRY) {
+ i18n_number->country_code_source() !=
+ ::i18n::phonenumbers::PhoneNumber::FROM_DEFAULT_COUNTRY) {
*country_code = base::UTF8ToUTF16(
base::IntToString(i18n_number->country_code()));
}
@@ -166,7 +186,7 @@ base::string16 NormalizePhoneNumber(const base::string16& value,
DCHECK_EQ(2u, region.size());
base::string16 country_code, unused_city_code, unused_number;
std::string unused_region;
- PhoneNumber phone_number;
+ ::i18n::phonenumbers::PhoneNumber phone_number;
if (!ParsePhoneNumber(value, region, &country_code, &unused_city_code,
&unused_number, &unused_region, &phone_number)) {
return base::string16(); // Parsing failed - do not store phone.
@@ -187,7 +207,7 @@ bool ConstructPhoneNumber(const base::string16& country_code,
base::string16 unused_country_code, unused_city_code, unused_number;
std::string unused_region;
- PhoneNumber phone_number;
+ ::i18n::phonenumbers::PhoneNumber phone_number;
if (!ParsePhoneNumber(country_code + city_code + number, region,
&unused_country_code, &unused_city_code, &unused_number,
&unused_region, &phone_number)) {
@@ -208,14 +228,14 @@ bool PhoneNumbersMatch(const base::string16& number_a,
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
// Parse phone numbers based on the region
- PhoneNumber i18n_number1;
+ ::i18n::phonenumbers::PhoneNumber i18n_number1;
if (phone_util->Parse(
base::UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) !=
PhoneNumberUtil::NO_PARSING_ERROR) {
return false;
}
- PhoneNumber i18n_number2;
+ ::i18n::phonenumbers::PhoneNumber i18n_number2;
if (phone_util->Parse(
base::UTF16ToUTF8(number_b), region.c_str(), &i18n_number2) !=
PhoneNumberUtil::NO_PARSING_ERROR) {
@@ -237,6 +257,45 @@ bool PhoneNumbersMatch(const base::string16& number_a,
return false;
}
+base::string16 GetFormattedPhoneNumberForDisplay(const AutofillProfile& profile,
+ const std::string& locale) {
+ // Since the "+" is removed for some country's phone numbers, try to add a "+"
+ // and see if it is a valid phone number for a country.
+ // Having two "+" in front of a number has no effect on the formatted number.
+ // The reason for this is international phone numbers for another country. For
+ // example, without adding a "+", the US number 1-415-123-1234 for an AU
+ // address would be wrongly formatted as +61 1-415-123-1234 which is invalid.
+ std::string phone = base::UTF16ToUTF8(
+ profile.GetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), locale));
+ std::string tentative_intl_phone = "+" + phone;
+
+ // Always favor the tentative international phone number if it's determined as
+ // being a valid number.
+ if (IsValidPhoneNumber(
+ base::UTF8ToUTF16(tentative_intl_phone),
+ autofill::data_util::GetCountryCodeWithFallback(&profile, locale))) {
+ return base::UTF8ToUTF16(FormatPhoneForDisplay(
+ tentative_intl_phone,
+ autofill::data_util::GetCountryCodeWithFallback(&profile, locale)));
+ }
+
+ return base::UTF8ToUTF16(FormatPhoneForDisplay(
+ phone,
+ autofill::data_util::GetCountryCodeWithFallback(&profile, locale)));
+}
+
+std::string FormatPhoneForDisplay(const std::string& phone_number,
+ const std::string& country_code) {
+ return FormatPhoneNumber(phone_number, country_code,
+ PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL);
+}
+
+std::string FormatPhoneForResponse(const std::string& phone_number,
+ const std::string& country_code) {
+ return FormatPhoneNumber(phone_number, country_code,
+ PhoneNumberUtil::PhoneNumberFormat::E164);
+}
+
PhoneObject::PhoneObject(const base::string16& number,
const std::string& region) {
DCHECK_EQ(2u, region.size());
@@ -246,7 +305,8 @@ PhoneObject::PhoneObject(const base::string16& number,
// [ http://crbug.com/100845 ]. Once the bug is fixed, add a DCHECK here to
// verify.
- std::unique_ptr<PhoneNumber> i18n_number(new PhoneNumber);
+ std::unique_ptr<::i18n::phonenumbers::PhoneNumber> i18n_number(
+ new ::i18n::phonenumbers::PhoneNumber);
if (ParsePhoneNumber(number, region, &country_code_, &city_code_, &number_,
&region_, i18n_number.get())) {
// The phone number was successfully parsed, so store the parsed version.
@@ -298,7 +358,8 @@ PhoneObject& PhoneObject::operator=(const PhoneObject& other) {
region_ = other.region_;
if (other.i18n_number_.get())
- i18n_number_.reset(new PhoneNumber(*other.i18n_number_));
+ i18n_number_.reset(
+ new ::i18n::phonenumbers::PhoneNumber(*other.i18n_number_));
else
i18n_number_.reset();
diff --git a/chromium/components/autofill/core/browser/phone_number_i18n.h b/chromium/components/autofill/core/browser/phone_number_i18n.h
index 26e2a1b7f13..5baa44ac031 100644
--- a/chromium/components/autofill/core/browser/phone_number_i18n.h
+++ b/chromium/components/autofill/core/browser/phone_number_i18n.h
@@ -20,6 +20,8 @@ class PhoneNumber;
namespace autofill {
+class AutofillProfile;
+
// Utilities to process, normalize and compare international phone numbers.
namespace i18n {
@@ -68,6 +70,24 @@ bool PhoneNumbersMatch(const base::string16& number_a,
const std::string& region,
const std::string& app_locale);
+// Returns the phone number from the given |profile| formatted for display.
+base::string16 GetFormattedPhoneNumberForDisplay(const AutofillProfile& profile,
+ const std::string& locale);
+
+// Formats the given number |phone_number| to
+// i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::INTERNATIONAL format
+// by using i18n::phonenumbers::PhoneNumberUtil::Format.
+std::string FormatPhoneForDisplay(const std::string& phone_number,
+ const std::string& country_code);
+
+// Formats the given number |phone_number| to
+// i18n::phonenumbers::PhoneNumberUtil::PhoneNumberFormat::E164 format by using
+// i18n::phonenumbers::PhoneNumberUtil::Format, as defined in the Payment
+// Request spec
+// (https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm)
+std::string FormatPhoneForResponse(const std::string& phone_number,
+ const std::string& country_code);
+
// The cached phone number, does parsing only once, improves performance.
class PhoneObject {
public:
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 17a24311876..ac791074aca 100644
--- a/chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc
+++ b/chromium/components/autofill/core/browser/phone_number_i18n_unittest.cc
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/autofill/core/browser/phone_number_i18n.h"
+
#include <stddef.h>
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/phone_number_i18n.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/field_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libphonenumber/phonenumber_api.h"
@@ -272,4 +274,189 @@ TEST(PhoneNumberI18NTest, PhoneNumbersMatch) {
"en-US"));
}
+// Tests that the phone numbers are correctly formatted for the Payment
+// Response.
+TEST(PhoneNumberUtilTest, FormatPhoneForResponse) {
+ EXPECT_EQ("+15151231234",
+ i18n::FormatPhoneForResponse("(515) 123-1234", "US"));
+ EXPECT_EQ("+15151231234",
+ i18n::FormatPhoneForResponse("(1) 515-123-1234", "US"));
+ EXPECT_EQ("+33142685300",
+ i18n::FormatPhoneForResponse("1 42 68 53 00", "FR"));
+}
+
+// Tests that the phone numbers are correctly formatted to display to the user.
+TEST(PhoneNumberUtilTest, FormatPhoneForDisplay) {
+ EXPECT_EQ("+1 515-123-1234", i18n::FormatPhoneForDisplay("5151231234", "US"));
+ EXPECT_EQ("+33 1 42 68 53 00",
+ i18n::FormatPhoneForDisplay("142685300", "FR"));
+}
+
+// Test for the GetFormattedPhoneNumberForDisplay method.
+struct PhoneNumberFormatCase {
+ PhoneNumberFormatCase(const char* phone,
+ const char* country,
+ const char* expected_format,
+ const char* locale = "")
+ : phone(phone),
+ country(country),
+ expected_format(expected_format),
+ locale(locale) {}
+
+ const char* phone;
+ const char* country;
+ const char* expected_format;
+ const char* locale;
+};
+
+class GetFormattedPhoneNumberForDisplayTest
+ : public testing::TestWithParam<PhoneNumberFormatCase> {};
+
+TEST_P(GetFormattedPhoneNumberForDisplayTest,
+ GetFormattedPhoneNumberForDisplay) {
+ AutofillProfile profile;
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
+ base::UTF8ToUTF16(GetParam().phone));
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY,
+ base::UTF8ToUTF16(GetParam().country));
+ EXPECT_EQ(GetParam().expected_format,
+ base::UTF16ToUTF8(i18n::GetFormattedPhoneNumberForDisplay(
+ profile, GetParam().locale)));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ GetFormattedPhoneNumberForDisplay,
+ GetFormattedPhoneNumberForDisplayTest,
+ testing::Values(
+ //////////////////////////
+ // US phone in US.
+ //////////////////////////
+ // Formatted phone numbers.
+ PhoneNumberFormatCase("+1 415-555-5555", "US", "+1 415-555-5555"),
+ PhoneNumberFormatCase("1 415-555-5555", "US", "+1 415-555-5555"),
+ PhoneNumberFormatCase("415-555-5555", "US", "+1 415-555-5555"),
+ // Raw phone numbers.
+ PhoneNumberFormatCase("+14155555555", "US", "+1 415-555-5555"),
+ PhoneNumberFormatCase("14155555555", "US", "+1 415-555-5555"),
+ PhoneNumberFormatCase("4155555555", "US", "+1 415-555-5555"),
+
+ //////////////////////////
+ // US phone in CA.
+ //////////////////////////
+ // Formatted phone numbers.
+ PhoneNumberFormatCase("+1 415-555-5555", "CA", "+1 415-555-5555"),
+ PhoneNumberFormatCase("1 415-555-5555", "CA", "+1 415-555-5555"),
+ PhoneNumberFormatCase("415-555-5555", "CA", "+1 415-555-5555"),
+ // Raw phone numbers.
+ PhoneNumberFormatCase("+14155555555", "CA", "+1 415-555-5555"),
+ PhoneNumberFormatCase("14155555555", "CA", "+1 415-555-5555"),
+ PhoneNumberFormatCase("4155555555", "CA", "+1 415-555-5555"),
+
+ //////////////////////////
+ // US phone in AU.
+ //////////////////////////
+ // A US phone with the country code is correctly formatted as an US
+ // number.
+ PhoneNumberFormatCase("+1 415-555-5555", "AU", "+1 415-555-5555"),
+ PhoneNumberFormatCase("1 415-555-5555", "AU", "+1 415-555-5555"),
+ // Without a country code, the phone is formatted for the profile's
+ // country, even if it's invalid.
+ PhoneNumberFormatCase("415-555-5555", "AU", "+61 4155555555"),
+
+ //////////////////////////
+ // US phone in MX.
+ //////////////////////////
+ // A US phone with the country code is correctly formatted as an US
+ // number.
+ PhoneNumberFormatCase("+1 415-555-5555", "MX", "+1 415-555-5555"),
+ // "+52 1 415 555 5555" is a valid number for Mexico,
+ PhoneNumberFormatCase("1 415-555-5555", "MX", "+52 1 415 555 5555"),
+ // Without a country code, the phone is formatted for the profile's
+ // country.
+ PhoneNumberFormatCase("415-555-5555", "MX", "+52 415 555 5555"),
+
+ //////////////////////////
+ // AU phone in AU.
+ //////////////////////////
+ // Formatted phone numbers.
+ PhoneNumberFormatCase("+61 2 9374 4000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("61 2 9374 4000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("02 9374 4000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("2 9374 4000", "AU", "+61 2 9374 4000"),
+ // Raw phone numbers.
+ PhoneNumberFormatCase("+61293744000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("61293744000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("0293744000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("293744000", "AU", "+61 2 9374 4000"),
+
+ //////////////////////////
+ // AU phone in US.
+ //////////////////////////
+ // An AU phone with the country code is correctly formatted as an AU
+ // number.
+ PhoneNumberFormatCase("+61 2 9374 4000", "US", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("61 2 9374 4000", "US", "+61 2 9374 4000"),
+ // Without a country code, the phone is formatted for the profile's
+ // country.
+ // This local AU number fits the length of a US number, so it's
+ // formatted for US.
+ PhoneNumberFormatCase("02 9374 4000", "US", "+1 029-374-4000"),
+ // This local AU number is formatted as an US number, even if it's
+ // invlaid.
+ PhoneNumberFormatCase("2 9374 4000", "US", "+1 293744000"),
+
+ //////////////////////////
+ // MX phone in MX.
+ //////////////////////////
+ // Formatted phone numbers.
+ PhoneNumberFormatCase("+52 55 5342 8400", "MX", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("52 55 5342 8400", "MX", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("55 5342 8400", "MX", "+52 55 5342 8400"),
+ // Raw phone numbers.
+ PhoneNumberFormatCase("+525553428400", "MX", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("525553428400", "MX", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("5553428400", "MX", "+52 55 5342 8400"),
+
+ //////////////////////////
+ // MX phone in US.
+ //////////////////////////
+ // A MX phone with the country code is correctly formatted as a MX
+ // number.
+ PhoneNumberFormatCase("+52 55 5342 8400", "US", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("52 55 5342 8400", "US", "+52 55 5342 8400"),
+ // This local MX number fits the length of a US number, so it's
+ // formatted for US.
+ PhoneNumberFormatCase("55 5342 8400", "US", "+1 555-342-8400")));
+
+INSTANTIATE_TEST_CASE_P(
+ GetFormattedPhoneNumberForDisplay_EdgeCases,
+ GetFormattedPhoneNumberForDisplayTest,
+ testing::Values(
+ //////////////////////////
+ // No country.
+ //////////////////////////
+ // Fallback to locale if no country is set.
+ PhoneNumberFormatCase("52 55 5342 8400",
+ "",
+ "+52 55 5342 8400",
+ "es_MX"),
+ PhoneNumberFormatCase("55 5342 8400", "", "+52 55 5342 8400", "es_MX"),
+ PhoneNumberFormatCase("55 5342 8400", "", "+1 555-342-8400", "en_US"),
+ PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000", "en_AU"),
+ PhoneNumberFormatCase("02 9374 4000", "", "+61 2 9374 4000", "en_AU"),
+
+ //////////////////////////
+ // No country or locale.
+ //////////////////////////
+ // Format according to the country code.
+ PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000"),
+ PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("1 415 555 5555", "", "+1 415-555-5555"),
+ // If no country code is found, formats for US.
+ PhoneNumberFormatCase("02 9374 4000", "", "+1 029-374-4000"),
+ PhoneNumberFormatCase("2 9374 4000", "", "+1 293744000"),
+ PhoneNumberFormatCase("55 5342 8400", "", "+1 555-342-8400"),
+ PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
+ PhoneNumberFormatCase("415-555-5555", "", "+1 415-555-5555")));
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/popup_item_ids.h b/chromium/components/autofill/core/browser/popup_item_ids.h
index 4859fa266a8..4b79d2cffab 100644
--- a/chromium/components/autofill/core/browser/popup_item_ids.h
+++ b/chromium/components/autofill/core/browser/popup_item_ids.h
@@ -24,6 +24,7 @@ enum PopupItemId {
POPUP_ITEM_ID_USERNAME_ENTRY = -11,
POPUP_ITEM_ID_CREATE_HINT = -12,
POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY = -13,
+ POPUP_ITEM_ID_GENERATE_PASSWORD_ENTRY = -14,
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/proto/server.proto b/chromium/components/autofill/core/browser/proto/server.proto
index ad92f3768df..8156146c450 100644
--- a/chromium/components/autofill/core/browser/proto/server.proto
+++ b/chromium/components/autofill/core/browser/proto/server.proto
@@ -25,10 +25,16 @@ message AutofillQueryContents {
// This message is the result of an Autofill query. It holds the field type
// information.
-// Next available id: 7
+// Next available id: 8
message AutofillQueryResponseContents {
optional bool upload_required = 1;
- repeated group Field = 2 { required fixed32 autofill_type = 3; }
+ repeated group Field = 2 {
+ required fixed32 overall_type_prediction = 3;
+ // Detailed list of all possible predictions (including
+ // |overall_type_prediction| as the first item).
+ message FieldPrediction { optional fixed32 type = 1; }
+ repeated FieldPrediction predictions = 7;
+ }
}
// This message contains information about the field types in a single form.
diff --git a/chromium/components/autofill/core/browser/region_data_loader_impl.h b/chromium/components/autofill/core/browser/region_data_loader_impl.h
index 8113473e2db..b7a780d4bdb 100644
--- a/chromium/components/autofill/core/browser/region_data_loader_impl.h
+++ b/chromium/components/autofill/core/browser/region_data_loader_impl.h
@@ -7,15 +7,14 @@
#include "components/autofill/core/browser/region_data_loader.h"
+#include <memory>
#include <string>
#include "base/timer/timer.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/util/scoped_ptr.h"
namespace i18n {
namespace addressinput {
-class PreloadSupplier;
class Source;
class Storage;
} // namespace addressinput
@@ -51,8 +50,7 @@ class RegionDataLoaderImpl : public RegionDataLoader {
void DeleteThis();
// The callback to give to |region_data_supplier_| for async operations.
- ::i18n::addressinput::scoped_ptr<
- ::i18n::addressinput::PreloadSupplier::Callback>
+ std::unique_ptr<::i18n::addressinput::PreloadSupplier::Callback>
region_data_supplier_callback_;
// A supplier of region data.
diff --git a/chromium/components/autofill/core/browser/subkey_requester.cc b/chromium/components/autofill/core/browser/subkey_requester.cc
new file mode 100644
index 00000000000..ff90378903d
--- /dev/null
+++ b/chromium/components/autofill/core/browser/subkey_requester.cc
@@ -0,0 +1,143 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/subkey_requester.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/cancelable_callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+
+namespace autofill {
+
+namespace {
+
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+
+class SubKeyRequest : public SubKeyRequester::Request {
+ public:
+ // The |delegate| and |address_validator| need to outlive this Request.
+ SubKeyRequest(const std::string& region_code,
+ const std::string& language,
+ int timeout_seconds,
+ AddressValidator* address_validator,
+ SubKeyReceiverCallback on_subkeys_received)
+ : region_code_(region_code),
+ language_(language),
+ address_validator_(address_validator),
+ on_subkeys_received_(std::move(on_subkeys_received)),
+ has_responded_(false),
+ on_timeout_(
+ base::Bind(&SubKeyRequest::OnRulesLoaded, base::Unretained(this))) {
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, on_timeout_.callback(),
+ base::TimeDelta::FromSeconds(timeout_seconds));
+ }
+
+ ~SubKeyRequest() override { on_timeout_.Cancel(); }
+
+ void OnRulesLoaded() override {
+ on_timeout_.Cancel();
+ // Check if the timeout happened before the rules were loaded.
+ if (has_responded_)
+ return;
+ has_responded_ = true;
+
+ auto subkeys =
+ address_validator_->GetRegionSubKeys(region_code_, language_);
+ std::vector<std::string> subkeys_codes;
+ std::vector<std::string> subkeys_names;
+ for (auto s : subkeys) {
+ subkeys_codes.push_back(s.first);
+ subkeys_names.push_back(s.second);
+ }
+ std::move(on_subkeys_received_).Run(subkeys_codes, subkeys_names);
+ }
+
+ private:
+ std::string region_code_;
+ std::string language_;
+ // Not owned. Never null. Outlive this object.
+ AddressValidator* address_validator_;
+
+ SubKeyReceiverCallback on_subkeys_received_;
+
+ bool has_responded_;
+ base::CancelableCallback<void()> on_timeout_;
+
+ DISALLOW_COPY_AND_ASSIGN(SubKeyRequest);
+};
+
+} // namespace
+
+SubKeyRequester::SubKeyRequester(std::unique_ptr<Source> source,
+ std::unique_ptr<Storage> storage)
+ : address_validator_(std::move(source), std::move(storage), this) {}
+
+SubKeyRequester::~SubKeyRequester() {}
+
+void SubKeyRequester::StartRegionSubKeysRequest(const std::string& region_code,
+ const std::string& language,
+ int timeout_seconds,
+ SubKeyReceiverCallback cb) {
+ DCHECK(timeout_seconds >= 0);
+
+ std::unique_ptr<SubKeyRequest> request(
+ base::MakeUnique<SubKeyRequest>(region_code, language, timeout_seconds,
+ &address_validator_, std::move(cb)));
+
+ if (AreRulesLoadedForRegion(region_code)) {
+ request->OnRulesLoaded();
+ } else {
+ // Setup the variables so that the subkeys request is sent, when the rules
+ // are loaded.
+ pending_subkey_region_code_ = region_code;
+ pending_subkey_request_ = std::move(request);
+
+ // Start loading the rules for that region. If the rules were already in the
+ // process of being loaded, this call will do nothing.
+ LoadRulesForRegion(region_code);
+ }
+}
+
+bool SubKeyRequester::AreRulesLoadedForRegion(const std::string& region_code) {
+ return address_validator_.AreRulesLoadedForRegion(region_code);
+}
+
+void SubKeyRequester::LoadRulesForRegion(const std::string& region_code) {
+ address_validator_.LoadRules(region_code);
+}
+
+void SubKeyRequester::OnAddressValidationRulesLoaded(
+ const std::string& region_code,
+ bool success) {
+ // The case for |success| == false is already handled. if |success| == false,
+ // AddressValidator::GetRegionSubKeys will return an empty list of subkeys.
+ // Therefore, here, we can ignore the value of |success|.
+ // Check if there is any subkey request for that region code.
+ if (pending_subkey_request_ &&
+ !pending_subkey_region_code_.compare(region_code)) {
+ pending_subkey_request_->OnRulesLoaded();
+ }
+ pending_subkey_region_code_.clear();
+ pending_subkey_request_.reset();
+}
+
+void SubKeyRequester::CancelPendingGetSubKeys() {
+ pending_subkey_region_code_.clear();
+ pending_subkey_request_.reset();
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/subkey_requester.h b/chromium/components/autofill/core/browser/subkey_requester.h
new file mode 100644
index 00000000000..164857c3134
--- /dev/null
+++ b/chromium/components/autofill/core/browser/subkey_requester.h
@@ -0,0 +1,76 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_SUBKEY_REQUESTER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_SUBKEY_REQUESTER_H_
+
+#include "base/macros.h"
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+
+namespace autofill {
+
+// This receives a region code and the device's language.
+using SubKeyReceiverCallback =
+ base::OnceCallback<void(const std::vector<std::string>&,
+ const std::vector<std::string>&)>;
+
+// SubKeyRequester Loads Rules from the server and extracts the subkeys.
+// For a given key (region code for a country, such as US), the list of its
+// corresponding subkeys is the list of that countries admin areas (states,
+// provinces, ..).
+class SubKeyRequester : public LoadRulesListener {
+ public:
+ // The interface for the subkey request.
+ class Request {
+ public:
+ virtual void OnRulesLoaded() = 0;
+ virtual ~Request() {}
+ };
+
+ SubKeyRequester(std::unique_ptr<::i18n::addressinput::Source> source,
+ std::unique_ptr<::i18n::addressinput::Storage> storage);
+ ~SubKeyRequester() override;
+
+ // If the rules for |region_code| are loaded, this gets the subkeys for the
+ // |region_code|, synchronously. If they are not loaded yet, it sets up a
+ // task to get the subkeys when the rules are loaded (asynchronous). If the
+ // loading has not yet started, it will also start loading the rules for the
+ // |region_code|. The received subkeys will be returned to the |requester|. If
+ // the subkeys are not received in |timeout_seconds|, then the requester will
+ // be informed and the request will be canceled. |requester| should never be
+ // null. The requesting device language is set to |language|, ex:"fr".
+ void StartRegionSubKeysRequest(const std::string& region_code,
+ const std::string& language,
+ int timeout_seconds,
+ SubKeyReceiverCallback cb);
+
+ // Returns whether the rules for the specified |region_code| have finished
+ // loading.
+ bool AreRulesLoadedForRegion(const std::string& region_code);
+
+ // Start loading the rules for the specified |region_code|.
+ virtual void LoadRulesForRegion(const std::string& region_code);
+
+ // Cancels the pending subkey request task.
+ void CancelPendingGetSubKeys();
+
+ private:
+ // Called when the address rules for the |region_code| have finished
+ // loading. Implementation of the LoadRulesListener interface.
+ void OnAddressValidationRulesLoaded(const std::string& region_code,
+ bool success) override;
+
+ // The region code and the request for the pending subkey request.
+ std::unique_ptr<Request> pending_subkey_request_;
+ std::string pending_subkey_region_code_;
+
+ // The address validator used to load subkeys.
+ AddressValidator address_validator_;
+
+ DISALLOW_COPY_AND_ASSIGN(SubKeyRequester);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_SUBKEY_REQUESTER_H_
diff --git a/chromium/components/autofill/core/browser/subkey_requester_unittest.cc b/chromium/components/autofill/core/browser/subkey_requester_unittest.cc
new file mode 100644
index 00000000000..eafb829dc25
--- /dev/null
+++ b/chromium/components/autofill/core/browser/subkey_requester_unittest.cc
@@ -0,0 +1,202 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/subkey_requester.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+#include "third_party/libaddressinput/src/cpp/test/testdata_source.h"
+
+namespace autofill {
+
+namespace {
+
+using ::i18n::addressinput::NullStorage;
+using ::i18n::addressinput::Source;
+using ::i18n::addressinput::Storage;
+using ::i18n::addressinput::TestdataSource;
+
+const char kLocale[] = "OZ";
+const char kLanguage[] = "en";
+const int kInvalidSize = -1;
+const int kCorrectSize = 2; // for subkeys = Do, Re
+const int kEmptySize = 0;
+
+class SubKeyReceiver : public base::RefCountedThreadSafe<SubKeyReceiver> {
+ public:
+ SubKeyReceiver() : subkeys_size_(kInvalidSize) {}
+
+ void OnSubKeysReceived(const std::vector<std::string>& subkeys_codes,
+ const std::vector<std::string>& subkeys_names) {
+ subkeys_size_ = subkeys_codes.size();
+ }
+
+ int subkeys_size() const { return subkeys_size_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<SubKeyReceiver>;
+ ~SubKeyReceiver() {}
+
+ int subkeys_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(SubKeyReceiver);
+};
+
+// Used to load region rules for this test.
+class ChromiumTestdataSource : public TestdataSource {
+ public:
+ ChromiumTestdataSource() : TestdataSource(true) {}
+
+ ~ChromiumTestdataSource() override {}
+
+ // For this test, only load the rules for the kLocale.
+ void Get(const std::string& key, const Callback& data_ready) const override {
+ data_ready(
+ true, key,
+ new std::string(
+ "{\"data/OZ\": "
+ "{\"id\":\"data/OZ\",\"key\":\"OZ\",\"name\":\"Oz \", "
+ "\"lang\":\"en\",\"sub_keys\":\"DO~RE\", \"sub_names\":\"Do~Re\"},"
+ "\"data/OZ/DO\": "
+ "{\"id\":\"data/OZ/DO\",\"key\":\"DO\",\"name\":\"Do \", "
+ "\"lang\":\"en\"},"
+ "\"data/OZ/RE\": "
+ "{\"id\":\"data/OZ/RE\",\"key\":\"RE\",\"name\":\"Re \", "
+ "\"lang\":\"en\"}}"));
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromiumTestdataSource);
+};
+
+// A test subclass of the SubKeyRequesterImpl. Used to simulate rules not
+// being loaded.
+class TestSubKeyRequester : public SubKeyRequester {
+ public:
+ TestSubKeyRequester(std::unique_ptr<::i18n::addressinput::Source> source,
+ std::unique_ptr<::i18n::addressinput::Storage> storage)
+ : SubKeyRequester(std::move(source), std::move(storage)),
+ should_load_rules_(true) {}
+
+ ~TestSubKeyRequester() override {}
+
+ void ShouldLoadRules(bool should_load_rules) {
+ should_load_rules_ = should_load_rules;
+ }
+
+ void LoadRulesForRegion(const std::string& region_code) override {
+ if (should_load_rules_) {
+ SubKeyRequester::LoadRulesForRegion(region_code);
+ }
+ }
+
+ private:
+ bool should_load_rules_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSubKeyRequester);
+};
+
+} // namespace
+
+class SubKeyRequesterTest : public testing::Test {
+ protected:
+ SubKeyRequesterTest()
+ : requester_(new TestSubKeyRequester(
+ std::unique_ptr<Source>(new ChromiumTestdataSource),
+ std::unique_ptr<Storage>(new NullStorage))) {}
+
+ ~SubKeyRequesterTest() override {}
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ const std::unique_ptr<TestSubKeyRequester> requester_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SubKeyRequesterTest);
+};
+
+// Tests that rules are not loaded by default.
+TEST_F(SubKeyRequesterTest, AreRulesLoadedForRegion_NotLoaded) {
+ EXPECT_FALSE(requester_->AreRulesLoadedForRegion(kLocale));
+}
+
+// Tests that the rules are loaded correctly.
+TEST_F(SubKeyRequesterTest, AreRulesLoadedForRegion_Loaded) {
+ requester_->LoadRulesForRegion(kLocale);
+ EXPECT_TRUE(requester_->AreRulesLoadedForRegion(kLocale));
+}
+
+// Tests that if the rules are loaded before the subkey request is started, the
+// received subkeys will be returned to the delegate synchronously.
+TEST_F(SubKeyRequesterTest, StartRequest_RulesLoaded) {
+ scoped_refptr<SubKeyReceiver> subkey_receiver_ = new SubKeyReceiver();
+
+ SubKeyReceiverCallback cb =
+ base::BindOnce(&SubKeyReceiver::OnSubKeysReceived, subkey_receiver_);
+
+ // Load the rules.
+ requester_->LoadRulesForRegion(kLocale);
+ EXPECT_TRUE(requester_->AreRulesLoadedForRegion(kLocale));
+
+ // Start the request.
+ requester_->StartRegionSubKeysRequest(kLocale, kLanguage, 0, std::move(cb));
+
+ // Since the rules are already loaded, the subkeys should be received
+ // synchronously.
+ EXPECT_EQ(subkey_receiver_->subkeys_size(), kCorrectSize);
+}
+
+// Tests that if the rules are not loaded before the request and cannot be
+// loaded after, the subkeys will not be received and the delegate will be
+// notified.
+TEST_F(SubKeyRequesterTest, StartRequest_RulesNotLoaded_WillNotLoad) {
+ scoped_refptr<SubKeyReceiver> subkey_receiver_ = new SubKeyReceiver();
+
+ SubKeyReceiverCallback cb =
+ base::BindOnce(&SubKeyReceiver::OnSubKeysReceived, subkey_receiver_);
+
+ // Make sure the rules will not be loaded in the StartRegionSubKeysRequest
+ // call.
+ requester_->ShouldLoadRules(false);
+
+ // Start the normalization.
+ requester_->StartRegionSubKeysRequest(kLocale, kLanguage, 0, std::move(cb));
+
+ // Let the timeout execute.
+ scoped_task_environment_.RunUntilIdle();
+
+ // Since the rules are never loaded and the timeout is 0, the delegate should
+ // get notified that the subkeys could not be received.
+ EXPECT_EQ(subkey_receiver_->subkeys_size(), kEmptySize);
+}
+
+// Tests that if the rules are not loaded before the call to
+// StartRegionSubKeysRequest, they will be loaded in the call.
+TEST_F(SubKeyRequesterTest, StartRequest_RulesNotLoaded_WillLoad) {
+ scoped_refptr<SubKeyReceiver> subkey_receiver_ = new SubKeyReceiver();
+
+ SubKeyReceiverCallback cb =
+ base::BindOnce(&SubKeyReceiver::OnSubKeysReceived, subkey_receiver_);
+
+ // Make sure the rules will not be loaded in the StartRegionSubKeysRequest
+ // call.
+ requester_->ShouldLoadRules(true);
+ // Start the request.
+ requester_->StartRegionSubKeysRequest(kLocale, kLanguage, 0, std::move(cb));
+
+ // Even if the rules are not loaded before the call to
+ // StartRegionSubKeysRequest, they should get loaded in the call. Since our
+ // test source is synchronous, the request will happen synchronously
+ // too.
+ EXPECT_TRUE(requester_->AreRulesLoadedForRegion(kLocale));
+ EXPECT_EQ(subkey_receiver_->subkeys_size(), kCorrectSize);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_address_normalizer.cc b/chromium/components/autofill/core/browser/test_address_normalizer.cc
new file mode 100644
index 00000000000..1ec6324e028
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_address_normalizer.cc
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/test_address_normalizer.h"
+
+namespace autofill {
+
+bool TestAddressNormalizer::AreRulesLoadedForRegion(
+ const std::string& region_code) {
+ return true;
+}
+
+void TestAddressNormalizer::StartAddressNormalization(
+ const AutofillProfile& profile,
+ const std::string& region_code,
+ int timeout_seconds,
+ AddressNormalizer::Delegate* requester) {
+ if (instantaneous_normalization_) {
+ requester->OnAddressNormalized(profile);
+ return;
+ }
+
+ // Setup the necessary variables for the delayed normalization.
+ profile_ = profile;
+ requester_ = requester;
+}
+
+void TestAddressNormalizer::DelayNormalization() {
+ instantaneous_normalization_ = false;
+}
+
+void TestAddressNormalizer::CompleteAddressNormalization() {
+ DCHECK(instantaneous_normalization_ == false);
+ requester_->OnAddressNormalized(profile_);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_address_normalizer.h b/chromium/components/autofill/core/browser/test_address_normalizer.h
new file mode 100644
index 00000000000..d9dbbd8863f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_address_normalizer.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_H_
+
+#include <string>
+
+#include "components/autofill/core/browser/address_normalizer.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+
+namespace autofill {
+
+// A simpler version of the address normalizer to be used in tests. Can be set
+// to normalize instantaneously or to wait for a call.
+class TestAddressNormalizer : public AddressNormalizer {
+ public:
+ TestAddressNormalizer() {}
+
+ void LoadRulesForRegion(const std::string& region_code) override {}
+
+ bool AreRulesLoadedForRegion(const std::string& region_code) override;
+
+ void StartAddressNormalization(
+ const AutofillProfile& profile,
+ const std::string& region_code,
+ int timeout_seconds,
+ AddressNormalizer::Delegate* requester) override;
+
+ void OnAddressValidationRulesLoaded(const std::string& region_code,
+ bool success) override {}
+
+ void DelayNormalization();
+
+ void CompleteAddressNormalization();
+
+ private:
+ AutofillProfile profile_;
+ AddressNormalizer::Delegate* requester_;
+
+ bool instantaneous_normalization_ = true;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_ADDRESS_NORMALIZER_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 d663cdefe55..18413eec03f 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
@@ -33,17 +33,11 @@ void TestPersonalDataManager::AddTestingServerCreditCard(
server_credit_cards_.push_back(base::MakeUnique<CreditCard>(credit_card));
}
-const std::vector<AutofillProfile*>& TestPersonalDataManager::GetProfiles()
- const {
- return GetProfiles(false);
-}
-
-std::vector<AutofillProfile*> TestPersonalDataManager::web_profiles() const {
+std::vector<AutofillProfile*> TestPersonalDataManager::GetProfiles() const {
return profiles_;
}
-const std::vector<CreditCard*>& TestPersonalDataManager::GetCreditCards()
- const {
+std::vector<CreditCard*> TestPersonalDataManager::GetCreditCards() const {
return credit_cards_;
}
@@ -72,9 +66,4 @@ const std::string& TestPersonalDataManager::GetDefaultCountryCodeForNewAddress()
return default_country_code_;
}
-const std::vector<AutofillProfile*>& TestPersonalDataManager::GetProfiles(
- bool record_metrics) const {
- return profiles_;
-}
-
} // namespace autofill
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 71e06180cbe..d9868d8cfb1 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h
@@ -33,9 +33,8 @@ class TestPersonalDataManager : public PersonalDataManager {
// Adds |credit_card| to |server_credit_cards_| by copying.
void AddTestingServerCreditCard(const CreditCard& credit_card);
- const std::vector<AutofillProfile*>& GetProfiles() const override;
- std::vector<AutofillProfile*> web_profiles() const override;
- const std::vector<CreditCard*>& GetCreditCards() const override;
+ std::vector<AutofillProfile*> GetProfiles() const override;
+ std::vector<CreditCard*> GetCreditCards() const override;
std::string SaveImportedProfile(
const AutofillProfile& imported_profile) override;
@@ -56,9 +55,6 @@ class TestPersonalDataManager : public PersonalDataManager {
const CreditCard& imported_credit_card() { return imported_credit_card_; }
private:
- const std::vector<AutofillProfile*>& GetProfiles(
- bool record_metrics) const override;
-
std::vector<AutofillProfile*> profiles_;
std::vector<CreditCard*> credit_cards_;
AutofillProfile imported_profile_;
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
index c0e86025a21..6053afa3be3 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
@@ -193,7 +193,7 @@ syncer::SyncDataList AutocompleteSyncableService::GetAllSyncData(
}
syncer::SyncError AutocompleteSyncableService::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sync_processor_);
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.h
index 9d603cc19d2..72a22f778d9 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.h
@@ -74,7 +74,7 @@ class AutocompleteSyncableService
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// AutofillWebDataServiceObserverOnDBSequence:
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 e67793de69c..03e16fefd1b 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
@@ -227,7 +227,7 @@ syncer::SyncDataList AutofillProfileSyncableService::GetAllSyncData(
}
syncer::SyncError AutofillProfileSyncableService::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!sync_processor_.get()) {
@@ -407,6 +407,14 @@ bool AutofillProfileSyncableService::OverwriteProfileWithServerData(
diff = true;
}
+ // Update the validity state bitfield.
+ if (specifics.has_validity_state_bitfield() &&
+ specifics.validity_state_bitfield() !=
+ profile->GetValidityBitfieldValue()) {
+ profile->SetValidityFromBitfieldValue(specifics.validity_state_bitfield());
+ diff = true;
+ }
+
if (static_cast<size_t>(specifics.use_count()) != profile->use_count()) {
profile->set_use_count(specifics.use_count());
diff = true;
@@ -471,6 +479,7 @@ void AutofillProfileSyncableService::WriteAutofillProfile(
LimitData(
UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY))));
specifics->set_address_home_language_code(LimitData(profile.language_code()));
+ specifics->set_validity_state_bitfield(profile.GetValidityBitfieldValue());
// TODO(estade): this should be set_email_address.
specifics->add_email_address(
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
index 9ab95866032..8566101b710 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_syncable_service.h
@@ -75,7 +75,7 @@ class AutofillProfileSyncableService
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// AutofillWebDataServiceObserverOnDBSequence implementation.
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 7c840464cf4..d1ec72bf0e0 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
@@ -40,6 +40,7 @@ const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D";
const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E";
const char kHttpOrigin[] = "http://www.example.com/";
const char kHttpsOrigin[] = "https://www.example.com/";
+const int kValidityStateBitfield = 1984;
class MockAutofillProfileSyncableService
: public AutofillProfileSyncableService {
@@ -107,7 +108,7 @@ class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
~MockSyncChangeProcessor() override {}
MOCK_METHOD2(ProcessSyncChanges,
- syncer::SyncError(const tracked_objects::Location&,
+ syncer::SyncError(const base::Location&,
const syncer::SyncChangeList&));
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
return syncer::SyncDataList();
@@ -120,7 +121,7 @@ class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
~TestSyncChangeProcessor() override {}
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& location,
+ const base::Location& location,
const syncer::SyncChangeList& changes) override {
changes_ = changes;
return syncer::SyncError();
@@ -169,6 +170,7 @@ std::unique_ptr<AutofillProfile> ConstructCompleteProfile() {
profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
ASCIIToUTF16("Santa Clara"));
profile->set_language_code("en");
+ profile->SetValidityFromBitfieldValue(kValidityStateBitfield);
return profile;
}
@@ -206,6 +208,7 @@ syncer::SyncData ConstructCompleteSyncData() {
specifics->set_address_home_sorting_code("CEDEX");
specifics->set_address_home_dependent_locality("Santa Clara");
specifics->set_address_home_language_code("en");
+ specifics->set_validity_state_bitfield(kValidityStateBitfield);
return syncer::SyncData::CreateLocalData(kGuid1, kGuid1, entity_specifics);
}
@@ -1072,6 +1075,196 @@ TEST_F(AutofillProfileSyncableServiceTest, LanguageCodePropagates) {
EXPECT_EQ("en", specifics.address_home_language_code());
}
+// Missing validity state bitifield should not generate sync events.
+TEST_F(AutofillProfileSyncableServiceTest, DefaultValidityStateNoSync) {
+ std::vector<std::unique_ptr<AutofillProfile>> profiles_from_web_db;
+
+ // Local autofill profile has a default validity state bitfield.
+ AutofillProfile profile(kGuid1, kHttpsOrigin);
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+ profiles_from_web_db.push_back(base::MakeUnique<AutofillProfile>(profile));
+
+ // Remote data does not have a validity state bitfield value.
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::AutofillProfileSpecifics* autofill_specifics =
+ specifics.mutable_autofill_profile();
+ autofill_specifics->set_guid(profile.guid());
+ autofill_specifics->set_origin(profile.origin());
+ autofill_specifics->add_name_first(std::string());
+ autofill_specifics->add_name_middle(std::string());
+ autofill_specifics->add_name_last(std::string());
+ autofill_specifics->add_name_full(std::string());
+ autofill_specifics->add_email_address(std::string());
+ autofill_specifics->add_phone_home_whole_number(std::string());
+ autofill_specifics->set_use_count(profile.use_count());
+ autofill_specifics->set_use_date(profile.use_date().ToTimeT());
+ EXPECT_FALSE(autofill_specifics->has_validity_state_bitfield());
+
+ syncer::SyncDataList data_list;
+ data_list.push_back(syncer::SyncData::CreateLocalData(
+ profile.guid(), profile.guid(), specifics));
+
+ // Expect no changes to local and remote data.
+ MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
+ syncer::SyncChangeList expected_empty_change_list;
+
+ MergeDataAndStartSyncing(std::move(profiles_from_web_db), data_list,
+ expected_empty_bundle, expected_empty_change_list);
+ autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+// Default validity state bitfield should be overwritten by sync.
+TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesDefaultValidityBitfield) {
+ std::vector<std::unique_ptr<AutofillProfile>> profiles_from_web_db;
+
+ // Local autofill profile has a default validity state.
+ AutofillProfile profile(kGuid1, kHttpsOrigin);
+ EXPECT_EQ(0, profile.GetValidityBitfieldValue());
+ profiles_from_web_db.push_back(base::MakeUnique<AutofillProfile>(profile));
+
+ // Remote data has a non default validity state bitfield value.
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::AutofillProfileSpecifics* autofill_specifics =
+ specifics.mutable_autofill_profile();
+ autofill_specifics->set_guid(profile.guid());
+ autofill_specifics->set_origin(profile.origin());
+ autofill_specifics->add_name_first(std::string());
+ autofill_specifics->add_name_middle(std::string());
+ autofill_specifics->add_name_last(std::string());
+ autofill_specifics->add_name_full(std::string());
+ autofill_specifics->add_email_address(std::string());
+ autofill_specifics->add_phone_home_whole_number(std::string());
+ autofill_specifics->set_validity_state_bitfield(kValidityStateBitfield);
+ EXPECT_TRUE(autofill_specifics->has_validity_state_bitfield());
+
+ syncer::SyncDataList data_list;
+ data_list.push_back(syncer::SyncData::CreateLocalData(
+ profile.guid(), profile.guid(), specifics));
+
+ // Expect the local autofill profile to have the non default validity state
+ // bitfield after sync.
+ MockAutofillProfileSyncableService::DataBundle expected_bundle;
+ AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
+ expected_profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ expected_bundle.profiles_to_update.push_back(&expected_profile);
+
+ // Expect no changes to remote data.
+ syncer::SyncChangeList expected_empty_change_list;
+
+ MergeDataAndStartSyncing(std::move(profiles_from_web_db), data_list,
+ expected_bundle, expected_empty_change_list);
+ autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+// Local validity state bitfield should be overwritten by sync.
+TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesLocalValidityBitfield) {
+ std::vector<std::unique_ptr<AutofillProfile>> profiles_from_web_db;
+
+ // Local autofill profile has a non default validity state bitfield value.
+ AutofillProfile profile(kGuid1, kHttpsOrigin);
+ profile.SetValidityFromBitfieldValue(kValidityStateBitfield + 1);
+ profiles_from_web_db.push_back(base::MakeUnique<AutofillProfile>(profile));
+
+ // Remote data has a different non default validity state bitfield value.
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::AutofillProfileSpecifics* autofill_specifics =
+ specifics.mutable_autofill_profile();
+ autofill_specifics->set_guid(profile.guid());
+ autofill_specifics->set_origin(profile.origin());
+ autofill_specifics->add_name_first(std::string());
+ autofill_specifics->add_name_middle(std::string());
+ autofill_specifics->add_name_last(std::string());
+ autofill_specifics->add_name_full(std::string());
+ autofill_specifics->add_email_address(std::string());
+ autofill_specifics->add_phone_home_whole_number(std::string());
+ autofill_specifics->set_validity_state_bitfield(kValidityStateBitfield);
+ EXPECT_TRUE(autofill_specifics->has_validity_state_bitfield());
+
+ syncer::SyncDataList data_list;
+ data_list.push_back(syncer::SyncData::CreateLocalData(
+ profile.guid(), profile.guid(), specifics));
+
+ // Expect the local autofill profile to have the remote validity state
+ // bitfield value after sync.
+ MockAutofillProfileSyncableService::DataBundle expected_bundle;
+ AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
+ expected_profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ expected_bundle.profiles_to_update.push_back(&expected_profile);
+
+ // Expect no changes to remote data.
+ syncer::SyncChangeList expected_empty_change_list;
+
+ MergeDataAndStartSyncing(std::move(profiles_from_web_db), data_list,
+ expected_bundle, expected_empty_change_list);
+ autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+// Sync data without a default validity state bitfield should not overwrite
+// an existing validity state bitfield in local autofill profile.
+TEST_F(AutofillProfileSyncableServiceTest,
+ DefaultSyncPreservesLocalValidityBitfield) {
+ std::vector<std::unique_ptr<AutofillProfile>> profiles_from_web_db;
+
+ // Local autofill profile has a non default validity state bitfield value.
+ AutofillProfile profile(kGuid1, kHttpsOrigin);
+ profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ profiles_from_web_db.push_back(base::MakeUnique<AutofillProfile>(profile));
+
+ // Remote data does not has no validity state bitfield value.
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::AutofillProfileSpecifics* autofill_specifics =
+ specifics.mutable_autofill_profile();
+ autofill_specifics->set_guid(profile.guid());
+ autofill_specifics->set_origin(profile.origin());
+ autofill_specifics->add_name_first("John");
+ autofill_specifics->add_name_middle(std::string());
+ autofill_specifics->add_name_last(std::string());
+ autofill_specifics->add_name_full(std::string());
+ autofill_specifics->add_email_address(std::string());
+ autofill_specifics->add_phone_home_whole_number(std::string());
+ EXPECT_FALSE(autofill_specifics->has_validity_state_bitfield());
+
+ syncer::SyncDataList data_list;
+ data_list.push_back(syncer::SyncData::CreateLocalData(
+ profile.guid(), profile.guid(), specifics));
+
+ // Expect local autofill profile to still have the kValidityStateBitfield
+ // language code after sync.
+ MockAutofillProfileSyncableService::DataBundle expected_bundle;
+ AutofillProfile expected_profile(profile.guid(), profile.origin());
+ expected_profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
+ expected_bundle.profiles_to_update.push_back(&expected_profile);
+
+ // Expect no changes to remote data.
+ syncer::SyncChangeList expected_empty_change_list;
+
+ MergeDataAndStartSyncing(std::move(profiles_from_web_db), data_list,
+ expected_bundle, expected_empty_change_list);
+ autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
+}
+
+// Validity state bitfield in autofill profiles should be synced to the server.
+TEST_F(AutofillProfileSyncableServiceTest, LocalValidityBitfieldPropagates) {
+ TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
+ autofill_syncable_service_.set_sync_processor(sync_change_processor);
+
+ AutofillProfile profile(kGuid1, kHttpsOrigin);
+ profile.SetValidityFromBitfieldValue(kValidityStateBitfield);
+ AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
+ autofill_syncable_service_.AutofillProfileChanged(change);
+
+ ASSERT_EQ(1U, sync_change_processor->changes().size());
+ syncer::SyncChange result = sync_change_processor->changes()[0];
+ EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());
+
+ sync_pb::AutofillProfileSpecifics specifics =
+ result.sync_data().GetSpecifics().autofill_profile();
+ EXPECT_EQ(kGuid1, specifics.guid());
+ EXPECT_EQ(kHttpsOrigin, specifics.origin());
+ EXPECT_EQ(kValidityStateBitfield, specifics.validity_state_bitfield());
+}
+
// Missing full name field should not generate sync events.
TEST_F(AutofillProfileSyncableServiceTest, NoFullNameNoSync) {
std::vector<std::unique_ptr<AutofillProfile>> profiles_from_web_db;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index 92ce2201c1a..2c64d1f66fb 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -7,7 +7,6 @@
#include <stdint.h>
#include <algorithm>
-#include <cmath>
#include <limits>
#include <map>
#include <set>
@@ -43,6 +42,7 @@
#include "sql/statement.h"
#include "sql/transaction.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "url/gurl.h"
namespace autofill {
@@ -61,12 +61,6 @@ struct AutofillUpdate {
int count;
};
-// Rounds a positive floating point number to the nearest integer.
-int Round(float f) {
- DCHECK_GE(f, 0.f);
- return base::checked_cast<int>(std::floor(f + 0.5f));
-}
-
// Returns the |data_model|'s value corresponding to the |type|, trimmed to the
// maximum length that can be stored in a column of the Autofill database.
base::string16 GetInfo(const AutofillDataModel& data_model,
@@ -98,6 +92,7 @@ void BindAutofillProfileToStatement(const AutofillProfile& profile,
s->BindInt64(index++, modification_date.ToTimeT());
s->BindString(index++, profile.origin());
s->BindString(index++, profile.language_code());
+ s->BindInt64(index++, profile.GetValidityBitfieldValue());
}
std::unique_ptr<AutofillProfile> AutofillProfileFromStatement(
@@ -121,6 +116,7 @@ std::unique_ptr<AutofillProfile> AutofillProfileFromStatement(
profile->set_modification_date(base::Time::FromTimeT(s.ColumnInt64(index++)));
profile->set_origin(s.ColumnString(index++));
profile->set_language_code(s.ColumnString(index++));
+ profile->SetValidityFromBitfieldValue(s.ColumnInt64(index++));
return profile;
}
@@ -479,6 +475,9 @@ bool AutofillTable::MigrateToVersion(int version,
case 74:
*update_compatible_version = false;
return MigrateToVersion74AddServerCardTypeColumn();
+ case 75:
+ *update_compatible_version = false;
+ return MigrateToVersion75AddProfileValidityBitfieldColumn();
}
return true;
}
@@ -631,10 +630,10 @@ bool AutofillTable::RemoveFormElementsAddedBetween(
? date_last_used_time_t
: delete_begin_time_t - 1;
updated_entry.count =
- 1 +
- Round(1.0 * (count - 1) *
- (updated_entry.date_last_used - updated_entry.date_created) /
- (date_last_used_time_t - date_created_time_t));
+ 1 + gfx::ToRoundedInt(
+ 1.0 * (count - 1) *
+ (updated_entry.date_last_used - updated_entry.date_created) /
+ (date_last_used_time_t - date_created_time_t));
updates.push_back(updated_entry);
}
@@ -884,8 +883,8 @@ bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) {
"INSERT INTO autofill_profiles"
"(guid, company_name, street_address, dependent_locality, city, state,"
" zipcode, sorting_code, country_code, use_count, use_date, "
- " date_modified, origin, language_code)"
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ " date_modified, origin, language_code, validity_bitfield)"
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
BindAutofillProfileToStatement(profile, AutofillClock::Now(), &s);
if (!s.Run())
@@ -900,7 +899,7 @@ std::unique_ptr<AutofillProfile> AutofillTable::GetAutofillProfile(
sql::Statement s(db_->GetUniqueStatement(
"SELECT guid, company_name, street_address, dependent_locality, city,"
" state, zipcode, sorting_code, country_code, use_count, use_date,"
- " date_modified, origin, language_code "
+ " date_modified, origin, language_code, validity_bitfield "
"FROM autofill_profiles "
"WHERE guid=?"));
s.BindString(0, guid);
@@ -1088,14 +1087,15 @@ bool AutofillTable::UpdateAutofillProfile(const AutofillProfile& profile) {
"UPDATE autofill_profiles "
"SET guid=?, company_name=?, street_address=?, dependent_locality=?, "
" city=?, state=?, zipcode=?, sorting_code=?, country_code=?, "
- " use_count=?, use_date=?, date_modified=?, origin=?, language_code=? "
+ " use_count=?, use_date=?, date_modified=?, origin=?, "
+ " language_code=?, validity_bitfield=? "
"WHERE guid=?"));
BindAutofillProfileToStatement(profile,
update_modification_date
? AutofillClock::Now()
: old_profile->modification_date(),
&s);
- s.BindString(14, profile.guid());
+ s.BindString(15, profile.guid());
bool result = s.Run();
DCHECK_GT(db_->GetLastChangeCount(), 0);
@@ -1907,7 +1907,8 @@ bool AutofillTable::InitProfilesTable() {
"origin VARCHAR DEFAULT '', "
"language_code VARCHAR, "
"use_count INTEGER NOT NULL DEFAULT 0, "
- "use_date INTEGER NOT NULL DEFAULT 0) ")) {
+ "use_date INTEGER NOT NULL DEFAULT 0, "
+ "validity_bitfield UNSIGNED NOT NULL DEFAULT 0) ")) {
NOTREACHED();
return false;
}
@@ -2642,4 +2643,11 @@ bool AutofillTable::MigrateToVersion74AddServerCardTypeColumn() {
"COLUMN type INTEGER DEFAULT 0");
}
+bool AutofillTable::MigrateToVersion75AddProfileValidityBitfieldColumn() {
+ // Add the new valdity_bitfield column to the autofill_profiles table.
+ return db_->Execute(
+ "ALTER TABLE autofill_profiles ADD COLUMN validity_bitfield UNSIGNED NOT "
+ "NULL DEFAULT 0");
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.h b/chromium/components/autofill/core/browser/webdata/autofill_table.h
index 95634417a01..bc498b96805 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -87,6 +87,9 @@ struct FormFieldData;
// code starts with the postal code, but a JP address with
// "ja-latn" language code starts with the recipient name.
// Added in version 56.
+// validity_bitfield A bitfield representing the validity state of different
+// fields in the profile.
+// Added in version 75.
//
// autofill_profile_names
// This table contains the multi-valued name fields
@@ -469,6 +472,7 @@ class AutofillTable : public WebDatabaseTable,
bool MigrateToVersion72RenameCardTypeToIssuerNetwork();
bool MigrateToVersion73AddMaskedCardBankName();
bool MigrateToVersion74AddServerCardTypeColumn();
+ bool MigrateToVersion75AddProfileValidityBitfieldColumn();
// Max data length saved in the table, AKA the maximum length allowed for
// form data.
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 298a2c3c422..5df7e968873 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -735,7 +735,8 @@ TEST_F(AutofillTableTest,
}
TEST_F(AutofillTableTest, AutofillProfile) {
- // Add a 'Home' profile.
+ // Add a 'Home' profile with non-default data. The specific values are not
+ // important.
AutofillProfile home_profile;
home_profile.set_origin(std::string());
home_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
@@ -754,6 +755,7 @@ TEST_F(AutofillTableTest, AutofillProfile) {
home_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
home_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("18181234567"));
home_profile.set_language_code("en");
+ home_profile.SetValidityFromBitfieldValue(6);
Time pre_creation_time = Time::Now();
EXPECT_TRUE(table_->AddAutofillProfile(home_profile));
@@ -818,7 +820,8 @@ TEST_F(AutofillTableTest, AutofillProfile) {
post_modification_time.ToTimeT());
EXPECT_FALSE(s_billing_updated.Step());
- // Update the 'Billing' profile.
+ // Update the 'Billing' profile with non-default data. The specific values are
+ // not important.
billing_profile.set_origin(kSettingsOrigin);
billing_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Janice"));
billing_profile.SetRawInfo(NAME_MIDDLE, ASCIIToUTF16("C."));
@@ -836,6 +839,7 @@ TEST_F(AutofillTableTest, AutofillProfile) {
billing_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
billing_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
ASCIIToUTF16("18181230000"));
+ billing_profile.SetValidityFromBitfieldValue(54);
Time pre_modification_time_2 = Time::Now();
EXPECT_TRUE(table_->UpdateAutofillProfile(billing_profile));
Time post_modification_time_2 = Time::Now();
@@ -1612,6 +1616,40 @@ TEST_F(AutofillTableTest, Autofill_GetAllAutofillEntries_TwoSame) {
CompareAutofillEntrySets(entry_set, expected_entries);
}
+TEST_F(AutofillTableTest, AutofillProfileValidityBitfield) {
+ // Add an autofill profile with a non default validity state. The value itself
+ // is insignificant for this test since only the serialization and
+ // deserialization are tested.
+ const int kValidityBitfieldValue = 1984;
+ AutofillProfile profile;
+ profile.set_origin(std::string());
+ profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
+ profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+ profile.SetValidityFromBitfieldValue(kValidityBitfieldValue);
+
+ // Add the profile to the table.
+ EXPECT_TRUE(table_->AddAutofillProfile(profile));
+
+ // Get the profile from the table and make sure the validity was set.
+ std::unique_ptr<AutofillProfile> db_profile =
+ table_->GetAutofillProfile(profile.guid());
+ ASSERT_TRUE(db_profile);
+ EXPECT_EQ(kValidityBitfieldValue, db_profile->GetValidityBitfieldValue());
+
+ // Modify the validity of the profile.
+ const int kOtherValidityBitfieldValue = 1999;
+ profile.SetValidityFromBitfieldValue(kOtherValidityBitfieldValue);
+
+ // Update the profile in the table.
+ EXPECT_TRUE(table_->UpdateAutofillProfile(profile));
+
+ // Get the profile from the table and make sure the validity was updated.
+ db_profile = table_->GetAutofillProfile(profile.guid());
+ ASSERT_TRUE(db_profile);
+ EXPECT_EQ(kOtherValidityBitfieldValue,
+ db_profile->GetValidityBitfieldValue());
+}
+
TEST_F(AutofillTableTest, SetGetServerCards) {
std::vector<CreditCard> inputs;
inputs.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "a123"));
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 7d47212f84f..a1720b4f461 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
@@ -387,7 +387,7 @@ syncer::SyncDataList AutofillWalletMetadataSyncableService::GetAllSyncData(
}
syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& changes_from_sync) {
DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
index 5e16997bdf3..23da67cc634 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h
@@ -21,15 +21,15 @@
#include "components/sync/model/syncable_service.h"
#include "components/sync/protocol/autofill_specifics.pb.h"
+namespace base {
+class Location;
+}
+
namespace syncer {
class SyncChangeProcessor;
class SyncErrorFactory;
}
-namespace tracked_objects {
-class Location;
-}
-
namespace autofill {
class AutofillProfile;
@@ -60,7 +60,7 @@ class AutofillWalletMetadataSyncableService
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& changes_from_sync) override;
// AutofillWebDataServiceObserverOnDBSequence implementation.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index 39382970d7a..90d6408695e 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -238,7 +238,7 @@ syncer::SyncDataList AutofillWalletSyncableService::GetAllSyncData(
}
syncer::SyncError AutofillWalletSyncableService::ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
DCHECK(thread_checker_.CalledOnValidThread());
// Don't bother handling incremental updates. Wallet data changes very rarely
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
index 4156f6cd644..9e823ae952f 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h
@@ -39,7 +39,7 @@ class AutofillWalletSyncableService
void StopSyncing(syncer::ModelType type) override;
syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
syncer::SyncError ProcessSyncChanges(
- const tracked_objects::Location& from_here,
+ const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// Creates a new AutofillWalletSyncableService and hangs it off of
diff --git a/chromium/components/autofill/core/common/autofill_pref_names.cc b/chromium/components/autofill/core/common/autofill_pref_names.cc
index 4f3b11dc6cf..c52ffb9a7cf 100644
--- a/chromium/components/autofill/core/common/autofill_pref_names.cc
+++ b/chromium/components/autofill/core/common/autofill_pref_names.cc
@@ -26,6 +26,16 @@ const char kAutofillWalletImportEnabled[] = "autofill.wallet_import_enabled";
// was run. This routine will be run once per version.
const char kAutofillLastVersionDeduped[] = "autofill.last_version_deduped";
+// Integer that is set to the last version where disused addresses were
+// deleted. This deletion will be run once per version.
+const char kAutofillLastVersionDisusedAddressesDeleted[] =
+ "autofill.last_version_disused_addresses_deleted";
+
+// Integer that is set to the last version where disused credit cards were
+// deleted. This deletion will be run once per version.
+const char kAutofillLastVersionDisusedCreditCardsDeleted[] =
+ "autofill.last_version_disused_credit_cards_deleted";
+
// Boolean that is set to the last choice user made when prompted for saving an
// unmasked server card locally.
const char kAutofillWalletImportStorageCheckboxState[] =
@@ -38,5 +48,9 @@ const char kAutofillWalletImportStorageCheckboxState[] =
const char kAutofillAcceptSaveCreditCardPromptState[] =
"autofill.accept_save_credit_card_prompt_state";
+// Boolean that is true if Autofill is enabled and allowed to save credit card
+// data.
+const char kAutofillCreditCardEnabled[] = "autofill.credit_card_enabled";
+
} // namespace prefs
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_pref_names.h b/chromium/components/autofill/core/common/autofill_pref_names.h
index e18a77abdb8..de57761997c 100644
--- a/chromium/components/autofill/core/common/autofill_pref_names.h
+++ b/chromium/components/autofill/core/common/autofill_pref_names.h
@@ -12,10 +12,13 @@ namespace prefs {
// component. Keep alphabetized, and document each in the .cc file.
extern const char kAutofillAcceptSaveCreditCardPromptState[];
+extern const char kAutofillCreditCardEnabled[];
extern const char kAutofillCreditCardSigninPromoImpressionCount[];
extern const char kAutofillEnabled[];
-extern const char kAutofillProfileUseDatesFixed[];
extern const char kAutofillLastVersionDeduped[];
+extern const char kAutofillLastVersionDisusedAddressesDeleted[];
+extern const char kAutofillLastVersionDisusedCreditCardsDeleted[];
+extern const char kAutofillProfileUseDatesFixed[];
extern const char kAutofillWalletImportEnabled[];
extern const char kAutofillWalletImportStorageCheckboxState[];
diff --git a/chromium/components/autofill/core/common/autofill_regex_constants.cc b/chromium/components/autofill/core/common/autofill_regex_constants.cc
index 47c9883b857..81463c16b0c 100644
--- a/chromium/components/autofill/core/common/autofill_regex_constants.cc
+++ b/chromium/components/autofill/core/common/autofill_regex_constants.cc
@@ -299,32 +299,53 @@ const char kPhoneExtensionRe[] =
"|ramal"; // pt-BR, pt-PT
const char kUPIVirtualPaymentAddressRe[] =
"^\\w+@("
- "upi|" // BHIM Bharat Interface for Money
- "allbank|" // Allahabad Bank UPI
- "andb|" // Andhra Bank ONE
- "axisbank|" // Axis Pay
- "barodampay|" // Baroda MPay
- "mahb|" // MAHAUPI
- "cnrb|" // Canara Bank UPI - Empower
- "csbpay|" // CSB UPI
- "dcb|" // DCB Bank
- "federal|" // Lotza
- "hdfcbank|" // HDFC Bank MobileBanking
- "pockets|" // Pockets- ICICI Bank
- "icici|" // Pockets- ICICI Bank
- "idfcbank|" // IDFC Bank UPI App
- "indus|" // Indus Pay
- "kbl|" // KBL Smartz
- "kaypay|" // KayPay
- "pnb|" // PNB UPI
- "sib|" // SIB M-Pay (UPI Pay)
- "sbi|" // SBI Pay
- "tjsp|" // TranZapp
- "uco|" // UCO UPI
- "unionbank|" // Union Bank UPI
- "united|" // United UPI
- "vijb|" // Vijaya UPI App
- "ybl" // Yes Pay
+ "allbank|" // Allahabad Bank UPI
+ "andb|" // Andhra Bank ONE
+ "axisbank|" // Axis Pay
+ "barodampay|" // Baroda MPay
+ "centralbank|" // Cent UPI
+ "cnrb|" // Canara Bank UPI - Empower
+ "csbpay|" // CSB UPI
+ "dbs|" // digibank by DBS
+ "dcb|" // DCB Bank
+ "denabank|" // Dena Bank E-UPI
+ "fbl|" // Cointab
+ "federal|" // Lotza
+ "hdfcbank|" // HDFC Bank MobileBanking
+ "hsbc|" // HSBC Simply Pay
+ "icici|" // Pockets- ICICI Bank
+ "idbi|" // PayWiz
+ "idfcbank|" // IDFC Bank UPI App
+ "indianbank|" // Indian Bank UPI
+ "indus|" // Indus Pay
+ "iob|" // IOB UPI
+ "kaypay|" // KayPay
+ "kbl|" // KBL Smartz
+ "kotak|" // kotak Mahindra Bank
+ "kvb|" // KVB Upay
+ "lvb|" // LVB UPay
+ "mahb|" // MAHAUPI
+ "obc|" // Oriental BHIM UPI
+ "pingpay|" // Samsung Pay
+ "pnb|" // PNB UPI
+ "pockets|" // Pockets- ICICI Bank
+ "psb|" // PSB UPI App
+ "rbl|" // RBL Pay
+ "sbi|" // SBI Pay
+ "scb|" // Standard Chartered
+ "sib|" // SIB M-Pay (UPI Pay)
+ "syndicate|" // Synd UPI
+ "tjsp|" // TranZapp
+ "ubi|" // United UPI
+ "uboi|" // Union Bank UPI
+ "uco|" // UCO UPI
+ "unionbank|" // Union Bank UPI
+ "united|" // United UPI
+ "upi|" // BHIM Bharat Interface for Money
+ "utbi|" // United UPI
+ "vijb|" // Vijaya UPI App
+ "ybl|" // Yes Pay
+ "yesbank" // NuPay
")$";
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/password_form.cc b/chromium/components/autofill/core/common/password_form.cc
index cc44dd7f494..5039ca95d53 100644
--- a/chromium/components/autofill/core/common/password_form.cc
+++ b/chromium/components/autofill/core/common/password_form.cc
@@ -44,6 +44,8 @@ void PasswordFormToJSON(const PasswordForm& form,
target->SetString(
"other_possible_usernames",
OtherPossibleUsernamesToString(form.other_possible_usernames));
+ target->SetString("all_possible_passwords",
+ AllPossiblePasswordsToString(form.all_possible_passwords));
target->SetBoolean("blacklisted", form.blacklisted_by_user);
target->SetBoolean("preferred", form.preferred);
target->SetDouble("date_created", form.date_created.ToDoubleT());
@@ -78,6 +80,7 @@ void PasswordFormToJSON(const PasswordForm& form,
PasswordForm::PasswordForm()
: scheme(SCHEME_HTML),
username_marked_by_site(false),
+ form_has_autofilled_value(false),
password_value_is_default(false),
new_password_value_is_default(false),
new_password_marked_by_site(false),
@@ -96,8 +99,14 @@ PasswordForm::PasswordForm()
PasswordForm::PasswordForm(const PasswordForm& other) = default;
+PasswordForm::PasswordForm(PasswordForm&& other) = default;
+
PasswordForm::~PasswordForm() = default;
+PasswordForm& PasswordForm::operator=(const PasswordForm& form) = default;
+
+PasswordForm& PasswordForm::operator=(PasswordForm&& form) = default;
+
bool PasswordForm::IsPossibleChangePasswordForm() const {
return !new_password_element.empty() &&
layout != PasswordForm::Layout::LAYOUT_LOGIN_AND_SIGNUP;
@@ -115,6 +124,8 @@ bool PasswordForm::operator==(const PasswordForm& form) const {
username_marked_by_site == form.username_marked_by_site &&
username_value == form.username_value &&
other_possible_usernames == form.other_possible_usernames &&
+ all_possible_passwords == form.all_possible_passwords &&
+ form_has_autofilled_value == form.form_has_autofilled_value &&
password_element == form.password_element &&
password_value == form.password_value &&
new_password_element == form.new_password_element &&
@@ -187,6 +198,11 @@ base::string16 OtherPossibleUsernamesToString(
return base::JoinString(pairs, base::ASCIIToUTF16(", "));
}
+base::string16 AllPossiblePasswordsToString(
+ const std::vector<base::string16>& possible_passwords) {
+ return base::JoinString(possible_passwords, base::ASCIIToUTF16(", "));
+}
+
std::ostream& operator<<(std::ostream& os, PasswordForm::Layout layout) {
switch (layout) {
case PasswordForm::Layout::LAYOUT_OTHER:
diff --git a/chromium/components/autofill/core/common/password_form.h b/chromium/components/autofill/core/common/password_form.h
index 825fdabcda6..c1931c4f9df 100644
--- a/chromium/components/autofill/core/common/password_form.h
+++ b/chromium/components/autofill/core/common/password_form.h
@@ -183,6 +183,14 @@ struct PasswordForm {
// When parsing an HTML form, this is typically empty.
PossibleUsernamesVector other_possible_usernames;
+ // This member is populated in cases where we there are multiple posssible
+ // password values. Used in pending password state, to populate a dropdown
+ // for possible passwords. Contains all possible passwords. Optional.
+ std::vector<base::string16> all_possible_passwords;
+
+ // True if |all_possible_passwords| have autofilled value or its part.
+ bool form_has_autofilled_value;
+
// The name of the input element corresponding to the current password.
// Optional (improves scoring).
//
@@ -332,7 +340,11 @@ struct PasswordForm {
PasswordForm();
PasswordForm(const PasswordForm& other);
+ PasswordForm(PasswordForm&& other);
~PasswordForm();
+
+ PasswordForm& operator=(const PasswordForm& form);
+ PasswordForm& operator=(PasswordForm&& form);
};
// True if the unique keys for the forms are the same. The unique key is
@@ -350,6 +362,10 @@ struct LessThanUniqueKey {
base::string16 OtherPossibleUsernamesToString(
const PossibleUsernamesVector& possible_usernames);
+// Converts a vector of possible passwords to string.
+base::string16 AllPossiblePasswordsToString(
+ const std::vector<base::string16>& possible_passwords);
+
// For testing.
std::ostream& operator<<(std::ostream& os, PasswordForm::Layout layout);
std::ostream& operator<<(std::ostream& os, const PasswordForm& form);
diff --git a/chromium/components/autofill/core/common/password_generation_util.h b/chromium/components/autofill/core/common/password_generation_util.h
index af37a9e29ba..0d1547a779d 100644
--- a/chromium/components/autofill/core/common/password_generation_util.h
+++ b/chromium/components/autofill/core/common/password_generation_util.h
@@ -62,6 +62,12 @@ enum PasswordGenerationEvent {
// new-password are set.
AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION,
+ // Generation is triggered by the user from the context menu.
+ PASSWORD_GENERATION_CONTEXT_MENU_PRESSED,
+
+ // Context menu with generation item was shown.
+ PASSWORD_GENERATION_CONTEXT_MENU_SHOWN,
+
// Number of enum entries, used for UMA histogram reporting macros.
EVENT_ENUM_COUNT
};
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.cc b/chromium/components/autofill/core/common/save_password_progress_logger.cc
index 19b46a8368d..3eb32852cc5 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -394,9 +394,6 @@ std::string SavePasswordProgressLogger::GetStringFromID(
return "Generation disabled: saving disabled";
case SavePasswordProgressLogger::STRING_GENERATION_DISABLED_NO_SYNC:
return "Generation disabled: no sync";
- case SavePasswordProgressLogger::
- STRING_GENERATION_DISABLED_CUSTOM_PASSPHRASE:
- return "Generation disabled: custom passphrase";
case STRING_GENERATION_RENDERER_ENABLED:
return "Generation renderer enabled";
case STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM:
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger.h b/chromium/components/autofill/core/common/save_password_progress_logger.h
index d55b04f5119..e2770ac9d3a 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.h
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.h
@@ -152,7 +152,6 @@ class SavePasswordProgressLogger {
STRING_REUSE_FOUND,
STRING_GENERATION_DISABLED_SAVING_DISABLED,
STRING_GENERATION_DISABLED_NO_SYNC,
- STRING_GENERATION_DISABLED_CUSTOM_PASSPHRASE,
STRING_GENERATION_RENDERER_ENABLED,
STRING_GENERATION_RENDERER_INVALID_PASSWORD_FORM,
STRING_GENERATION_RENDERER_POSSIBLE_ACCOUNT_CREATION_FORMS,