summaryrefslogtreecommitdiff
path: root/chromium/components/autofill/core
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-05 17:15:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-11 07:47:18 +0000
commit7324afb043a0b1e623d8e8eb906cdc53bdeb4685 (patch)
treea3fe2d74ea9c9e142c390dac4ca0e219382ace46 /chromium/components/autofill/core
parent6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (diff)
downloadqtwebengine-chromium-7324afb043a0b1e623d8e8eb906cdc53bdeb4685.tar.gz
BASELINE: Update Chromium to 58.0.3029.54
Change-Id: I67f57065a7afdc8e4614adb5c0230281428df4d1 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/components/autofill/core')
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn22
-rw-r--r--chromium/components/autofill/core/browser/DEPS3
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_assistant.h6
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h7
-rw-r--r--chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_model.cc9
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.cc57
-rw-r--r--chromium/components/autofill/core/browser/autofill_data_util.h14
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver.h4
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory.cc58
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory.h71
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc240
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc43
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.h21
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc140
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h43
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager_unittest.cc272
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc52
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h39
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc285
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc4
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc5
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.h3
-rw-r--r--chromium/components/autofill/core/browser/country_combobox_model.cc99
-rw-r--r--chromium/components/autofill/core/browser/country_combobox_model.h56
-rw-r--r--chromium/components/autofill/core/browser/country_combobox_model_unittest.cc65
-rw-r--r--chromium/components/autofill/core/browser/country_data.cc2
-rw-r--r--chromium/components/autofill/core/browser/credit_card.cc159
-rw-r--r--chromium/components/autofill/core/browser/credit_card.h31
-rw-r--r--chromium/components/autofill/core/browser/credit_card_field.cc5
-rw-r--r--chromium/components/autofill/core/browser/credit_card_unittest.cc72
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc7
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc105
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.cc69
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.h25
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc358
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_service_url.cc11
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_service_url_unittest.cc18
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc266
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h77
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc906
-rw-r--r--chromium/components/autofill/core/browser/proto/server.proto9
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc4
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h7
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_clock.cc33
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_clock.h39
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.cc7
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.h3
-rw-r--r--chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc23
-rw-r--r--chromium/components/autofill/core/browser/validation.cc134
-rw-r--r--chromium/components/autofill/core/browser/validation.h19
-rw-r--r--chromium/components/autofill/core/browser/validation_unittest.cc302
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc46
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h3
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc201
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc3
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_entry.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_entry.h4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc127
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h9
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_encryptor.h26
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.cc33
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.h53
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc107
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc73
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc224
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc13
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.h18
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc72
-rw-r--r--chromium/components/autofill/core/browser/webdata/system_encryptor.cc21
-rw-r--r--chromium/components/autofill/core/browser/webdata/system_encryptor.h30
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc36
-rw-r--r--chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h49
-rw-r--r--chromium/components/autofill/core/common/BUILD.gn2
-rw-r--r--chromium/components/autofill/core/common/autofill_clock.cc43
-rw-r--r--chromium/components/autofill/core/common/autofill_clock.h48
-rw-r--r--chromium/components/autofill/core/common/autofill_switches.cc3
-rw-r--r--chromium/components/autofill/core/common/autofill_switches.h1
-rw-r--r--chromium/components/autofill/core/common/autofill_util.cc5
-rw-r--r--chromium/components/autofill/core/common/autofill_util.h3
-rw-r--r--chromium/components/autofill/core/common/form_field_data.cc28
-rw-r--r--chromium/components/autofill/core/common/form_field_data.h2
-rw-r--r--chromium/components/autofill/core/common/form_field_data_unittest.cc42
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger.cc5
88 files changed, 4475 insertions, 1185 deletions
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index 5281b7de472..4e6332c41f8 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -28,6 +28,8 @@ static_library("browser") {
"autofill_download_manager.cc",
"autofill_download_manager.h",
"autofill_driver.h",
+ "autofill_driver_factory.cc",
+ "autofill_driver_factory.h",
"autofill_experiments.cc",
"autofill_experiments.h",
"autofill_external_delegate.cc",
@@ -60,6 +62,8 @@ static_library("browser") {
"card_unmask_delegate.h",
"contact_info.cc",
"contact_info.h",
+ "country_combobox_model.cc",
+ "country_combobox_model.h",
"country_data.cc",
"country_data.h",
"country_names.cc",
@@ -135,6 +139,9 @@ static_library("browser") {
"webdata/autofill_profile_syncable_service.h",
"webdata/autofill_table.cc",
"webdata/autofill_table.h",
+ "webdata/autofill_table_encryptor.h",
+ "webdata/autofill_table_encryptor_factory.cc",
+ "webdata/autofill_table_encryptor_factory.h",
"webdata/autofill_wallet_metadata_syncable_service.cc",
"webdata/autofill_wallet_metadata_syncable_service.h",
"webdata/autofill_wallet_syncable_service.cc",
@@ -146,6 +153,10 @@ static_library("browser") {
"webdata/autofill_webdata_service.cc",
"webdata/autofill_webdata_service.h",
"webdata/autofill_webdata_service_observer.h",
+ "webdata/system_encryptor.cc",
+ "webdata/system_encryptor.h",
+ "webdata/web_data_model_type_controller.cc",
+ "webdata/web_data_model_type_controller.h",
]
if (is_ios) {
@@ -189,6 +200,7 @@ static_library("browser") {
"//components/signin/core/common",
"//components/strings",
"//components/sync",
+ "//components/ukm",
"//components/variations/net",
"//components/version_info",
"//components/webdata/common",
@@ -225,6 +237,8 @@ static_library("test_support") {
"suggestion_test_helpers.h",
"test_autofill_client.cc",
"test_autofill_client.h",
+ "test_autofill_clock.cc",
+ "test_autofill_clock.h",
"test_autofill_driver.cc",
"test_autofill_driver.h",
"test_autofill_external_delegate.cc",
@@ -250,6 +264,8 @@ static_library("test_support") {
"//components/rappor:test_support",
"//components/signin/core/browser",
"//components/signin/core/common",
+ "//components/ukm",
+ "//components/ukm:test_support",
"//google_apis:test_support",
"//skia",
"//testing/gtest",
@@ -293,6 +309,7 @@ source_set("unit_tests") {
"autofill_data_model_unittest.cc",
"autofill_data_util_unittest.cc",
"autofill_download_manager_unittest.cc",
+ "autofill_driver_factory_unittest.cc",
"autofill_external_delegate_unittest.cc",
"autofill_field_unittest.cc",
"autofill_ie_toolbar_import_win_unittest.cc",
@@ -303,6 +320,7 @@ source_set("unit_tests") {
"autofill_profile_unittest.cc",
"autofill_type_unittest.cc",
"contact_info_unittest.cc",
+ "country_combobox_model_unittest.cc",
"country_names_unittest.cc",
"credit_card_field_unittest.cc",
"credit_card_unittest.cc",
@@ -340,6 +358,7 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/autofill/core/common",
+ "//components/metrics/proto",
"//components/os_crypt",
"//components/os_crypt:test_support",
"//components/prefs:test_support",
@@ -353,7 +372,10 @@ source_set("unit_tests") {
"//components/sync",
"//components/sync:test_support_driver",
"//components/sync:test_support_model",
+ "//components/ukm",
+ "//components/ukm:test_support",
"//components/variations",
+ "//components/variations:test_support",
"//components/webdata/common",
"//components/webdata_services:test_support",
"//google_apis",
diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS
index a72c3d8b45e..54761f260e5 100644
--- a/chromium/components/autofill/core/browser/DEPS
+++ b/chromium/components/autofill/core/browser/DEPS
@@ -1,11 +1,14 @@
include_rules = [
"+components/data_use_measurement/core",
+ "+components/grit/components_scaled_resources.h",
"+components/infobars/core",
"+components/keyed_service/core",
+ "+components/metrics",
"+components/security_state",
"+components/signin/core/browser",
"+components/signin/core/common",
"+components/sync",
+ "+components/ukm",
"+components/variations",
"+components/version_info",
"+components/webdata/common",
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.cc b/chromium/components/autofill/core/browser/autofill_assistant.cc
index 3e463b614bc..02b20bd98bf 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.cc
+++ b/chromium/components/autofill/core/browser/autofill_assistant.cc
@@ -55,8 +55,8 @@ void AutofillAssistant::ShowAssistForCreditCard(const CreditCard& card) {
void AutofillAssistant::OnUserDidAcceptCreditCardFill(const CreditCard& card) {
autofill_manager_->GetOrCreateFullCardRequest()->GetFullCard(
- card, AutofillClient::UNMASK_FOR_AUTOFILL,
- weak_ptr_factory_.GetWeakPtr());
+ card, AutofillClient::UNMASK_FOR_AUTOFILL, weak_ptr_factory_.GetWeakPtr(),
+ autofill_manager_->GetAsFullCardRequestUIDelegate());
}
void AutofillAssistant::OnFullCardRequestSucceeded(const CreditCard& card,
diff --git a/chromium/components/autofill/core/browser/autofill_assistant.h b/chromium/components/autofill/core/browser/autofill_assistant.h
index fb3d4ae2e74..b383faa6ae9 100644
--- a/chromium/components/autofill/core/browser/autofill_assistant.h
+++ b/chromium/components/autofill/core/browser/autofill_assistant.h
@@ -21,10 +21,10 @@ class FormStructure;
// This class encompasses the triggering rules and the logic for the autofill
// assisted filling mechanisms.
-class AutofillAssistant : public payments::FullCardRequest::Delegate {
+class AutofillAssistant : public payments::FullCardRequest::ResultDelegate {
public:
explicit AutofillAssistant(AutofillManager* autofill_manager);
- ~AutofillAssistant();
+ ~AutofillAssistant() override;
// Should be called at every page navigation to clear state.
void Reset();
@@ -43,7 +43,7 @@ class AutofillAssistant : public payments::FullCardRequest::Delegate {
// Called by the infobar delegate when the user accepts the infobar.
void OnUserDidAcceptCreditCardFill(const CreditCard& card);
- // payments::FullCardRequest::Delegate:
+ // payments::FullCardRequest::ResultDelegate:
void OnFullCardRequestSucceeded(const CreditCard& card,
const base::string16& cvc) override;
void OnFullCardRequestFailed() override;
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index 3960f44fdbb..d36f0026ffc 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -36,6 +36,10 @@ namespace syncer {
class SyncService;
}
+namespace ukm {
+class UkmService;
+}
+
namespace autofill {
class AutofillPopupDelegate;
@@ -105,6 +109,9 @@ class AutofillClient {
// Gets the RapporServiceImpl associated with the client (for metrics).
virtual rappor::RapporServiceImpl* GetRapporServiceImpl() = 0;
+ // Gets the UKM service assiciated with this client (for metrics).
+ virtual ukm::UkmService* GetUkmService() = 0;
+
// Causes the Autofill settings UI to be shown.
virtual void ShowAutofillSettings() = 0;
diff --git a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
index c79d465c41d..5f0942c539e 100644
--- a/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
@@ -7,9 +7,9 @@
#include "base/memory/ptr_util.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/grit/components_scaled_resources.h"
#include "components/infobars/core/infobar_delegate.h"
-#include "grit/components_scaled_resources.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/autofill_data_model.cc b/chromium/components/autofill/core/browser/autofill_data_model.cc
index 4f42566bcb5..1d36be4f55c 100644
--- a/chromium/components/autofill/core/browser/autofill_data_model.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_model.cc
@@ -7,6 +7,7 @@
#include <math.h>
#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "url/gurl.h"
namespace autofill {
@@ -16,8 +17,8 @@ AutofillDataModel::AutofillDataModel(const std::string& guid,
: guid_(guid),
origin_(origin),
use_count_(1),
- use_date_(base::Time::Now()),
- modification_date_(base::Time::Now()) {}
+ use_date_(AutofillClock::Now()),
+ modification_date_(AutofillClock::Now()) {}
AutofillDataModel::~AutofillDataModel() {}
bool AutofillDataModel::IsVerified() const {
@@ -27,7 +28,7 @@ bool AutofillDataModel::IsVerified() const {
// TODO(crbug.com/629507): Add support for injected mock clock for testing.
void AutofillDataModel::RecordUse() {
++use_count_;
- use_date_ = base::Time::Now();
+ use_date_ = AutofillClock::Now();
}
bool AutofillDataModel::CompareFrecency(const AutofillDataModel* other,
@@ -50,6 +51,8 @@ double AutofillDataModel::GetFrecencyScore(base::Time time) const {
// of the profile and leveraging the properties of the logarithmic function.
// DaysSinceLastUse() and |use_count_| are offset because their minimum values
// are respectively 0 and 1 but the formula requires at least a value of 2.
+ // Please update getFrecencyScore in PaymentRequestImpl.java as well if below
+ // formula needs update.
return -log((time - use_date_).InDays() + 2) / log(use_count_ + 1);
}
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.cc b/chromium/components/autofill/core/browser/autofill_data_util.cc
index d931d7b0888..f55ec9068c5 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_data_util.cc
@@ -12,6 +12,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/grit/components_scaled_resources.h"
#include "third_party/icu/source/common/unicode/uscript.h"
namespace autofill {
@@ -75,12 +76,12 @@ const char* korean_multi_char_surnames[] = {
// Returns true if |set| contains |element|, modulo a final period.
bool ContainsString(const char* const set[],
size_t set_size,
- const base::string16& element) {
+ base::StringPiece16 element) {
if (!base::IsStringASCII(element))
return false;
- base::string16 trimmed_element;
- base::TrimString(element, base::ASCIIToUTF16("."), &trimmed_element);
+ base::StringPiece16 trimmed_element =
+ base::TrimString(element, base::ASCIIToUTF16("."), base::TRIM_ALL);
for (size_t i = 0; i < set_size; ++i) {
if (base::LowerCaseEqualsASCII(trimmed_element, set[i]))
@@ -91,21 +92,21 @@ bool ContainsString(const char* const set[],
}
// Removes common name prefixes from |name_tokens|.
-void StripPrefixes(std::vector<base::string16>* name_tokens) {
- std::vector<base::string16>::iterator iter = name_tokens->begin();
+void StripPrefixes(std::vector<base::StringPiece16>* name_tokens) {
+ std::vector<base::StringPiece16>::iterator iter = name_tokens->begin();
while (iter != name_tokens->end()) {
if (!ContainsString(name_prefixes, arraysize(name_prefixes), *iter))
break;
++iter;
}
- std::vector<base::string16> copy_vector;
+ std::vector<base::StringPiece16> copy_vector;
copy_vector.assign(iter, name_tokens->end());
*name_tokens = copy_vector;
}
// Removes common name suffixes from |name_tokens|.
-void StripSuffixes(std::vector<base::string16>* name_tokens) {
+void StripSuffixes(std::vector<base::StringPiece16>* name_tokens) {
while (!name_tokens->empty()) {
if (!ContainsString(name_suffixes, arraysize(name_suffixes),
name_tokens->back())) {
@@ -156,7 +157,7 @@ bool IsHangulCharacter(UChar32 c) {
// Returns true if |name| looks like a Korean name, made up entirely of Hangul
// characters or spaces. |name| should already be confirmed to be a CJK name, as
// per |IsCJKName()|.
-bool IsHangulName(const base::string16& name) {
+bool IsHangulName(base::StringPiece16 name) {
for (base::i18n::UTF16CharIterator iter(name.data(), name.length());
!iter.end(); iter.Advance()) {
UChar32 c = iter.get();
@@ -170,7 +171,7 @@ bool IsHangulName(const base::string16& name) {
// Tries to split a Chinese, Japanese, or Korean name into its given name &
// surname parts, and puts the result in |parts|. If splitting did not work for
// whatever reason, returns false.
-bool SplitCJKName(const std::vector<base::string16>& name_tokens,
+bool SplitCJKName(const std::vector<base::StringPiece16>& name_tokens,
NameParts* parts) {
// The convention for CJK languages is to put the surname (last name) first,
// and the given name (first name) second. In a continuous text, there is
@@ -187,7 +188,7 @@ bool SplitCJKName(const std::vector<base::string16>& name_tokens,
// since we don't have a list of Japanese last names. In the Han alphabet,
// it might also be difficult for us to differentiate between Chinese &
// Japanese names.
- const base::string16& name = name_tokens.front();
+ const base::StringPiece16& name = name_tokens.front();
const bool is_korean = IsHangulName(name);
size_t surname_length = 0;
if (is_korean && name.size() > 3) {
@@ -204,15 +205,15 @@ bool SplitCJKName(const std::vector<base::string16>& name_tokens,
1, StartsWithAny(name, common_cjk_multi_char_surnames,
arraysize(common_cjk_multi_char_surnames)));
}
- parts->family = name.substr(0, surname_length);
- parts->given = name.substr(surname_length);
+ parts->family = name.substr(0, surname_length).as_string();
+ parts->given = name.substr(surname_length).as_string();
return true;
}
if (name_tokens.size() == 2) {
// The user entered a space between the two name parts. This makes our job
// easier. Family name first, given name second.
- parts->family = name_tokens[0];
- parts->given = name_tokens[1];
+ parts->family = name_tokens[0].as_string();
+ parts->given = name_tokens[1].as_string();
return true;
}
// We don't know what to do if there are more than 2 tokens.
@@ -221,7 +222,7 @@ bool SplitCJKName(const std::vector<base::string16>& name_tokens,
} // namespace
-bool IsCJKName(const base::string16& name) {
+bool IsCJKName(base::StringPiece16 name) {
// The name is considered to be a CJK name if it is only CJK characters,
// spaces, and "middle dot" separators, with at least one CJK character, and
// no more than 2 words.
@@ -254,7 +255,7 @@ bool IsCJKName(const base::string16& name) {
return word_count > 0 && word_count < 3;
}
-NameParts SplitName(const base::string16& name) {
+NameParts SplitName(base::StringPiece16 name) {
static const base::char16 kWordSeparators[] = {
u' ', // ASCII space.
u',', // ASCII comma.
@@ -263,7 +264,7 @@ NameParts SplitName(const base::string16& name) {
u'\u00B7', // 'MIDDLE DOT' (U+00B7).
u'\0' // End of string.
};
- std::vector<base::string16> name_tokens = base::SplitString(
+ std::vector<base::StringPiece16> name_tokens = base::SplitStringPiece(
name, kWordSeparators, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
StripPrefixes(&name_tokens);
@@ -284,19 +285,19 @@ NameParts SplitName(const base::string16& name) {
if (name_tokens.empty()) {
// Bad things have happened; just assume the whole thing is a given name.
- parts.given = name;
+ parts.given = name.as_string();
return parts;
}
// Only one token, assume given name.
if (name_tokens.size() == 1) {
- parts.given = name_tokens[0];
+ parts.given = name_tokens[0].as_string();
return parts;
}
// 2 or more tokens. Grab the family, which is the last word plus any
// recognizable family prefixes.
- std::vector<base::string16> reverse_family_tokens;
+ std::vector<base::StringPiece16> reverse_family_tokens;
reverse_family_tokens.push_back(name_tokens.back());
name_tokens.pop_back();
while (name_tokens.size() >= 1 &&
@@ -306,14 +307,14 @@ NameParts SplitName(const base::string16& name) {
name_tokens.pop_back();
}
- std::vector<base::string16> family_tokens(reverse_family_tokens.rbegin(),
- reverse_family_tokens.rend());
+ std::vector<base::StringPiece16> family_tokens(reverse_family_tokens.rbegin(),
+ reverse_family_tokens.rend());
parts.family = base::JoinString(family_tokens, base::ASCIIToUTF16(" "));
// Take the last remaining token as the middle name (if there are at least 2
// tokens).
if (name_tokens.size() >= 2) {
- parts.middle = name_tokens.back();
+ parts.middle = name_tokens.back().as_string();
name_tokens.pop_back();
}
@@ -323,11 +324,11 @@ NameParts SplitName(const base::string16& name) {
return parts;
}
-base::string16 JoinNameParts(const base::string16& given,
- const base::string16& middle,
- const base::string16& family) {
+base::string16 JoinNameParts(base::StringPiece16 given,
+ base::StringPiece16 middle,
+ base::StringPiece16 family) {
// First Middle Last
- std::vector<base::string16> full_name;
+ std::vector<base::StringPiece16> full_name;
if (!given.empty())
full_name.push_back(given);
@@ -347,7 +348,7 @@ base::string16 JoinNameParts(const base::string16& given,
return base::JoinString(full_name, base::ASCIIToUTF16(separator));
}
-bool ProfileMatchesFullName(const base::string16 full_name,
+bool ProfileMatchesFullName(base::StringPiece16 full_name,
const autofill::AutofillProfile& profile) {
const base::string16 kSpace = base::ASCIIToUTF16(" ");
const base::string16 kPeriodSpace = base::ASCIIToUTF16(". ");
diff --git a/chromium/components/autofill/core/browser/autofill_data_util.h b/chromium/components/autofill/core/browser/autofill_data_util.h
index d398e476b68..2084c361594 100644
--- a/chromium/components/autofill/core/browser/autofill_data_util.h
+++ b/chromium/components/autofill/core/browser/autofill_data_util.h
@@ -6,8 +6,8 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DATA_UTIL_H_
#include "base/strings/string16.h"
+#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/autofill_profile.h"
-#include "grit/components_scaled_resources.h"
namespace autofill {
namespace data_util {
@@ -28,23 +28,23 @@ struct PaymentRequestData {
// Returns true if |name| looks like a CJK name (or some kind of mish-mash of
// the three, at least).
-bool IsCJKName(const base::string16& name);
+bool IsCJKName(base::StringPiece16 name);
// TODO(crbug.com/586510): Investigate the use of app_locale to do better name
// splitting.
// Returns the different name parts (given, middle and family names) of the full
// |name| passed as a parameter.
-NameParts SplitName(const base::string16& name);
+NameParts SplitName(base::StringPiece16 name);
// Concatenates the name parts together in the correct order (based on script),
// and returns the result.
-base::string16 JoinNameParts(const base::string16& given,
- const base::string16& middle,
- const base::string16& family);
+base::string16 JoinNameParts(base::StringPiece16 given,
+ base::StringPiece16 middle,
+ base::StringPiece16 family);
// Returns true iff |full_name| is a concatenation of some combination of the
// first/middle/last (incl. middle initial) in |profile|.
-bool ProfileMatchesFullName(const base::string16 full_name,
+bool ProfileMatchesFullName(base::StringPiece16 full_name,
const autofill::AutofillProfile& profile);
// Returns the Payment Request API basic card payment spec data for the provided
diff --git a/chromium/components/autofill/core/browser/autofill_driver.h b/chromium/components/autofill/core/browser/autofill_driver.h
index a702eb26a03..e8b95d87a02 100644
--- a/chromium/components/autofill/core/browser/autofill_driver.h
+++ b/chromium/components/autofill/core/browser/autofill_driver.h
@@ -103,6 +103,10 @@ class AutofillDriver {
// Called when the user interacted with a credit card form, so that
// the current page's security state can be updated appropriately.
virtual void DidInteractWithCreditCardForm() = 0;
+
+ // Tells the associated frame that a user gesture was observed somewhere in
+ // the tab (including in a different frame).
+ virtual void NotifyFirstUserGestureObservedInTab() {}
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory.cc b/chromium/components/autofill/core/browser/autofill_driver_factory.cc
new file mode 100644
index 00000000000..224c1efde47
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory.cc
@@ -0,0 +1,58 @@
+// 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_driver_factory.h"
+
+#include "base/callback.h"
+#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_driver.h"
+
+namespace autofill {
+
+AutofillDriverFactory::AutofillDriverFactory(AutofillClient* client)
+ : client_(client) {}
+
+AutofillDriverFactory::~AutofillDriverFactory() {}
+
+AutofillDriver* AutofillDriverFactory::DriverForKey(void* key) {
+ auto mapping = driver_map_.find(key);
+ return mapping == driver_map_.end() ? nullptr : mapping->second.get();
+}
+
+void AutofillDriverFactory::NavigationFinished() {
+ user_gesture_seen_ = false;
+ client_->HideAutofillPopup();
+}
+
+void AutofillDriverFactory::TabHidden() {
+ client_->HideAutofillPopup();
+}
+
+void AutofillDriverFactory::OnFirstUserGestureObserved() {
+ if (user_gesture_seen_)
+ return;
+
+ for (auto& driver : driver_map_)
+ driver.second->NotifyFirstUserGestureObservedInTab();
+
+ user_gesture_seen_ = true;
+}
+
+void AutofillDriverFactory::AddForKey(
+ void* key,
+ base::Callback<std::unique_ptr<AutofillDriver>()> factory_method) {
+ auto insertion_result = driver_map_.insert(std::make_pair(key, nullptr));
+ // This can be called twice for the key representing the main frame.
+ if (insertion_result.second) {
+ insertion_result.first->second = factory_method.Run();
+ if (user_gesture_seen_)
+ insertion_result.first->second->NotifyFirstUserGestureObservedInTab();
+ }
+}
+
+void AutofillDriverFactory::DeleteForKey(void* key) {
+ driver_map_.erase(key);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory.h b/chromium/components/autofill/core/browser/autofill_driver_factory.h
new file mode 100644
index 00000000000..ff48bb67ec3
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory.h
@@ -0,0 +1,71 @@
+// 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 AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
+#define AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
+
+#include <memory>
+#include <unordered_map>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+
+namespace autofill {
+
+class AutofillClient;
+class AutofillDriver;
+
+// Manages the lifetime of AutofillDrivers for a particular AutofillClient by
+// creating, notifying, retrieving and deleting on demand.
+class AutofillDriverFactory {
+ public:
+ explicit AutofillDriverFactory(AutofillClient* client);
+
+ ~AutofillDriverFactory();
+
+ // A convenience function to retrieve an AutofillDriver for the given key or
+ // null if there is none.
+ AutofillDriver* DriverForKey(void* key);
+
+ // Handles finished navigation in any of the frames.
+ void NavigationFinished();
+
+ // Handles hiding of the corresponding tab.
+ void TabHidden();
+
+ // Call this to notify the factory that one of the frames saw a user gesture.
+ // The factory will distribute this information to all drivers when it comes
+ // for the first time since the last main frame navigation to a different
+ // page. It will also notify drivers added later (see AddForKey).
+ void OnFirstUserGestureObserved();
+
+ AutofillClient* client() { return client_; };
+
+ protected:
+ // The API manipulating the drivers map is protected to guarantee subclasses
+ // that nothing else can interfere with the map of drivers.
+
+ // Adds a driver, constructed by calling |factory_method|, for |key|. If there
+ // already is a driver for |key|, |factory_method| is not called. This might
+ // end up notifying the driver that a user gesture has been observed.
+ void AddForKey(
+ void* key,
+ base::Callback<std::unique_ptr<AutofillDriver>()> factory_method);
+
+ // Deletes the AutofillDriver for |key|.
+ void DeleteForKey(void* key);
+
+ private:
+ AutofillClient* const client_;
+
+ std::unordered_map<void*, std::unique_ptr<AutofillDriver>> driver_map_;
+
+ bool user_gesture_seen_ = false; // The state for OnFirstUserGestureObserved.
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillDriverFactory);
+};
+
+} // namespace autofill
+
+#endif // AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
new file mode 100644
index 00000000000..8355161333c
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory_unittest.cc
@@ -0,0 +1,240 @@
+// 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_driver_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "components/autofill/core/browser/test_autofill_client.h"
+#include "components/autofill/core/browser/test_autofill_driver.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+namespace {
+
+class MockAutofillClient : public TestAutofillClient {
+ public:
+ MOCK_METHOD0(HideAutofillPopup, void());
+};
+
+// Just a stub AutofillDriver implementation which announces its construction
+// and desctruction by updating the passed |instance_counter|. It also records
+// when "user gesture observed" was signalled to it.
+class CountingAutofillDriver : public TestAutofillDriver {
+ public:
+ CountingAutofillDriver(int* instance_counter)
+ : instance_counter_(instance_counter) {
+ ++*instance_counter;
+ }
+
+ ~CountingAutofillDriver() override { --*instance_counter_; }
+
+ // Note that EXPECT_CALL cannot be used here, because creation and
+ // notification of the same driver might be done by a single AddForKey call
+ // from the test. Therefore tracking the "gesture_observed" flag is done
+ // explicitly here.
+ void NotifyFirstUserGestureObservedInTab() override {
+ gesture_observed_ = true;
+ }
+
+ bool gesture_observed() { return gesture_observed_; }
+
+ private:
+ int* const instance_counter_;
+ bool gesture_observed_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(CountingAutofillDriver);
+};
+
+// Code-wise this class is identitcal to AutofillDriverFactory, but exposes the
+// protected API to the test. Do not modify any of the methods, only include
+// "using" declarations to make the AutofillDriverFactory methods public.
+class PublicAutofillDriverFactory : public AutofillDriverFactory {
+ public:
+ explicit PublicAutofillDriverFactory(AutofillClient* client)
+ : AutofillDriverFactory(client) {}
+
+ ~PublicAutofillDriverFactory() {}
+
+ using AutofillDriverFactory::AddForKey;
+ using AutofillDriverFactory::DeleteForKey;
+};
+
+// Wrapper around an integer, checking that the integer is 0 on desctruction.
+class CheckedInt {
+ public:
+ CheckedInt() {}
+
+ ~CheckedInt() { EXPECT_EQ(0, val_); }
+
+ int* val() { return &val_; }
+
+ private:
+ int val_ = 0;
+};
+
+} // namespace
+
+class AutofillDriverFactoryTest : public testing::Test {
+ public:
+ AutofillDriverFactoryTest() : factory_(&client_) {}
+
+ ~AutofillDriverFactoryTest() override {}
+
+ // AutofillDriverFactory stores drivers in a map with keys, which are void*
+ // pointers. The factory never dereferences them, so their value does not
+ // matter. This is a handy function to create such pointers from integer
+ // constants.
+ void* KeyFrom(int x) { return reinterpret_cast<void*>(x); }
+
+ // Convenience accessor with a cast to CountingAutofillDriver.
+ CountingAutofillDriver* GetDriver(void* key) {
+ return static_cast<CountingAutofillDriver*>(factory_.DriverForKey(key));
+ }
+
+ std::unique_ptr<AutofillDriver> CreateDriver() {
+ ++drivers_created_;
+ return base::MakeUnique<CountingAutofillDriver>(instance_counter_.val());
+ }
+
+ base::Callback<std::unique_ptr<AutofillDriver>()> CreateDriverCallback() {
+ return base::Bind(&AutofillDriverFactoryTest::CreateDriver,
+ base::Unretained(this));
+ }
+
+ protected:
+ base::MessageLoop message_loop_; // For TestAutofillDriver.
+
+ MockAutofillClient client_;
+
+ CheckedInt instance_counter_;
+
+ PublicAutofillDriverFactory factory_;
+
+ // How many AutofillDriver instances were created with CreateDriver().
+ int drivers_created_ = 0;
+};
+
+TEST_F(AutofillDriverFactoryTest, DriverForKey_NoKey) {
+ EXPECT_FALSE(factory_.DriverForKey(nullptr));
+ EXPECT_FALSE(factory_.DriverForKey(KeyFrom(1)));
+}
+
+TEST_F(AutofillDriverFactoryTest, DriverForKey_OneKey) {
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_FALSE(factory_.DriverForKey(nullptr));
+ EXPECT_TRUE(factory_.DriverForKey(KeyFrom(1)));
+}
+
+TEST_F(AutofillDriverFactoryTest, DriverForKey_TwoKeys) {
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_FALSE(factory_.DriverForKey(nullptr));
+ EXPECT_TRUE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(1, *instance_counter_.val());
+
+ factory_.AddForKey(nullptr, CreateDriverCallback());
+ EXPECT_TRUE(factory_.DriverForKey(nullptr));
+ EXPECT_TRUE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(2, *instance_counter_.val());
+}
+
+TEST_F(AutofillDriverFactoryTest, AddForKey_Duplicated) {
+ EXPECT_FALSE(factory_.DriverForKey(KeyFrom(1)));
+
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_TRUE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(1, drivers_created_);
+ EXPECT_EQ(1, *instance_counter_.val());
+
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_TRUE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(1, drivers_created_);
+ EXPECT_EQ(1, *instance_counter_.val());
+}
+
+TEST_F(AutofillDriverFactoryTest, DeleteForKey) {
+ EXPECT_FALSE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(0, *instance_counter_.val());
+
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_TRUE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(1, *instance_counter_.val());
+
+ factory_.DeleteForKey(KeyFrom(1));
+ EXPECT_FALSE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(0, *instance_counter_.val());
+
+ // Duplicated calls should raise no errors.
+ factory_.DeleteForKey(KeyFrom(1));
+ EXPECT_FALSE(factory_.DriverForKey(KeyFrom(1)));
+ EXPECT_EQ(0, *instance_counter_.val());
+}
+
+TEST_F(AutofillDriverFactoryTest, NavigationFinished) {
+ EXPECT_CALL(client_, HideAutofillPopup());
+ factory_.NavigationFinished();
+}
+
+TEST_F(AutofillDriverFactoryTest, TabHidden) {
+ EXPECT_CALL(client_, HideAutofillPopup());
+ factory_.TabHidden();
+}
+
+// Without calling OnFirstUserGestureObserved on the factory, the factory will
+// not call NotifyFirstUserGestureObservedInTab on a driver.
+TEST_F(AutofillDriverFactoryTest, OnFirstUserGestureObserved_NotCalled) {
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_FALSE(GetDriver(KeyFrom(1))->gesture_observed());
+}
+
+// Call OnFirstUserGestureObserved on the factory with one driver. The factory
+// will call NotifyFirstUserGestureObservedInTab on that driver.
+TEST_F(AutofillDriverFactoryTest, OnFirstUserGestureObserved_CalledOld) {
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ factory_.OnFirstUserGestureObserved();
+ EXPECT_TRUE(GetDriver(KeyFrom(1))->gesture_observed());
+}
+
+// Call OnFirstUserGestureObserved on the factory without drivers. Add a
+// driver. The factory will call NotifyFirstUserGestureObservedInTab on that
+// driver.
+TEST_F(AutofillDriverFactoryTest, OnFirstUserGestureObserved_CalledNew) {
+ factory_.OnFirstUserGestureObserved();
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ EXPECT_TRUE(GetDriver(KeyFrom(1))->gesture_observed());
+}
+
+// Combining the CalledOld and CalledNew test cases into one.
+TEST_F(AutofillDriverFactoryTest, OnFirstUserGestureObserved_MultipleDrivers) {
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ factory_.OnFirstUserGestureObserved();
+ EXPECT_TRUE(GetDriver(KeyFrom(1))->gesture_observed());
+
+ factory_.AddForKey(KeyFrom(7), CreateDriverCallback());
+ EXPECT_TRUE(GetDriver(KeyFrom(7))->gesture_observed());
+}
+
+// Call OnFirstUserGestureObserved on the factory with one driver. Simulate
+// navigation to a different page. Add a driver. The factory will not call
+// NotifyFirstUserGestureObservedInTab on that driver.
+TEST_F(AutofillDriverFactoryTest, OnFirstUserGestureObserved_CalledNavigation) {
+ factory_.AddForKey(KeyFrom(1), CreateDriverCallback());
+ factory_.OnFirstUserGestureObserved();
+ EXPECT_TRUE(GetDriver(KeyFrom(1))->gesture_observed());
+
+ EXPECT_CALL(client_, HideAutofillPopup());
+ factory_.NavigationFinished();
+
+ // Adding a sub-frame
+ factory_.AddForKey(KeyFrom(2), CreateDriverCallback());
+ EXPECT_FALSE(GetDriver(KeyFrom(2))->gesture_observed());
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index 39472262445..b27569f4d8c 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -16,33 +16,36 @@
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
#include "components/sync/driver/sync_service.h"
#include "components/variations/variations_associated_data.h"
#include "google_apis/gaia/gaia_auth_util.h"
-#include "grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
const base::Feature kAutofillCreditCardAssist{
"AutofillCreditCardAssist", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillCreditCardSigninPromo{
- "AutofillCreditCardSigninPromo", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kAutofillScanCardholderName{
"AutofillScanCardholderName", 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 kAutofillUkmLogging{"kAutofillUkmLogging",
+ base::FEATURE_DISABLED_BY_DEFAULT};
const char kCreditCardSigninPromoImpressionLimitParamKey[] = "impression_limit";
const char kAutofillCreditCardPopupBackgroundColorKey[] = "background_color";
const char kAutofillCreditCardPopupDividerColorKey[] = "dropdown_divider_color";
const char kAutofillCreditCardPopupValueBoldKey[] = "is_value_bold";
const char kAutofillCreditCardPopupIsValueAndLabelInSingleLineKey[] =
"is_value_and_label_in_single_line";
-const char kAutofillPopupDropdownItemHeightKey[] =
- "dropdown_item_height";
+const char kAutofillPopupDropdownItemHeightKey[] = "dropdown_item_height";
const char kAutofillCreditCardPopupIsIconAtStartKey[] =
"is_credit_card_icon_at_start";
const char kAutofillPopupMarginKey[] = "margin";
+const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[] =
+ "show_expiration_date";
namespace {
@@ -70,10 +73,6 @@ bool IsInAutofillSuggestionsDisabledExperiment() {
return group_name == "Disabled";
}
-bool IsAutofillCreditCardSigninPromoEnabled() {
- return base::FeatureList::IsEnabled(kAutofillCreditCardSigninPromo);
-}
-
bool IsAutofillCreditCardAssistEnabled() {
#if !defined(OS_ANDROID) && !defined(OS_IOS)
return false;
@@ -82,21 +81,14 @@ bool IsAutofillCreditCardAssistEnabled() {
#endif
}
-int GetCreditCardSigninPromoImpressionLimit() {
- int impression_limit;
- std::string param_value = variations::GetVariationParamValueByFeature(
- kAutofillCreditCardSigninPromo,
- kCreditCardSigninPromoImpressionLimitParamKey);
- if (!param_value.empty() && base::StringToInt(param_value, &impression_limit))
- return impression_limit;
-
- return 0;
-}
-
bool IsAutofillCreditCardPopupLayoutExperimentEnabled() {
return base::FeatureList::IsEnabled(kAutofillCreditCardPopupLayout);
}
+bool IsAutofillCreditCardLastUsedDateDisplayExperimentEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillCreditCardLastUsedDateDisplay);
+}
+
// |GetCreditCardPopupParameterUintValue| returns 0 if experiment parameter is
// not specified. 0 == |SK_ColorTRANSPARENT|.
SkColor GetCreditCardPopupBackgroundColor() {
@@ -126,6 +118,13 @@ bool IsIconInCreditCardPopupAtStart() {
return param_value == "true";
}
+bool ShowExpirationDateInAutofillCreditCardLastUsedDate() {
+ const std::string param_value = variations::GetVariationParamValueByFeature(
+ kAutofillCreditCardLastUsedDateDisplay,
+ kAutofillCreditCardLastUsedDateShowExpirationDateKey);
+ return param_value == "true";
+}
+
// Modifies |suggestion| as follows if experiment to display value and label in
// a single line is enabled.
// Say, |value| is 'Visa ....1111' and |label| is '01/18' (expiration date).
@@ -226,4 +225,8 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
return !group_name.empty() && group_name != "Disabled";
}
+bool IsUkmLoggingEnabled() {
+ return base::FeatureList::IsEnabled(kAutofillUkmLogging);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.h b/chromium/components/autofill/core/browser/autofill_experiments.h
index 4467e38d9b3..70c3f411c60 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.h
+++ b/chromium/components/autofill/core/browser/autofill_experiments.h
@@ -25,11 +25,13 @@ namespace autofill {
struct Suggestion;
extern const base::Feature kAutofillCreditCardAssist;
-extern const base::Feature kAutofillCreditCardSigninPromo;
extern const base::Feature kAutofillScanCardholderName;
extern const base::Feature kAutofillCreditCardPopupLayout;
+extern const base::Feature kAutofillCreditCardLastUsedDateDisplay;
+extern const base::Feature kAutofillUkmLogging;
extern const char kCreditCardSigninPromoImpressionLimitParamKey[];
extern const char kAutofillCreditCardPopupSettingsSuggestionValueKey[];
+extern const char kAutofillCreditCardLastUsedDateShowExpirationDateKey[];
// Returns true if autofill should be enabled. See also
// IsInAutofillSuggestionsDisabledExperiment below.
@@ -41,16 +43,9 @@ bool IsAutofillEnabled(const PrefService* pref_service);
// disables providing suggestions.
bool IsInAutofillSuggestionsDisabledExperiment();
-// Returns whether the Autofill credit card signin promo should be shown.
-bool IsAutofillCreditCardSigninPromoEnabled();
-
// Returns whether the Autofill credit card assist infobar should be shown.
bool IsAutofillCreditCardAssistEnabled();
-// Returns the maximum number of impressions of the credit card signin promo, or
-// 0 if there are no limits.
-int GetCreditCardSigninPromoImpressionLimit();
-
// Returns true if the user should be offered to locally store unmasked cards.
// This controls whether the option is presented at all rather than the default
// response of the option.
@@ -67,6 +62,13 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
// enabled.
bool IsAutofillCreditCardPopupLayoutExperimentEnabled();
+// Returns whether Autofill credit card last used date display experiment is
+// enabled.
+bool IsAutofillCreditCardLastUsedDateDisplayExperimentEnabled();
+
+// Returns whether Autofill credit card last used date shows expiration date.
+bool ShowExpirationDateInAutofillCreditCardLastUsedDate();
+
// Returns the background color for credit card autofill popup, or
// |SK_ColorTRANSPARENT| if the new credit card autofill popup layout experiment
// is not enabled.
@@ -99,6 +101,9 @@ void ModifyAutofillCreditCardSuggestion(struct Suggestion* suggestion);
// layout.
unsigned int GetPopupMargin();
+// Returns whether the feature to log UKMs is enabled.
+bool IsUkmLoggingEnabled();
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_EXPERIMENTS_H_
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index e80c8ac5461..5853a8de1d7 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -24,7 +24,7 @@
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/common/autofill_util.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/autofill_field.cc b/chromium/components/autofill/core/browser/autofill_field.cc
index bf57caec2f6..3704b10fd12 100644
--- a/chromium/components/autofill/core/browser/autofill_field.cc
+++ b/chromium/components/autofill/core/browser/autofill_field.cc
@@ -25,7 +25,7 @@
#include "components/autofill/core/common/autofill_l10n_util.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index 977e67ae874..056793fe09b 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -51,6 +51,7 @@
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_data_validation.h"
#include "components/autofill/core/common/autofill_pref_names.h"
@@ -64,8 +65,8 @@
#include "components/rappor/public/rappor_utils.h"
#include "components/rappor/rappor_service_impl.h"
#include "components/security_state/core/security_state.h"
+#include "components/strings/grit/components_strings.h"
#include "google_apis/gaia/identity_provider.h"
-#include "grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -79,6 +80,8 @@ namespace autofill {
using base::StartsWith;
using base::TimeTicks;
+const int kCreditCardSigninPromoImpressionLimit = 3;
+
namespace {
const size_t kMaxRecentFormSignaturesToRemember = 3;
@@ -306,6 +309,9 @@ bool AutofillManager::ShouldShowScanCreditCard(const FormData& form,
if (!is_card_number_field && !is_scannable_name_on_card_field)
return false;
+ if (IsFormNonSecure(form))
+ return false;
+
static const int kShowScanCreditCardMaxValueLength = 6;
return field.value.size() <= kShowScanCreditCardMaxValueLength;
}
@@ -319,9 +325,6 @@ bool AutofillManager::IsCreditCardPopup(const FormData& form,
bool AutofillManager::ShouldShowCreditCardSigninPromo(
const FormData& form,
const FormFieldData& field) {
- if (!IsAutofillCreditCardSigninPromoEnabled())
- return false;
-
// Check whether we are dealing with a credit card field and whether it's
// appropriate to show the promo (e.g. the platform is supported).
AutofillField* autofill_field = GetAutofillField(form, field);
@@ -329,12 +332,13 @@ bool AutofillManager::ShouldShowCreditCardSigninPromo(
!client_->ShouldShowSigninPromo())
return false;
- // The last step is checking if we are under the limit of impressions (a limit
- // of 0 means there is no limit);
- int impression_limit = GetCreditCardSigninPromoImpressionLimit();
+ if (IsFormNonSecure(form))
+ return false;
+
+ // The last step is checking if we are under the limit of impressions.
int impression_count = client_->GetPrefs()->GetInteger(
prefs::kAutofillCreditCardSigninPromoImpressionCount);
- if (impression_limit == 0 || impression_count < impression_limit) {
+ if (impression_count < kCreditCardSigninPromoImpressionLimit) {
// The promo will be shown. Increment the impression count.
client_->GetPrefs()->SetInteger(
prefs::kAutofillCreditCardSigninPromoImpressionCount,
@@ -529,6 +533,11 @@ void AutofillManager::OnTextFieldDidChange(const FormData& form,
UpdateInitialInteractionTimestamp(timestamp);
}
+bool AutofillManager::IsFormNonSecure(const FormData& form) const {
+ return !client_->IsContextSecure() ||
+ (form.action.is_valid() && form.action.SchemeIs("http"));
+}
+
void AutofillManager::OnQueryFormFieldAutofill(int query_id,
const FormData& form,
const FormFieldData& field,
@@ -538,6 +547,7 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
gfx::RectF transformed_box =
driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
+
external_delegate_->OnQuery(query_id, form, field, transformed_box);
// Need to refresh models before using the form_event_loggers.
@@ -564,14 +574,14 @@ void AutofillManager::OnQueryFormFieldAutofill(int query_id,
}
std::vector<Suggestion> suggestions;
- const bool is_context_secure =
- !form_structure ||
- (client_->IsContextSecure() &&
- (!form_structure->target_url().is_valid() ||
- !form_structure->target_url().SchemeIs("http")));
+ const bool is_context_secure = !IsFormNonSecure(form);
const bool is_http_warning_enabled =
security_state::IsHttpWarningInFormEnabled();
+ // TODO(rogerm): Early exit here on !driver_->RendererIsAvailable()?
+ // We skip populating autofill data, but might generate warnings and or
+ // signin promo to show over the unavailable renderer. That seems a mistake.
+
if (is_autofill_possible &&
driver_->RendererIsAvailable() &&
got_autofillable_form) {
@@ -723,7 +733,7 @@ void AutofillManager::FillOrPreviewCreditCardForm(
masked_card_ = credit_card;
GetOrCreateFullCardRequest()->GetFullCard(
masked_card_, AutofillClient::UNMASK_FOR_AUTOFILL,
- weak_ptr_factory_.GetWeakPtr());
+ weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr());
credit_card_form_event_logger_->OnDidSelectMaskedServerCardSuggestion();
return;
}
@@ -1029,6 +1039,7 @@ void AutofillManager::OnDidGetUploadDetails(
weak_ptr_factory_.GetWeakPtr()));
AutofillMetrics::LogCardUploadDecisionMetric(
AutofillMetrics::UPLOAD_OFFERED);
+ LogCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
} else {
// If the upload details request failed, fall back to a local save. The
// reasoning here is as follows:
@@ -1048,7 +1059,10 @@ void AutofillManager::OnDidGetUploadDetails(
base::Unretained(personal_data_), upload_request_.card));
AutofillMetrics::LogCardUploadDecisionMetric(
AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED);
+ LogCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED);
}
+ pending_upload_request_url_ = GURL();
}
void AutofillManager::OnDidUploadCard(
@@ -1069,6 +1083,18 @@ void AutofillManager::OnFullCardRequestFailed() {
driver_->RendererShouldClearPreviewedForm();
}
+void AutofillManager::ShowUnmaskPrompt(
+ const CreditCard& card,
+ AutofillClient::UnmaskCardReason reason,
+ base::WeakPtr<CardUnmaskDelegate> delegate) {
+ client_->ShowUnmaskPrompt(card, reason, delegate);
+}
+
+void AutofillManager::OnUnmaskVerificationResult(
+ AutofillClient::PaymentsRpcResult result) {
+ client_->OnUnmaskVerificationResult(result);
+}
+
void AutofillManager::OnUserDidAcceptUpload() {
user_did_accept_upload_prompt_ = true;
if (!upload_request_.risk_data.empty()) {
@@ -1165,6 +1191,13 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
upload_request_ = payments::PaymentsClient::UploadRequestDetails();
upload_request_.card = *imported_credit_card;
+ // In order to prompt the user to upload their card, we must have both:
+ // 1) Card with CVC
+ // 2) 1+ recently-used or modified addresses that meet the client-side
+ // validation rules
+ // Here we perform both checks before returning or logging anything,
+ // because if only one of the two is missing, it may be fixable.
+
// Check for a CVC to determine whether we can prompt the user to upload
// their card. If no CVC is present, do nothing. We could fall back to a
// local save but we believe that sometimes offering upload and sometimes
@@ -1177,19 +1210,40 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
break;
}
}
+
+ // Upload requires that recently used or modified addresses meet the
+ // client-side validation rules.
+ autofill::AutofillMetrics::CardUploadDecisionMetric
+ get_profiles_decision_metric = AutofillMetrics::UPLOAD_OFFERED;
+ std::string rappor_metric_name;
+ bool get_profiles_succeeded =
+ GetProfilesForCreditCardUpload(*imported_credit_card,
+ &upload_request_.profiles,
+ &get_profiles_decision_metric,
+ &rappor_metric_name);
+
+ pending_upload_request_url_ = GURL(submitted_form.source_url());
+
+ // Both the CVC and address checks are done. Conform to the legacy order of
+ // reporting on CVC then address.
if (upload_request_.cvc.empty()) {
AutofillMetrics::LogCardUploadDecisionMetric(
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC);
+ LogCardUploadDecisionUkm(AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC);
+ pending_upload_request_url_ = GURL();
CollectRapportSample(submitted_form.source_url(),
"Autofill.CardUploadNotOfferedNoCvc");
return;
}
-
- // Upload also requires recently used or modified addresses that meet the
- // client-side validation rules.
- if (!GetProfilesForCreditCardUpload(*imported_credit_card,
- &upload_request_.profiles,
- submitted_form.source_url())) {
+ if (!get_profiles_succeeded) {
+ DCHECK(get_profiles_decision_metric != AutofillMetrics::UPLOAD_OFFERED);
+ AutofillMetrics::LogCardUploadDecisionMetric(
+ get_profiles_decision_metric);
+ LogCardUploadDecisionUkm(get_profiles_decision_metric);
+ pending_upload_request_url_ = GURL();
+ if (!rappor_metric_name.empty()) {
+ CollectRapportSample(submitted_form.source_url(), rappor_metric_name);
+ }
return;
}
@@ -1201,9 +1255,11 @@ void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
bool AutofillManager::GetProfilesForCreditCardUpload(
const CreditCard& card,
std::vector<AutofillProfile>* profiles,
- const GURL& source_url) const {
+ autofill::AutofillMetrics::CardUploadDecisionMetric*
+ address_upload_decision_metric,
+ std::string* rappor_metric_name) const {
std::vector<AutofillProfile> candidate_profiles;
- const base::Time now = base::Time::Now();
+ const base::Time now = AutofillClock::Now();
const base::TimeDelta fifteen_minutes = base::TimeDelta::FromMinutes(15);
// First, collect all of the addresses used recently.
@@ -1214,9 +1270,9 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
}
}
if (candidate_profiles.empty()) {
- AutofillMetrics::LogCardUploadDecisionMetric(
- AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ADDRESS);
- CollectRapportSample(source_url, "Autofill.CardUploadNotOfferedNoAddress");
+ *address_upload_decision_metric =
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ADDRESS;
+ *rappor_metric_name = "Autofill.CardUploadNotOfferedNoAddress";
return false;
}
@@ -1244,10 +1300,9 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
// countries, we'll need to make the name comparison more sophisticated.
if (!base::EqualsCaseInsensitiveASCII(
verified_name, RemoveMiddleInitial(address_name))) {
- AutofillMetrics::LogCardUploadDecisionMetric(
- AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES);
- CollectRapportSample(source_url,
- "Autofill.CardUploadNotOfferedConflictingNames");
+ *address_upload_decision_metric =
+ AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES;
+ *rappor_metric_name = "Autofill.CardUploadNotOfferedConflictingNames";
return false;
}
}
@@ -1256,9 +1311,9 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
// If neither the card nor any of the addresses have a name associated with
// them, the candidate set is invalid.
if (verified_name.empty()) {
- AutofillMetrics::LogCardUploadDecisionMetric(
- AutofillMetrics::UPLOAD_NOT_OFFERED_NO_NAME);
- CollectRapportSample(source_url, "Autofill.CardUploadNotOfferedNoName");
+ *address_upload_decision_metric =
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_NAME;
+ *rappor_metric_name = "Autofill.CardUploadNotOfferedNoName";
return false;
}
@@ -1284,8 +1339,8 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
// likely to fail.
if (!(StartsWith(verified_zip, zip, base::CompareCase::SENSITIVE) ||
StartsWith(zip, verified_zip, base::CompareCase::SENSITIVE))) {
- AutofillMetrics::LogCardUploadDecisionMetric(
- AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS);
+ *address_upload_decision_metric =
+ AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS;
return false;
}
}
@@ -1295,8 +1350,8 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
// If none of the candidate addresses have a zip, the candidate set is
// invalid.
if (verified_zip.empty()) {
- AutofillMetrics::LogCardUploadDecisionMetric(
- AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE);
+ *address_upload_decision_metric =
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE;
return false;
}
@@ -1305,7 +1360,8 @@ bool AutofillManager::GetProfilesForCreditCardUpload(
}
void AutofillManager::CollectRapportSample(const GURL& source_url,
- const char* metric_name) const {
+ const std::string& metric_name)
+ const {
if (source_url.is_valid() && client_->GetRapporServiceImpl()) {
rappor::SampleDomainAndRegistryFromGURL(client_->GetRapporServiceImpl(),
metric_name, source_url);
@@ -1573,7 +1629,7 @@ void AutofillManager::FillOrPreviewDataModelForm(
} else if (is_credit_card && IsCreditCardExpirationType(
cached_field->Type().GetStorableType()) &&
static_cast<const CreditCard*>(&data_model)
- ->IsExpired(base::Time::Now())) {
+ ->IsExpired(AutofillClock::Now())) {
// Don't fill expired cards expiration date.
value = base::string16();
}
@@ -1871,7 +1927,7 @@ void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
personal_data_->GetCreditCardsToSuggest();
// Expired cards are last in the sorted order, so if the first one is
// expired, they all are.
- if (!cards.empty() && !cards.front()->IsExpired(base::Time::Now()))
+ if (!cards.empty() && !cards.front()->IsExpired(AutofillClock::Now()))
autofill_assistant_.ShowAssistForCreditCard(*cards.front());
}
#endif
@@ -2151,4 +2207,10 @@ void AutofillManager::DumpAutofillData(bool imported_cc) const {
}
#endif // ENABLE_FORM_DEBUG_DUMP
+void AutofillManager::LogCardUploadDecisionUkm(
+ AutofillMetrics::CardUploadDecisionMetric upload_decision) {
+ AutofillMetrics::LogCardUploadDecisionUkm(
+ client_->GetUkmService(), pending_upload_request_url_, upload_decision);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index ce8608f03db..290126ec108 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -43,6 +43,8 @@
#define ENABLE_FORM_DEBUG_DUMP
#endif
+class GURL;
+
namespace gfx {
class RectF;
}
@@ -67,11 +69,15 @@ class FormStructureBrowserTest;
struct FormData;
struct FormFieldData;
+// We show the credit card signin promo only a certain number of times.
+extern const int kCreditCardSigninPromoImpressionLimit;
+
// Manages saving and restoring the user's personal information entered into web
// forms. One per frame; owned by the AutofillDriver.
class AutofillManager : public AutofillDownloadManager::Observer,
public payments::PaymentsClientDelegate,
- public payments::FullCardRequest::Delegate {
+ public payments::FullCardRequest::ResultDelegate,
+ public payments::FullCardRequest::UIDelegate {
public:
enum AutofillDownloadManagerState {
ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
@@ -153,6 +159,11 @@ class AutofillManager : public AutofillDownloadManager::Observer,
payments::FullCardRequest* GetOrCreateFullCardRequest();
+ base::WeakPtr<payments::FullCardRequest::UIDelegate>
+ GetAsFullCardRequestUIDelegate() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
const std::string& app_locale() const { return app_locale_; }
// Only for testing.
@@ -290,11 +301,18 @@ class AutofillManager : public AutofillDownloadManager::Observer,
std::unique_ptr<base::DictionaryValue> legal_message) override;
void OnDidUploadCard(AutofillClient::PaymentsRpcResult result) override;
- // FullCardRequest::Delegate:
+ // payments::FullCardRequest::ResultDelegate:
void OnFullCardRequestSucceeded(const CreditCard& card,
const base::string16& cvc) override;
void OnFullCardRequestFailed() override;
+ // payments::FullCardRequest::UIDelegate:
+ void ShowUnmaskPrompt(const CreditCard& card,
+ AutofillClient::UnmaskCardReason reason,
+ base::WeakPtr<CardUnmaskDelegate> delegate) override;
+ void OnUnmaskVerificationResult(
+ AutofillClient::PaymentsRpcResult result) override;
+
// Sets |user_did_accept_upload_prompt_| and calls UploadCard if the risk data
// is available.
void OnUserDidAcceptUpload();
@@ -401,15 +419,19 @@ class AutofillManager : public AutofillDownloadManager::Observer,
// Logs |metric_name| with RAPPOR, for the specific form |source_url|.
void CollectRapportSample(const GURL& source_url,
- const char* metric_name) const;
+ const std::string& metric_name) const;
// Examines |card| and the stored profiles and if a candidate set of profiles
// is found that matches the client-side validation rules, assigns the values
- // to |profiles|. |source_url| is the source URL for the form. If no valid set
- // can be found, returns false.
+ // to |profiles|. If no valid set can be found, returns false, assigns the
+ // failure reason to |address_upload_decision_metric|, and if applicable, the
+ // RAPPOR metric to log to |rappor_metric_name|.
bool GetProfilesForCreditCardUpload(const CreditCard& card,
std::vector<AutofillProfile>* profiles,
- const GURL& source_url) const;
+ autofill::AutofillMetrics::
+ CardUploadDecisionMetric*
+ address_upload_decision_metric,
+ std::string* rappor_metric_name) const;
// If |initial_interaction_timestamp_| is unset or is set to a later time than
// |interaction_timestamp|, updates the cached timestamp. The latter check is
@@ -417,6 +439,10 @@ class AutofillManager : public AutofillDownloadManager::Observer,
void UpdateInitialInteractionTimestamp(
const base::TimeTicks& interaction_timestamp);
+ // Examines |form| and returns true if it is in a non-secure context or
+ // its action attribute targets a HTTP url.
+ bool IsFormNonSecure(const FormData& form) const;
+
// Uses the existing personal data in |profiles| and |credit_cards| to
// determine possible field types for the |submitted_form|. This is
// potentially expensive -- on the order of 50ms even for a small set of
@@ -451,6 +477,10 @@ class AutofillManager : public AutofillDownloadManager::Observer,
void DumpAutofillData(bool imported_cc) const;
#endif
+ // Logs the card upload decision UKM.
+ void LogCardUploadDecisionUkm(
+ AutofillMetrics::CardUploadDecisionMetric upload_decision);
+
// Provides driver-level context to the shared code of the component. Must
// outlive this object.
AutofillDriver* driver_;
@@ -521,6 +551,7 @@ class AutofillManager : public AutofillDownloadManager::Observer,
// Collected information about a pending upload request.
payments::PaymentsClient::UploadRequestDetails upload_request_;
bool user_did_accept_upload_prompt_;
+ GURL pending_upload_request_url_;
#ifdef ENABLE_FORM_DEBUG_DUMP
// The last few autofilled forms (key/value pairs) submitted, for debugging.
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
index 38264eda18c..54643c65a6a 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -18,6 +18,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/metrics/field_trial.h"
+#include "base/metrics/metrics_hashes.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
@@ -47,11 +48,15 @@
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
+#include "components/metrics/proto/ukm/entry.pb.h"
#include "components/prefs/pref_service.h"
#include "components/rappor/test_rappor_service.h"
#include "components/security_state/core/security_state.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/ukm/test_ukm_service.h"
+#include "components/ukm/ukm_entry.h"
+#include "components/ukm/ukm_source.h"
#include "components/variations/variations_associated_data.h"
-#include "grit/components_strings.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -774,6 +779,17 @@ class TestAutofillExternalDelegate : public AutofillExternalDelegate {
DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate);
};
+// Finds the specified UKM metric by |name| in the specified UKM |metrics|.
+const ukm::Entry_Metric* FindMetric(
+ const char* name,
+ const google::protobuf::RepeatedPtrField<ukm::Entry_Metric>& metrics) {
+ for (const auto& metric : metrics) {
+ if (metric.metric_hash() == base::HashMetricName(name))
+ return &metric;
+ }
+ return nullptr;
+}
+
} // namespace
class AutofillManagerTest : public testing::Test {
@@ -817,32 +833,6 @@ class AutofillManagerTest : public testing::Test {
request_context_ = nullptr;
}
- void EnableCreditCardSigninPromoFeatureWithLimit(int impression_limit) {
- const std::string kTrialName = "MyTrial";
- const std::string kGroupName = "Group1";
-
- scoped_refptr<base::FieldTrial> trial(
- base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName));
- std::map<std::string, std::string> params;
- params[kCreditCardSigninPromoImpressionLimitParamKey] =
- base::IntToString(impression_limit);
- ASSERT_TRUE(
- variations::AssociateVariationParams(kTrialName, kGroupName, params));
-
- // Enable the feature.
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->RegisterFieldTrialOverride(
- kAutofillCreditCardSigninPromo.name,
- base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
- scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
-
- // Double-checking our params made it.
- std::map<std::string, std::string> actualParams;
- EXPECT_TRUE(variations::GetVariationParamsByFeature(
- kAutofillCreditCardSigninPromo, &actualParams));
- EXPECT_EQ(params, actualParams);
- }
-
void GetAutofillSuggestions(int query_id,
const FormData& form,
const FormFieldData& field) {
@@ -1024,6 +1014,39 @@ class AutofillManagerTest : public testing::Test {
security_state::kHttpFormWarningFeature);
}
+ void EnableUkmLogging() {
+ scoped_feature_list_.InitAndEnableFeature(kAutofillUkmLogging);
+ }
+
+ void ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::CardUploadDecisionMetric upload_decision) {
+ ukm::TestUkmService* ukm_service = autofill_client_.GetTestUkmService();
+
+ // Check that one source is logged.
+ ASSERT_EQ(1U, ukm_service->sources_count());
+ const ukm::UkmSource* source = ukm_service->GetSource(0);
+
+ // Check that one entry is logged.
+ EXPECT_EQ(1U, ukm_service->entries_count());
+ const ukm::UkmEntry* entry = ukm_service->GetEntry(0);
+ EXPECT_EQ(source->id(), entry->source_id());
+
+ ukm::Entry entry_proto;
+ entry->PopulateProto(&entry_proto);
+ EXPECT_EQ(source->id(), entry_proto.source_id());
+
+ // Check if there is an entry for card upload decisions.
+ EXPECT_EQ(base::HashMetricName(internal::kUKMCardUploadDecisionEntryName),
+ entry_proto.event_hash());
+ EXPECT_EQ(1, entry_proto.metrics_size());
+
+ // Check that the expected upload decision is logged.
+ const ukm::Entry_Metric* metric = FindMetric(
+ internal::kUKMCardUploadDecisionMetricName, entry_proto.metrics());
+ ASSERT_NE(nullptr, metric);
+ EXPECT_EQ(static_cast<int>(upload_decision), metric->value());
+ }
+
protected:
base::MessageLoop message_loop_;
MockAutofillClient autofill_client_;
@@ -1690,9 +1713,6 @@ TEST_F(AutofillManagerTest,
// are no credit card suggestions and the promo is active. See the tests in
// AutofillExternalDelegateTest that test whether the promo is added.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_OnlySigninPromo) {
- // Enable the signin promo feature with no impression limit.
- EnableCreditCardSigninPromoFeatureWithLimit(0);
-
// Make sure there are no credit cards.
personal_data_.ClearCreditCards();
@@ -4497,6 +4517,7 @@ TEST_F(AutofillManagerTest, FillInUpdatedExpirationDate) {
#define MAYBE_UploadCreditCard UploadCreditCard
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4528,6 +4549,8 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard) {
// Verify that the correct histogram entry (and only that) was logged.
histogram_tester.ExpectUniqueSample("Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_OFFERED, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
@@ -4578,6 +4601,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_FeatureNotEnabled) {
#define MAYBE_UploadCreditCard_CvcUnavailable UploadCreditCard_CvcUnavailable
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcUnavailable) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4612,6 +4636,8 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcUnavailable) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC);
rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
@@ -4631,6 +4657,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcUnavailable) {
#define MAYBE_UploadCreditCard_CvcInvalidLength UploadCreditCard_CvcInvalidLength
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcInvalidLength) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4665,6 +4692,8 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcInvalidLength) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC);
rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
@@ -4684,6 +4713,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_CvcInvalidLength) {
#define MAYBE_UploadCreditCard_MultipleCvcFields UploadCreditCard_MultipleCvcFields
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_MultipleCvcFields) {
+ EnableUkmLogging();
autofill_manager_->set_credit_card_upload_enabled(true);
// Remove the profiles that were created in the TestPersonalDataManager
@@ -4740,6 +4770,8 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_MultipleCvcFields) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_OFFERED, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
@@ -4749,6 +4781,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_MultipleCvcFields) {
#define MAYBE_UploadCreditCard_NoProfileAvailable UploadCreditCard_NoProfileAvailable
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoProfileAvailable) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4777,6 +4810,9 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoProfileAvailable) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ADDRESS, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ADDRESS);
rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
@@ -4791,11 +4827,65 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoProfileAvailable) {
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
#if defined(OS_ANDROID)
+#define MAYBE_UploadCreditCard_CvcUnavailableAndNoProfileAvailable DISABLED_UploadCreditCard_CvcUnavailableAndNoProfileAvailable
+#else
+#define MAYBE_UploadCreditCard_CvcUnavailableAndNoProfileAvailable UploadCreditCard_CvcUnavailableAndNoProfileAvailable
+#endif
+TEST_F(AutofillManagerTest,
+ MAYBE_UploadCreditCard_CvcUnavailableAndNoProfileAvailable) {
+ EnableUkmLogging();
+ personal_data_.ClearAutofillProfiles();
+ autofill_manager_->set_credit_card_upload_enabled(true);
+
+ // Don't fill or submit an 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(""); // CVC MISSING
+
+ base::HistogramTester histogram_tester;
+
+ // Neither a local save nor an upload should happen in this case.
+ // Note that AutofillManager should *check* for both no CVC and no address
+ // profile, but the no CVC case should have priority over being reported.
+ 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.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.CardUploadDecisionExpanded",
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_NOT_OFFERED_NO_CVC);
+
+ rappor::TestRapporServiceImpl* rappor_service =
+ autofill_client_.test_rappor_service();
+ EXPECT_EQ(1, rappor_service->GetReportsCount());
+ std::string sample;
+ rappor::RapporType type;
+ EXPECT_TRUE(rappor_service->GetRecordedSampleForMetric(
+ "Autofill.CardUploadNotOfferedNoCvc", &sample, &type));
+ EXPECT_EQ("myform.com", sample);
+ EXPECT_EQ(rappor::ETLD_PLUS_ONE_RAPPOR_TYPE, type);
+}
+
+// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
+#if defined(OS_ANDROID)
#define MAYBE_UploadCreditCard_NoNameAvailable DISABLED_UploadCreditCard_NoNameAvailable
#else
#define MAYBE_UploadCreditCard_NoNameAvailable UploadCreditCard_NoNameAvailable
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoNameAvailable) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4830,6 +4920,9 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoNameAvailable) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_NAME, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_NAME);
rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
@@ -4849,6 +4942,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoNameAvailable) {
#define MAYBE_UploadCreditCard_ZipCodesConflict UploadCreditCard_ZipCodesConflict
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesConflict) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4891,6 +4985,9 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesConflict) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS);
}
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
@@ -4900,6 +4997,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesConflict) {
#define MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch UploadCreditCard_ZipCodesHavePrefixMatch
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4942,6 +5040,8 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_OFFERED, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
@@ -4951,6 +5051,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_ZipCodesHavePrefixMatch) {
#define MAYBE_UploadCreditCard_NoZipCodeAvailable UploadCreditCard_NoZipCodeAvailable
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoZipCodeAvailable) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -4992,6 +5093,9 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoZipCodeAvailable) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE);
}
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
@@ -5001,6 +5105,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NoZipCodeAvailable) {
#define MAYBE_UploadCreditCard_NamesMatchLoosely UploadCreditCard_NamesMatchLoosely
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesMatchLoosely) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -5046,6 +5151,8 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesMatchLoosely) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_OFFERED, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(AutofillMetrics::UPLOAD_OFFERED);
}
// TODO(crbug.com/666704): Flaky on android_n5x_swarming_rel bot.
@@ -5055,6 +5162,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesMatchLoosely) {
#define MAYBE_UploadCreditCard_NamesHaveToMatch UploadCreditCard_NamesHaveToMatch
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesHaveToMatch) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -5097,6 +5205,9 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesHaveToMatch) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES);
rappor::TestRapporServiceImpl* rappor_service =
autofill_client_.test_rappor_service();
@@ -5116,6 +5227,7 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_NamesHaveToMatch) {
#define MAYBE_UploadCreditCard_UploadDetailsFails UploadCreditCard_UploadDetailsFails
#endif
TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_UploadDetailsFails) {
+ EnableUkmLogging();
personal_data_.ClearAutofillProfiles();
autofill_manager_->set_credit_card_upload_enabled(true);
@@ -5154,6 +5266,9 @@ TEST_F(AutofillManagerTest, MAYBE_UploadCreditCard_UploadDetailsFails) {
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadDecisionExpanded",
AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED, 1);
+ // Verify that the correct UKM was logged.
+ ExpectUniqueCardUploadDecisionUkm(
+ AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED);
}
// Verify that typing "gmail" will match "theking@gmail.com" and
@@ -5271,11 +5386,12 @@ TEST_F(AutofillManagerTest, NoCreditCardSuggestionsForNonPrefixTokenMatch) {
}
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
-// card form, with no impression limit and the feature enabled.
+// card form with an impression limit of three and no impressions yet.
TEST_F(AutofillManagerTest,
- ShouldShowCreditCardSigninPromo_CreditCardField_NoLimit) {
- // Enable the feature with no impression limit.
- EnableCreditCardSigninPromoFeatureWithLimit(0);
+ ShouldShowCreditCardSigninPromo_CreditCardField_UnmetLimit) {
+ // No impressions yet.
+ ASSERT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount));
// Set up our form data.
FormData form;
@@ -5286,21 +5402,29 @@ TEST_F(AutofillManagerTest,
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
- // The result will depend on what ShouldShowSigninPromo(). We control its
- // output and verify that both cases behave as expected.
+ // The mock implementation of ShouldShowSigninPromo() will return true here,
+ // creating an impression, and false below, preventing an impression.
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(true));
EXPECT_TRUE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ // Expect to now have an impression.
+ EXPECT_EQ(1, autofill_client_.GetPrefs()->GetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount));
+
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(false));
EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+
+ // No additional impression.
+ EXPECT_EQ(1, autofill_client_.GetPrefs()->GetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount));
}
-// Test that ShouldShowCreditCardSigninPromo doesn't show for a credit card form
-// when the feature is off.
+// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
+// card form with an impression limit that has been attained already.
TEST_F(AutofillManagerTest,
- ShouldShowCreditCardSigninPromo_CreditCardField_FeatureOff) {
+ ShouldShowCreditCardSigninPromo_CreditCardField_WithAttainedLimit) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
@@ -5310,69 +5434,73 @@ TEST_F(AutofillManagerTest,
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
- // Returns false without calling ShouldShowSigninPromo().
- EXPECT_CALL(autofill_client_, ShouldShowSigninPromo()).Times(0);
+ // Set the impression count to the same value as the limit.
+ autofill_client_.GetPrefs()->SetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount,
+ kCreditCardSigninPromoImpressionLimit);
+
+ // Both calls will now return false, regardless of the mock implementation of
+ // ShouldShowSigninPromo().
+ EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
+ .WillOnce(testing::Return(true));
EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+
+ EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
+ .WillOnce(testing::Return(false));
+ EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+
+ // Number of impressions stay the same.
+ EXPECT_EQ(kCreditCardSigninPromoImpressionLimit,
+ autofill_client_.GetPrefs()->GetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount));
}
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
-// card form with an impression limit and no impressions yet.
+// card form on a non-secure page.
TEST_F(AutofillManagerTest,
- ShouldShowCreditCardSigninPromo_CreditCardField_UnmetLimit) {
- // Enable the feature with an impression limit.
- EnableCreditCardSigninPromoFeatureWithLimit(10);
- // No impressions yet.
- ASSERT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
- prefs::kAutofillCreditCardSigninPromoImpressionCount));
-
+ ShouldShowCreditCardSigninPromo_CreditCardField_NonSecureContext) {
// Set up our form data.
FormData form;
- CreateTestCreditCardFormData(&form, true, false);
+ CreateTestCreditCardFormData(&form, false, false);
+ form.origin = GURL("http://myform.com/form.html");
+ form.action = GURL("https://myform.com/submit.html");
+ autofill_client_.set_form_origin(form.origin);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
- // The mock implementation of ShouldShowSigninPromo() will return true here,
- // creating an impression, and false below, preventing an impression.
+ // Both calls will now return false, regardless of the mock implementation of
+ // ShouldShowSigninPromo().
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(true));
- EXPECT_TRUE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
-
- // Expect to now have an impression.
- EXPECT_EQ(1, autofill_client_.GetPrefs()->GetInteger(
- prefs::kAutofillCreditCardSigninPromoImpressionCount));
+ EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(false));
EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
- // No additional impression.
- EXPECT_EQ(1, autofill_client_.GetPrefs()->GetInteger(
+ // Number of impressions should remain at zero.
+ EXPECT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
prefs::kAutofillCreditCardSigninPromoImpressionCount));
}
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
-// card form with an impression limit that has been attained already.
+// card form targeting a non-secure page.
TEST_F(AutofillManagerTest,
- ShouldShowCreditCardSigninPromo_CreditCardField_WithAttainedLimit) {
- // Enable the feature with an impression limit.
- EnableCreditCardSigninPromoFeatureWithLimit(10);
-
+ ShouldShowCreditCardSigninPromo_CreditCardField_NonSecureAction) {
// Set up our form data.
FormData form;
- CreateTestCreditCardFormData(&form, true, false);
+ CreateTestCreditCardFormData(&form, false, false);
+ form.origin = GURL("https://myform.com/form.html");
+ form.action = GURL("http://myform.com/submit.html");
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
- // Set the impression count to the same value as the limit.
- autofill_client_.GetPrefs()->SetInteger(
- prefs::kAutofillCreditCardSigninPromoImpressionCount, 10);
-
// Both calls will now return false, regardless of the mock implementation of
// ShouldShowSigninPromo().
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
@@ -5383,9 +5511,9 @@ TEST_F(AutofillManagerTest,
.WillOnce(testing::Return(false));
EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
- // Number of impressions stay the same.
- EXPECT_EQ(10, autofill_client_.GetPrefs()->GetInteger(
- prefs::kAutofillCreditCardSigninPromoImpressionCount));
+ // Number of impressions should remain at zero.
+ EXPECT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount));
}
// Test that ShouldShowCreditCardSigninPromo behaves as expected for an address
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 66a7bfcc967..239334c5e66 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -11,9 +11,16 @@
#include "base/metrics/sparse_histogram.h"
#include "base/metrics/user_metrics.h"
#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/common/form_data.h"
+#include "components/ukm/ukm_entry_builder.h"
+
+namespace internal {
+const char kUKMCardUploadDecisionEntryName[] = "Autofill.CardUploadDecision";
+const char kUKMCardUploadDecisionMetricName[] = "UploadDecision";
+} // namespace internal
namespace autofill {
@@ -676,11 +683,56 @@ void AutofillMetrics::LogIsQueriedCreditCardFormSecure(bool is_secure) {
}
// static
+void AutofillMetrics::LogWalletAddressConversionType(
+ WalletAddressConversionType type) {
+ DCHECK_LT(type, NUM_CONVERTED_ADDRESS_CONVERSION_TYPES);
+ UMA_HISTOGRAM_ENUMERATION("Autofill.WalletAddressConversionType", type,
+ NUM_CONVERTED_ADDRESS_CONVERSION_TYPES);
+}
+
+// static
void AutofillMetrics::LogShowedHttpNotSecureExplanation() {
base::RecordAction(
base::UserMetricsAction("Autofill_ShowedHttpNotSecureExplanation"));
}
+// static
+void AutofillMetrics::LogCardUploadDecisionUkm(
+ ukm::UkmService* ukm_service,
+ const GURL& url,
+ AutofillMetrics::CardUploadDecisionMetric upload_decision) {
+ if (upload_decision >= AutofillMetrics::NUM_CARD_UPLOAD_DECISION_METRICS)
+ return;
+
+ // Set up as a map because the follow-up CL will add more metrics.
+ std::map<std::string, int> metrics = {
+ {internal::kUKMCardUploadDecisionMetricName,
+ static_cast<int>(upload_decision)}};
+ LogUkm(ukm_service, url, internal::kUKMCardUploadDecisionEntryName, metrics);
+}
+
+// static
+bool AutofillMetrics::LogUkm(ukm::UkmService* ukm_service,
+ const GURL& url,
+ const std::string& ukm_entry_name,
+ const std::map<std::string, int>& metrics) {
+ if (!IsUkmLoggingEnabled() || !ukm_service || !url.is_valid() ||
+ metrics.empty()) {
+ return false;
+ }
+
+ int32_t source_id = ukm_service->GetNewSourceID();
+ ukm_service->UpdateSourceURL(source_id, url);
+ std::unique_ptr<ukm::UkmEntryBuilder> builder =
+ ukm_service->GetEntryBuilder(source_id, ukm_entry_name.c_str());
+
+ for (auto it = metrics.begin(); it != metrics.end(); ++it) {
+ builder->AddMetric(it->first.c_str(), it->second);
+ }
+
+ return true;
+}
+
AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card)
: is_for_credit_card_(is_for_credit_card),
is_server_data_available_(false),
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index 6fe8a34ebc3..d0aba8221f6 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -17,7 +17,17 @@
namespace base {
class TimeDelta;
-}
+} // namespace base
+
+namespace ukm {
+class UkmService;
+} // namespace ukm
+
+namespace internal {
+// Name constants are exposed here so they can be referenced from tests.
+extern const char kUKMCardUploadDecisionEntryName[];
+extern const char kUKMCardUploadDecisionMetricName[];
+} // namespace internal
namespace autofill {
@@ -518,6 +528,15 @@ class AutofillMetrics {
NUM_WALLET_REQUIRED_ACTIONS
};
+ // For mesuring how wallet addresses are converted to local profiles.
+ enum WalletAddressConversionType : int {
+ // The converted wallet address was merged into an existing local profile.
+ CONVERTED_ADDRESS_MERGED,
+ // The converted wallet address was added as a new local profile.
+ CONVERTED_ADDRESS_ADDED,
+ NUM_CONVERTED_ADDRESS_CONVERSION_TYPES
+ };
+
static void LogCardUploadDecisionMetric(CardUploadDecisionMetric metric);
static void LogCreditCardInfoBarMetric(InfoBarMetric metric,
bool is_uploading);
@@ -663,10 +682,28 @@ class AutofillMetrics {
// context.
static void LogIsQueriedCreditCardFormSecure(bool is_secure);
+ // Log how the converted wallet address was added to the local autofill
+ // profiles.
+ static void LogWalletAddressConversionType(WalletAddressConversionType type);
+
// This should be called when the user selects the Form-Not-Secure warning
// suggestion to show an explanation of the warning.
static void LogShowedHttpNotSecureExplanation();
+ // Logs the card upload decision ukm based on the specified |url| and
+ // |upload_decision|.
+ static void LogCardUploadDecisionUkm(
+ ukm::UkmService* ukm_service,
+ const GURL& url,
+ AutofillMetrics::CardUploadDecisionMetric upload_decision);
+
+ // Logs the the |ukm_entry_name| with the specified |url| and the specified
+ // |metrics|. Returns whether the ukm was sucessfully logged.
+ static bool LogUkm(ukm::UkmService* ukm_service,
+ const GURL& url,
+ const std::string& ukm_entry_name,
+ const std::map<std::string, int>& metrics);
+
// Utility to autofill form events in the relevant histograms depending on
// the presence of server and/or local data.
class FormEventLogger {
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index f9799f5e8af..36039f5f382 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -6,17 +6,22 @@
#include <stddef.h>
+#include <map>
#include <memory>
#include <vector>
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/metrics_hashes.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/user_action_tester.h"
#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -28,12 +33,16 @@
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
+#include "components/metrics/proto/ukm/entry.pb.h"
#include "components/prefs/pref_service.h"
#include "components/rappor/test_rappor_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/signin/core/common/signin_pref_names.h"
+#include "components/ukm/test_ukm_service.h"
+#include "components/ukm/ukm_entry.h"
+#include "components/ukm/ukm_source.h"
#include "components/webdata/common/web_data_results.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -125,33 +134,25 @@ class TestPersonalDataManager : public PersonalDataManager {
autofill_enabled_ = autofill_enabled;
}
- // Removes all existing profiles and creates 0 or 1 local profiles and 0 or 1
- // server profile according to the parameters.
- void RecreateProfiles(bool include_local_profile,
- bool include_server_profile) {
+ // Removes all existing profiles
+ void ClearProfiles() {
web_profiles_.clear();
- server_profiles_.clear();
- if (include_local_profile) {
- std::unique_ptr<AutofillProfile> profile =
- base::MakeUnique<AutofillProfile>();
- test::SetProfileInfo(profile.get(), "Elvis", "Aaron", "Presley",
- "theking@gmail.com", "RCA",
- "3734 Elvis Presley Blvd.", "Apt. 10", "Memphis",
- "Tennessee", "38116", "US", "12345678901");
- profile->set_guid("00000000-0000-0000-0000-000000000001");
- web_profiles_.push_back(std::move(profile));
- }
- if (include_server_profile) {
- std::unique_ptr<AutofillProfile> profile =
- base::MakeUnique<AutofillProfile>(AutofillProfile::SERVER_PROFILE,
- "server_id");
- test::SetProfileInfo(profile.get(), "Charles", "Hardin", "Holley",
- "buddy@gmail.com", "Decca", "123 Apple St.",
- "unit 6", "Lubbock", "Texas", "79401", "US",
- "2345678901");
- profile->set_guid("00000000-0000-0000-0000-000000000002");
- server_profiles_.push_back(std::move(profile));
- }
+ Refresh();
+ }
+
+ // Removes all existing profiles and creates one profile.
+ void RecreateProfile() {
+ web_profiles_.clear();
+
+ std::unique_ptr<AutofillProfile> profile =
+ base::MakeUnique<AutofillProfile>();
+ test::SetProfileInfo(profile.get(), "Elvis", "Aaron", "Presley",
+ "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.",
+ "Apt. 10", "Memphis", "Tennessee", "38116", "US",
+ "12345678901");
+ profile->set_guid("00000000-0000-0000-0000-000000000001");
+ web_profiles_.push_back(std::move(profile));
+
Refresh();
}
@@ -304,6 +305,17 @@ class TestAutofillManager : public AutofillManager {
DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
};
+// Finds the specified UKM metric by |name| in the specified UKM |metrics|.
+const ukm::Entry_Metric* FindMetric(
+ const char* name,
+ const google::protobuf::RepeatedPtrField<ukm::Entry_Metric>& metrics) {
+ for (const auto& metric : metrics) {
+ if (metric.metric_hash() == base::HashMetricName(name))
+ return &metric;
+ }
+ return nullptr;
+}
+
} // namespace
// This is defined in the autofill_metrics.cc implementation file.
@@ -319,6 +331,7 @@ class AutofillMetricsTest : public testing::Test {
protected:
void EnableWalletSync();
+ void EnableUkmLogging();
base::MessageLoop message_loop_;
TestAutofillClient autofill_client_;
@@ -329,6 +342,7 @@ class AutofillMetricsTest : public testing::Test {
std::unique_ptr<TestAutofillManager> autofill_manager_;
std::unique_ptr<TestPersonalDataManager> personal_data_;
std::unique_ptr<AutofillExternalDelegate> external_delegate_;
+ base::test::ScopedFeatureList scoped_feature_list_;
};
AutofillMetricsTest::~AutofillMetricsTest() {
@@ -385,6 +399,10 @@ void AutofillMetricsTest::EnableWalletSync() {
signin_manager_->SetAuthenticatedAccountInfo("12345", "syncuser@example.com");
}
+void AutofillMetricsTest::EnableUkmLogging() {
+ scoped_feature_list_.InitAndEnableFeature(kAutofillUkmLogging);
+}
+
// Test that we log quality metrics appropriately.
TEST_F(AutofillMetricsTest, QualityMetrics) {
// Set up our form data.
@@ -1741,9 +1759,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// Test that the profile checkout flow user actions are correctly logged.
TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
- // Create profiles.
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- false /* include_server_profile */);
+ // Create a profile.
+ personal_data_->RecreateProfile();
// Set up our form data.
FormData form;
@@ -1935,8 +1952,7 @@ TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) {
// Tests that the Autofill_PolledProfileSuggestions user action is only logged
// once if the field is queried repeatedly.
TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- false /* include_server_profile */);
+ personal_data_->RecreateProfile();
// Set up the form data.
FormData form;
@@ -2875,9 +2891,8 @@ TEST_F(AutofillMetricsTest, AddressInteractedFormEvents) {
// Test that we log suggestion shown form events for address.
TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
EnableWalletSync();
- // Creating all kinds of profiles.
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- true /* include_server_profile */);
+ // Create a profile.
+ personal_data_->RecreateProfile();
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -2950,9 +2965,8 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
// Test that we log filled form events for address.
TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
EnableWalletSync();
- // Creating all kinds of profiles.
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- true /* include_server_profile */);
+ // Create a profile.
+ personal_data_->RecreateProfile();
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -2995,25 +3009,6 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating selecting/filling a server profile suggestion.
- base::HistogramTester histogram_tester;
- std::string guid("00000000-0000-0000-0000-000000000002"); // server profile
- autofill_manager_->FillOrPreviewForm(
- AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendID(std::string(), guid));
- histogram_tester.ExpectBucketCount(
- "Autofill.FormEvents.Address",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED, 1);
- histogram_tester.ExpectBucketCount(
- "Autofill.FormEvents.Address",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE, 1);
- }
-
- // Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
-
- {
// Simulating selecting/filling a local profile suggestion.
base::HistogramTester histogram_tester;
std::string guid("00000000-0000-0000-0000-000000000001"); // local profile
@@ -3035,9 +3030,8 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
// Test that we log submitted form events for address.
TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
EnableWalletSync();
- // Creating all kinds of profiles.
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- true /* include_server_profile */);
+ // Create a profile.
+ personal_data_->RecreateProfile();
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -3117,27 +3111,6 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating submission with filled server data.
- base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
- std::string guid("00000000-0000-0000-0000-000000000002"); // server profile
- autofill_manager_->FillOrPreviewForm(
- AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendID(std::string(), guid));
- autofill_manager_->SubmitForm(form, TimeTicks::Now());
- histogram_tester.ExpectBucketCount(
- "Autofill.FormEvents.Address",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1);
- histogram_tester.ExpectBucketCount(
- "Autofill.FormEvents.Address",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 1);
- }
-
- // Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
-
- {
// Simulating multiple submissions.
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -3221,9 +3194,8 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
// metrics.
TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
EnableWalletSync();
- // Creating all kinds of profiles.
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- true /* include_server_profile */);
+ // Create a profile.
+ personal_data_->RecreateProfile();
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("TestForm");
@@ -3303,27 +3275,6 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
autofill_manager_->AddSeenForm(form, field_types, field_types);
{
- // Simulating submission with filled server data.
- base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
- std::string guid("00000000-0000-0000-0000-000000000002"); // server profile
- autofill_manager_->FillOrPreviewForm(
- AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendID(std::string(), guid));
- autofill_manager_->WillSubmitForm(form, TimeTicks::Now());
- histogram_tester.ExpectBucketCount(
- "Autofill.FormEvents.Address",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1);
- histogram_tester.ExpectBucketCount(
- "Autofill.FormEvents.Address",
- AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, 0);
- }
-
- // Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
-
- {
// Simulating multiple submissions.
base::HistogramTester histogram_tester;
autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
@@ -3545,8 +3496,7 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
autofill_manager_->AddSeenForm(form, field_types, field_types);
- personal_data_->RecreateProfiles(false /* include_local_profile */,
- false /* include_server_profile */);
+ personal_data_->ClearProfiles();
{
// Simulate activating the autofill popup for the street field.
@@ -3560,8 +3510,7 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
// Reset the autofill manager state.
autofill_manager_->Reset();
autofill_manager_->AddSeenForm(form, field_types, field_types);
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- false /* include_server_profile */);
+ personal_data_->RecreateProfile();
{
// Simulate activating the autofill popup for the street field.
@@ -3571,36 +3520,6 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
"Autofill.FormEvents.Address.WithOnlyLocalData",
AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1);
}
-
- // Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
- personal_data_->RecreateProfiles(false /* include_local_profile */,
- true /* include_server_profile */);
-
- {
- // Simulate activating the autofill popup for the street field.
- base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
- histogram_tester.ExpectUniqueSample(
- "Autofill.FormEvents.Address.WithOnlyServerData",
- AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1);
- }
-
- // Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
- personal_data_->RecreateProfiles(true /* include_local_profile */,
- true /* include_server_profile */);
-
- {
- // Simulate activating the autofill popup for the street field.
- base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(0, form, field, gfx::RectF());
- histogram_tester.ExpectUniqueSample(
- "Autofill.FormEvents.Address.WithBothServerAndLocalData",
- AutofillMetrics::FORM_EVENT_INTERACTED_ONCE, 1);
- }
}
@@ -4447,4 +4366,94 @@ TEST_F(AutofillMetricsTest,
}
}
+// Tests that logging a UKM works as expected.
+TEST_F(AutofillMetricsTest, RecordCardUploadDecisionMetric) {
+ EnableUkmLogging();
+ ukm::UkmServiceTestingHarness ukm_service_test_harness;
+ GURL url("https://www.google.com");
+ int upload_decision = 1;
+ std::map<std::string, int> metrics;
+ metrics.insert(std::make_pair(internal::kUKMCardUploadDecisionMetricName,
+ upload_decision));
+
+ EXPECT_TRUE(AutofillMetrics::LogUkm(
+ ukm_service_test_harness.test_ukm_service(), url,
+ internal::kUKMCardUploadDecisionEntryName, metrics));
+
+ // Make sure that the UKM was logged correctly.
+ ukm::TestUkmService* ukm_service =
+ ukm_service_test_harness.test_ukm_service();
+
+ ASSERT_EQ(1U, ukm_service->sources_count());
+ const ukm::UkmSource* source = ukm_service->GetSource(0);
+ EXPECT_EQ(url.spec(), source->url().spec());
+
+ EXPECT_EQ(1U, ukm_service->entries_count());
+ const ukm::UkmEntry* entry = ukm_service->GetEntry(0);
+ EXPECT_EQ(source->id(), entry->source_id());
+
+ // Make sure that an card upload decision entry was logged.
+ ukm::Entry entry_proto;
+ entry->PopulateProto(&entry_proto);
+ EXPECT_EQ(source->id(), entry_proto.source_id());
+ EXPECT_EQ(base::HashMetricName(internal::kUKMCardUploadDecisionEntryName),
+ entry_proto.event_hash());
+ EXPECT_EQ(1, entry_proto.metrics_size());
+
+ // Make sure that the correct upload decision was logged.
+ const ukm::Entry_Metric* metric = FindMetric(
+ internal::kUKMCardUploadDecisionMetricName, entry_proto.metrics());
+ ASSERT_NE(nullptr, metric);
+ EXPECT_EQ(upload_decision, metric->value());
+}
+
+// Tests that no UKM is logged when the URL is not valid.
+TEST_F(AutofillMetricsTest, RecordCardUploadDecisionMetric_InvalidUrl) {
+ EnableUkmLogging();
+ ukm::UkmServiceTestingHarness ukm_service_test_harness;
+ GURL url("");
+ std::map<std::string, int> metrics;
+ metrics.insert(std::make_pair("metric", 1));
+
+ EXPECT_FALSE(AutofillMetrics::LogUkm(
+ ukm_service_test_harness.test_ukm_service(), url, "test_ukm", metrics));
+ EXPECT_EQ(0U, ukm_service_test_harness.test_ukm_service()->sources_count());
+}
+
+// Tests that no UKM is logged when the metrics map is empty.
+TEST_F(AutofillMetricsTest, RecordCardUploadDecisionMetric_NoMetrics) {
+ EnableUkmLogging();
+ ukm::UkmServiceTestingHarness ukm_service_test_harness;
+ GURL url("https://www.google.com");
+ std::map<std::string, int> metrics;
+
+ EXPECT_FALSE(AutofillMetrics::LogUkm(
+ ukm_service_test_harness.test_ukm_service(), url, "test_ukm", metrics));
+ EXPECT_EQ(0U, ukm_service_test_harness.test_ukm_service()->sources_count());
+}
+
+// Tests that no UKM is logged when the ukm service is null.
+TEST_F(AutofillMetricsTest, RecordCardUploadDecisionMetric_NoUkmService) {
+ EnableUkmLogging();
+ ukm::UkmServiceTestingHarness ukm_service_test_harness;
+ GURL url("https://www.google.com");
+ std::map<std::string, int> metrics;
+ metrics.insert(std::make_pair("metric", 1));
+
+ EXPECT_FALSE(AutofillMetrics::LogUkm(nullptr, url, "test_ukm", metrics));
+ ASSERT_EQ(0U, ukm_service_test_harness.test_ukm_service()->sources_count());
+}
+
+// Tests that no UKM is logged when the ukm logging feature is disabled.
+TEST_F(AutofillMetricsTest, RecordCardUploadDecisionMetric_FeatureDisabled) {
+ ukm::UkmServiceTestingHarness ukm_service_test_harness;
+ GURL url("https://www.google.com");
+ std::map<std::string, int> metrics;
+ metrics.insert(std::make_pair("metric", 1));
+
+ EXPECT_FALSE(AutofillMetrics::LogUkm(
+ ukm_service_test_harness.test_ukm_service(), url, "test_ukm", metrics));
+ EXPECT_EQ(0U, ukm_service_test_harness.test_ukm_service()->sources_count());
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile.cc b/chromium/components/autofill/core/browser/autofill_profile.cc
index 9630d5b188b..1828497e688 100644
--- a/chromium/components/autofill/core/browser/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile.cc
@@ -33,9 +33,10 @@
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/autofill/core/browser/state_names.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/form_field_data.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "third_party/icu/source/common/unicode/utypes.h"
#include "third_party/icu/source/i18n/unicode/translit.h"
@@ -702,7 +703,7 @@ void AutofillProfile::GenerateServerProfileIdentifier() {
void AutofillProfile::RecordAndLogUse() {
UMA_HISTOGRAM_COUNTS_1000("Autofill.DaysSinceLastUse.Profile",
- (base::Time::Now() - use_date()).InDays());
+ (AutofillClock::Now() - use_date()).InDays());
RecordUse();
}
diff --git a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
index 4ac1475d133..fe2e1d3f566 100644
--- a/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
+++ b/chromium/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
@@ -11,10 +11,10 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/legal_message_line.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/grit/components_scaled_resources.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_manager.h"
-#include "grit/components_scaled_resources.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/vector_icons_public.h"
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index 6994b6faa76..78b1f0e09ed 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -341,8 +341,7 @@ void FillUploadField(AutofillUploadContents::Field* field,
const char* name,
const char* control_type,
const char* autocomplete,
- unsigned autofill_type,
- const char* css_classes) {
+ unsigned autofill_type) {
field->set_signature(signature);
if (name)
field->set_name(name);
@@ -351,8 +350,6 @@ void FillUploadField(AutofillUploadContents::Field* field,
if (autocomplete)
field->set_autocomplete(autocomplete);
field->set_autofill_type(autofill_type);
- if (css_classes)
- field->set_css_classes(css_classes);
}
void FillQueryField(AutofillQueryContents::Form::Field* field,
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.h b/chromium/components/autofill/core/browser/autofill_test_utils.h
index 4912732cb9e..3e6be716ff4 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.h
@@ -132,8 +132,7 @@ void FillUploadField(AutofillUploadContents::Field* field,
const char* name,
const char* control_type,
const char* autocomplete,
- unsigned autofill_type,
- const char* css_classes);
+ unsigned autofill_type);
// Fills the query form |field| with the information passed by parameter. If the
// value of a const char* parameter is NULL, the corresponding attribute won't
diff --git a/chromium/components/autofill/core/browser/country_combobox_model.cc b/chromium/components/autofill/core/browser/country_combobox_model.cc
new file mode 100644
index 00000000000..c9f8a47a217
--- /dev/null
+++ b/chromium/components/autofill/core/browser/country_combobox_model.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 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/country_combobox_model.h"
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/country_data.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
+#include "ui/base/l10n/l10n_util_collator.h"
+#include "ui/base/models/combobox_model_observer.h"
+
+namespace autofill {
+
+CountryComboboxModel::CountryComboboxModel() {}
+
+CountryComboboxModel::~CountryComboboxModel() {}
+
+void CountryComboboxModel::SetCountries(
+ const PersonalDataManager& manager,
+ const base::Callback<bool(const std::string&)>& filter,
+ const std::string& app_locale) {
+ countries_.clear();
+
+ // Insert the default country at the top as well as in the ordered list.
+ std::string default_country_code =
+ manager.GetDefaultCountryCodeForNewAddress();
+ DCHECK(!default_country_code.empty());
+
+ if (filter.is_null() || filter.Run(default_country_code)) {
+ countries_.push_back(
+ base::MakeUnique<AutofillCountry>(default_country_code, app_locale));
+#if !defined(OS_ANDROID)
+ // The separator item. On Android, there are separators after all items, so
+ // this is unnecessary.
+ countries_.push_back(nullptr);
+#endif
+ }
+
+ // The sorted list of country codes.
+ const std::vector<std::string>* available_countries =
+ &CountryDataMap::GetInstance()->country_codes();
+
+ // Filter out the countries that do not have rules for address input and
+ // validation.
+ const std::vector<std::string>& addressinput_countries =
+ ::i18n::addressinput::GetRegionCodes();
+ std::vector<std::string> filtered_countries;
+ filtered_countries.reserve(available_countries->size());
+ std::set_intersection(
+ available_countries->begin(), available_countries->end(),
+ addressinput_countries.begin(), addressinput_countries.end(),
+ std::back_inserter(filtered_countries));
+ available_countries = &filtered_countries;
+
+ CountryVector sorted_countries;
+ for (const auto& country_code : *available_countries) {
+ if (filter.is_null() || filter.Run(country_code))
+ sorted_countries.push_back(
+ base::MakeUnique<AutofillCountry>(country_code, app_locale));
+ }
+
+ l10n_util::SortStringsUsingMethod(app_locale, &sorted_countries,
+ &AutofillCountry::name);
+ std::move(sorted_countries.begin(), sorted_countries.end(),
+ std::back_inserter(countries_));
+}
+
+int CountryComboboxModel::GetItemCount() const {
+ return countries_.size();
+}
+
+base::string16 CountryComboboxModel::GetItemAt(int index) {
+ AutofillCountry* country = countries_[index].get();
+ if (country)
+ return countries_[index]->name();
+
+ // The separator item. Implemented for platforms that don't yet support
+ // IsItemSeparatorAt().
+ return base::ASCIIToUTF16("---");
+}
+
+bool CountryComboboxModel::IsItemSeparatorAt(int index) {
+ return !countries_[index].get();
+}
+
+std::string CountryComboboxModel::GetDefaultCountryCode() const {
+ return countries_[GetDefaultIndex()]->country_code();
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/country_combobox_model.h b/chromium/components/autofill/core/browser/country_combobox_model.h
new file mode 100644
index 00000000000..b3d90c3abf6
--- /dev/null
+++ b/chromium/components/autofill/core/browser/country_combobox_model.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 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_COUNTRY_COMBOBOX_MODEL_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_COUNTRY_COMBOBOX_MODEL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "ui/base/models/combobox_model.h"
+
+namespace autofill {
+
+class AutofillCountry;
+class PersonalDataManager;
+
+// A model for countries to be used to enter addresses.
+class CountryComboboxModel : public ui::ComboboxModel {
+ public:
+ using CountryVector = std::vector<std::unique_ptr<AutofillCountry>>;
+
+ CountryComboboxModel();
+ ~CountryComboboxModel() override;
+
+ // |filter| is passed each known country's country code. If |filter| returns
+ // true, an item for that country is added to the model (else it's omitted).
+ // |manager| determines the default choice.
+ void SetCountries(const PersonalDataManager& manager,
+ const base::Callback<bool(const std::string&)>& filter,
+ const std::string& app_locale);
+
+ // ui::ComboboxModel implementation:
+ int GetItemCount() const override;
+ base::string16 GetItemAt(int index) override;
+ bool IsItemSeparatorAt(int index) override;
+
+ const CountryVector& countries() const { return countries_; }
+
+ // Returns the default country code for this model.
+ std::string GetDefaultCountryCode() const;
+
+ private:
+ // The countries to show in the model, including NULL for entries that are
+ // not countries (the separator entry).
+ CountryVector countries_;
+
+ DISALLOW_COPY_AND_ASSIGN(CountryComboboxModel);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_COUNTRY_COMBOBOX_MODEL_H_
diff --git a/chromium/components/autofill/core/browser/country_combobox_model_unittest.cc b/chromium/components/autofill/core/browser/country_combobox_model_unittest.cc
new file mode 100644
index 00000000000..ca3e9f0f3be
--- /dev/null
+++ b/chromium/components/autofill/core/browser/country_combobox_model_unittest.cc
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/country_combobox_model.h"
+
+#include <memory>
+
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/prefs/pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/localization.h"
+
+namespace autofill {
+
+class CountryComboboxModelTest : public testing::Test {
+ public:
+ CountryComboboxModelTest()
+ : pref_service_(autofill::test::PrefServiceForTesting()) {
+ manager_.SetTestingPrefService(pref_service_.get());
+ manager_.set_timezone_country_code("KR");
+ model_.reset(new CountryComboboxModel());
+ model_->SetCountries(manager_, base::Callback<bool(const std::string&)>(),
+ "en-US");
+ }
+
+ void TearDown() override { manager_.SetTestingPrefService(nullptr); }
+
+ TestPersonalDataManager* manager() { return &manager_; }
+ CountryComboboxModel* model() { return model_.get(); }
+
+ private:
+ TestPersonalDataManager manager_;
+ std::unique_ptr<PrefService> pref_service_;
+ std::unique_ptr<CountryComboboxModel> model_;
+};
+
+TEST_F(CountryComboboxModelTest, DefaultCountryCode) {
+ std::string default_country = model()->GetDefaultCountryCode();
+ EXPECT_EQ(manager()->GetDefaultCountryCodeForNewAddress(), default_country);
+
+ AutofillCountry country(default_country, "en-US");
+ EXPECT_EQ(country.name(), model()->GetItemAt(0));
+}
+
+TEST_F(CountryComboboxModelTest, AllCountriesHaveComponents) {
+ ::i18n::addressinput::Localization localization;
+ std::string unused;
+ for (int i = 0; i < model()->GetItemCount(); ++i) {
+ if (model()->IsItemSeparatorAt(i))
+ continue;
+
+ std::string country_code = model()->countries()[i]->country_code();
+ std::vector<::i18n::addressinput::AddressUiComponent> components =
+ ::i18n::addressinput::BuildComponents(country_code, localization,
+ std::string(), &unused);
+ EXPECT_FALSE(components.empty()) << " for country " << country_code;
+ }
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/country_data.cc b/chromium/components/autofill/core/browser/country_data.cc
index 443b2f60b90..90401b09aa4 100644
--- a/chromium/components/autofill/core/browser/country_data.cc
+++ b/chromium/components/autofill/core/browser/country_data.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/memory/singleton.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "third_party/icu/source/common/unicode/locid.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/credit_card.cc b/chromium/components/autofill/core/browser/credit_card.cc
index 3b402eae9e8..bd5110eced3 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/time_formatting.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
@@ -23,14 +24,16 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_data_util.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_l10n_util.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "components/autofill/core/common/form_field_data.h"
-#include "grit/components_scaled_resources.h"
-#include "grit/components_strings.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/strings/grit/components_strings.h"
#include "third_party/icu/source/common/unicode/uloc.h"
#include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
#include "ui/base/l10n/l10n_util.h"
@@ -48,6 +51,9 @@ const base::char16 kMidlineEllipsis[] = { 0x0020, 0x0020,
namespace {
const base::char16 kCreditCardObfuscationSymbol = '*';
+// Time format pattern for short month name (3 digits) and day in month (2
+// digits), e.g. in en-US locale, it can be used to generate "Feb 02".
+const char kTimeFormatPatternNoYearShortMonthDate[] = "MMMdd";
bool ConvertYear(const base::string16& year, int* num) {
// If the |year| is empty, clear the stored value.
@@ -473,7 +479,7 @@ void CreditCard::SetExpirationYear(int expiration_year) {
// Will normalize 2-digit years to the 4-digit version.
if (expiration_year > 0 && expiration_year < 100) {
base::Time::Exploded now_exploded;
- base::Time::Now().LocalExplode(&now_exploded);
+ AutofillClock::Now().LocalExplode(&now_exploded);
expiration_year += (now_exploded.year / 100) * 100;
}
@@ -536,6 +542,55 @@ void CreditCard::operator=(const CreditCard& credit_card) {
set_origin(credit_card.origin());
}
+base::string16 CreditCard::GetLastUsedDateForDisplay(
+ const std::string& app_locale) const {
+ bool show_expiration_date =
+ ShowExpirationDateInAutofillCreditCardLastUsedDate();
+
+ DCHECK(use_count() > 0);
+ // use_count() is initialized as 1 when the card is just added.
+ if (use_count() == 1) {
+ return show_expiration_date
+ ? l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_EXP_AND_ADDED_DATE,
+ GetInfo(AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR),
+ app_locale),
+ base::TimeFormatWithPattern(
+ use_date(), kTimeFormatPatternNoYearShortMonthDate))
+ : l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_ADDED_DATE,
+ base::TimeFormatWithPattern(
+ use_date(), kTimeFormatPatternNoYearShortMonthDate));
+ }
+
+ // use_count() > 1 when the card has been used in autofill.
+
+ // If the card was last used in autofill more than a year ago,
+ // display "last used over a year ago" without showing date detail.
+ if ((AutofillClock::Now() - use_date()).InDays() > 365) {
+ return show_expiration_date
+ ? l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_EXP_AND_LAST_USED_YEAR_AGO,
+ GetInfo(AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR),
+ app_locale))
+ : l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_LAST_USED_YEAR_AGO);
+ }
+
+ // If the card was last used in autofill within a year, show date information.
+ return show_expiration_date
+ ? l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_EXP_AND_LAST_USED_DATE,
+ GetInfo(AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR),
+ app_locale),
+ base::TimeFormatWithPattern(
+ use_date(), kTimeFormatPatternNoYearShortMonthDate))
+ : l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_CREDIT_CARD_LAST_USED_DATE,
+ base::TimeFormatWithPattern(
+ use_date(), kTimeFormatPatternNoYearShortMonthDate));
+}
+
bool CreditCard::UpdateFromImportedCard(const CreditCard& imported_card,
const std::string& app_locale) {
if (this->GetInfo(AutofillType(CREDIT_CARD_NUMBER), app_locale) !=
@@ -550,8 +605,8 @@ bool CreditCard::UpdateFromImportedCard(const CreditCard& imported_card,
if (this->IsVerified() && !imported_card.IsVerified()) {
// If the original card is expired and the imported card is not, and the
// name on the cards are identical, update the expiration date.
- if (this->IsExpired(base::Time::Now()) &&
- !imported_card.IsExpired(base::Time::Now()) &&
+ if (this->IsExpired(AutofillClock::Now()) &&
+ !imported_card.IsExpired(AutofillClock::Now()) &&
(name_on_card_ == imported_card.name_on_card_)) {
DCHECK(imported_card.expiration_month_ && imported_card.expiration_year_);
expiration_month_ = imported_card.expiration_month_;
@@ -659,52 +714,8 @@ bool CreditCard::IsEmpty(const std::string& app_locale) const {
bool CreditCard::IsValid() const {
return IsValidCreditCardNumber(number_) &&
- IsValidCreditCardExpirationDate(
- expiration_year_, expiration_month_, base::Time::Now());
-}
-
-void CreditCard::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
- supported_types->insert(CREDIT_CARD_NAME_FULL);
- supported_types->insert(CREDIT_CARD_NAME_FIRST);
- supported_types->insert(CREDIT_CARD_NAME_LAST);
- supported_types->insert(CREDIT_CARD_NUMBER);
- supported_types->insert(CREDIT_CARD_TYPE);
- supported_types->insert(CREDIT_CARD_EXP_MONTH);
- supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
- supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
- supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
- supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
-}
-
-base::string16 CreditCard::ExpirationMonthAsString() const {
- if (expiration_month_ == 0)
- return base::string16();
-
- base::string16 month = base::IntToString16(expiration_month_);
- if (expiration_month_ >= 10)
- return month;
-
- base::string16 zero = ASCIIToUTF16("0");
- zero.append(month);
- return zero;
-}
-
-base::string16 CreditCard::TypeForFill() const {
- return ::autofill::TypeForFill(type_);
-}
-
-base::string16 CreditCard::Expiration4DigitYearAsString() const {
- if (expiration_year_ == 0)
- return base::string16();
-
- return base::IntToString16(Expiration4DigitYear());
-}
-
-base::string16 CreditCard::Expiration2DigitYearAsString() const {
- if (expiration_year_ == 0)
- return base::string16();
-
- return base::IntToString16(Expiration2DigitYear());
+ IsValidCreditCardExpirationDate(expiration_year_, expiration_month_,
+ AutofillClock::Now());
}
bool CreditCard::SetExpirationMonthFromString(const base::string16& text,
@@ -774,6 +785,50 @@ void CreditCard::SetExpirationDateFromString(const base::string16& text) {
SetExpirationYear(num);
}
+void CreditCard::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
+ supported_types->insert(CREDIT_CARD_NAME_FULL);
+ supported_types->insert(CREDIT_CARD_NAME_FIRST);
+ supported_types->insert(CREDIT_CARD_NAME_LAST);
+ supported_types->insert(CREDIT_CARD_NUMBER);
+ supported_types->insert(CREDIT_CARD_TYPE);
+ supported_types->insert(CREDIT_CARD_EXP_MONTH);
+ supported_types->insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
+ supported_types->insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
+ supported_types->insert(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR);
+ supported_types->insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
+}
+
+base::string16 CreditCard::ExpirationMonthAsString() const {
+ if (expiration_month_ == 0)
+ return base::string16();
+
+ base::string16 month = base::IntToString16(expiration_month_);
+ if (expiration_month_ >= 10)
+ return month;
+
+ base::string16 zero = ASCIIToUTF16("0");
+ zero.append(month);
+ return zero;
+}
+
+base::string16 CreditCard::TypeForFill() const {
+ return ::autofill::TypeForFill(type_);
+}
+
+base::string16 CreditCard::Expiration4DigitYearAsString() const {
+ if (expiration_year_ == 0)
+ return base::string16();
+
+ return base::IntToString16(Expiration4DigitYear());
+}
+
+base::string16 CreditCard::Expiration2DigitYearAsString() const {
+ if (expiration_year_ == 0)
+ return base::string16();
+
+ return base::IntToString16(Expiration2DigitYear());
+}
+
void CreditCard::SetNumber(const base::string16& number) {
number_ = number;
@@ -785,7 +840,7 @@ void CreditCard::SetNumber(const base::string16& number) {
void CreditCard::RecordAndLogUse() {
UMA_HISTOGRAM_COUNTS_1000("Autofill.DaysSinceLastUse.CreditCard",
- (base::Time::Now() - use_date()).InDays());
+ (AutofillClock::Now() - use_date()).InDays());
RecordUse();
}
diff --git a/chromium/components/autofill/core/browser/credit_card.h b/chromium/components/autofill/core/browser/credit_card.h
index d0a8a6eee7e..0fb251e9deb 100644
--- a/chromium/components/autofill/core/browser/credit_card.h
+++ b/chromium/components/autofill/core/browser/credit_card.h
@@ -174,6 +174,9 @@ class CreditCard : public AutofillDataModel {
// Sets |number_| to |number| and computes the appropriate card |type_|.
void SetNumber(const base::string16& number);
+ // Returns the date when the credit card was last used in autofill.
+ base::string16 GetLastUsedDateForDisplay(const std::string& app_locale) const;
+
// Logs the number of days since the credit card was last used and records its
// use.
void RecordAndLogUse();
@@ -196,6 +199,20 @@ class CreditCard : public AutofillDataModel {
billing_address_id_ = id;
}
+ // Sets |expiration_month_| to the integer conversion of |text| and returns
+ // whether the operation was successful.
+ bool SetExpirationMonthFromString(const base::string16& text,
+ const std::string& app_locale);
+
+ // Sets |expiration_year_| to the integer conversion of |text|. Will handle
+ // 4-digit year or 2-digit year (eventually converted to 4-digit year).
+ void SetExpirationYearFromString(const base::string16& text);
+
+ // Sets |expiration_year_| and |expiration_month_| to the integer conversion
+ // of |text|. Will handle mmyy, mmyyyy, mm-yyyy and mm-yy as well as single
+ // digit months, with various separators.
+ void SetExpirationDateFromString(const base::string16& text);
+
private:
FRIEND_TEST_ALL_PREFIXES(CreditCardTest, SetExpirationDateFromString);
FRIEND_TEST_ALL_PREFIXES(CreditCardTest, SetExpirationYearFromString);
@@ -213,20 +230,6 @@ class CreditCard : public AutofillDataModel {
base::string16 Expiration4DigitYearAsString() const;
base::string16 Expiration2DigitYearAsString() const;
- // Sets |expiration_month_| to the integer conversion of |text| and returns
- // whether the operation was successful.
- bool SetExpirationMonthFromString(const base::string16& text,
- const std::string& app_locale);
-
- // Sets |expiration_year_| to the integer conversion of |text|. Will handle
- // 4-digit year or 2-digit year (eventually converted to 4-digit year).
- void SetExpirationYearFromString(const base::string16& text);
-
- // Sets |expiration_year_| and |expiration_month_| to the integer conversion
- // of |text|. Will handle mmyy, mmyyyy, mm-yyyy and mm-yy as well as single
- // digit months, with various separators.
- void SetExpirationDateFromString(const base::string16& text);
-
// See enum definition above.
RecordType record_type_;
diff --git a/chromium/components/autofill/core/browser/credit_card_field.cc b/chromium/components/autofill/core/browser/credit_card_field.cc
index f53c6865f40..1f23137e4df 100644
--- a/chromium/components/autofill/core/browser/credit_card_field.cc
+++ b/chromium/components/autofill/core/browser/credit_card_field.cc
@@ -19,8 +19,9 @@
#include "components/autofill/core/browser/autofill_regex_constants.h"
#include "components/autofill/core/browser/autofill_scanner.h"
#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_regexes.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
@@ -285,7 +286,7 @@ bool CreditCardField::LikelyCardYearSelectField(AutofillScanner* scanner) {
if (!MatchesFormControlType(field->form_control_type, MATCH_SELECT))
return false;
- const base::Time time_now = base::Time::Now();
+ const base::Time time_now = AutofillClock::Now();
base::Time::Exploded time_exploded;
time_now.UTCExplode(&time_exploded);
diff --git a/chromium/components/autofill/core/browser/credit_card_unittest.cc b/chromium/components/autofill/core/browser/credit_card_unittest.cc
index de26d8e56d3..993862f6d6d 100644
--- a/chromium/components/autofill/core/browser/credit_card_unittest.cc
+++ b/chromium/components/autofill/core/browser/credit_card_unittest.cc
@@ -10,13 +10,15 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/form_field_data.h"
-#include "grit/components_scaled_resources.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/variations/variations_params_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
@@ -887,4 +889,72 @@ TEST(CreditCardTest, ShouldUpdateExpiration) {
}
}
+// Test that credit card last used date suggestion can be generated correctly
+// in different variations.
+TEST(CreditCardTest, GetLastUsedDateForDisplay) {
+ const base::Time::Exploded kTestDateTimeExploded = {
+ 2016, 12, 6, 10, // Sat, Dec 10, 2016
+ 15, 42, 7, 0 // 15:42:07.000
+ };
+ base::Time kArbitraryTime;
+ EXPECT_TRUE(
+ base::Time::FromLocalExploded(kTestDateTimeExploded, &kArbitraryTime));
+
+ // Test for added to chrome/chromium.
+ CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com");
+ credit_card0.set_use_count(1);
+ credit_card0.set_use_date(kArbitraryTime - base::TimeDelta::FromDays(1));
+ test::SetCreditCardInfo(&credit_card0, "John Dillinger",
+ "423456789012" /* Visa */, "01", "2021");
+
+ // Test for last used date.
+ CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com");
+ test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
+ "347666888555" /* American Express */, "04", "2021");
+ credit_card1.set_use_count(10);
+ credit_card1.set_use_date(kArbitraryTime - base::TimeDelta::FromDays(10));
+
+ // Test for last used more than one year ago.
+ CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com");
+ credit_card2.set_use_count(5);
+ credit_card2.set_use_date(kArbitraryTime - base::TimeDelta::FromDays(366));
+ test::SetCreditCardInfo(&credit_card2, "Bonnie Parker",
+ "518765432109" /* Mastercard */, "12", "2021");
+
+ static const struct {
+ const char* show_expiration_date;
+ const std::string& app_locale;
+ base::string16 added_to_autofill_date;
+ base::string16 last_used_date;
+ base::string16 last_used_year_ago;
+ } kTestCases[] = {
+ // only show last used date.
+ {"false", "en_US", ASCIIToUTF16("Added Dec 09"),
+ ASCIIToUTF16("Last used Nov 30"),
+ ASCIIToUTF16("Last used over a year ago")},
+ // show expiration date and last used date.
+ {"true", "en_US", ASCIIToUTF16("Exp: 01/21, added Dec 09"),
+ ASCIIToUTF16("Exp: 04/21, last used Nov 30"),
+ ASCIIToUTF16("Exp: 12/21, last used over a year ago")},
+ };
+
+ variations::testing::VariationParamsManager variation_params_;
+
+ for (const auto& test_case : kTestCases) {
+ variation_params_.SetVariationParamsWithFeatureAssociations(
+ kAutofillCreditCardLastUsedDateDisplay.name,
+ {{kAutofillCreditCardLastUsedDateShowExpirationDateKey,
+ test_case.show_expiration_date}},
+ {kAutofillCreditCardLastUsedDateDisplay.name});
+
+ EXPECT_EQ(test_case.added_to_autofill_date,
+ credit_card0.GetLastUsedDateForDisplay(test_case.app_locale));
+ EXPECT_EQ(test_case.last_used_date,
+ credit_card1.GetLastUsedDateForDisplay(test_case.app_locale));
+ EXPECT_EQ(test_case.last_used_year_ago,
+ credit_card2.GetLastUsedDateForDisplay(test_case.app_locale));
+ variation_params_.ClearAllVariationParams();
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index 278cc7b6de3..addf89f686b 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -628,7 +628,7 @@ void FormStructure::UpdateFromCache(const FormStructure& cached_form) {
// Map from field signatures to cached fields.
std::map<std::string, const AutofillField*> cached_fields;
for (size_t i = 0; i < cached_form.field_count(); ++i) {
- const auto& field = cached_form.field(i);
+ auto* const field = cached_form.field(i);
cached_fields[field->FieldSignatureAsStr()] = field;
}
@@ -681,7 +681,7 @@ void FormStructure::LogQualityMetrics(const base::TimeTicks& load_time,
bool did_autofill_all_possible_fields = true;
bool did_autofill_some_possible_fields = false;
for (size_t i = 0; i < field_count(); ++i) {
- const auto& field = this->field(i);
+ auto* const field = this->field(i);
// No further logging for password fields. Those are primarily related to a
// different feature code path, and so make more sense to track outside of
@@ -1159,6 +1159,9 @@ void FormStructure::EncodeFormForUpload(AutofillUploadContents* upload) const {
if (!field->name.empty())
added_field->set_name(base::UTF16ToUTF8(field->name));
+ if (!field->id.empty())
+ added_field->set_id(base::UTF16ToUTF8(field->id));
+
if (!field->autocomplete_attribute.empty())
added_field->set_autocomplete(field->autocomplete_attribute);
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index aaa39253621..c1ecb59405c 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -2191,15 +2191,15 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 3494530716U, "lastname", "text",
- nullptr, 5U, nullptr);
+ nullptr, 5U);
test::FillUploadField(upload.add_field(), 1029417091U, "email", "email",
- nullptr, 9U, nullptr);
+ nullptr, 9U);
test::FillUploadField(upload.add_field(), 466116101U, "phone", "number",
- nullptr, 14U, nullptr);
+ nullptr, 14U);
test::FillUploadField(upload.add_field(), 2799270304U, "country",
- "select-one", nullptr, 36U, nullptr);
+ "select-one", nullptr, 36U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2247,7 +2247,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest) {
// Create an additonal 8 fields (total of 13).
for (int i = 0; i < 8; ++i) {
test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
- nullptr, 30U, nullptr);
+ nullptr, 30U);
}
// Put the appropriate autofill type on the different address fields.
upload.mutable_field(6)->set_autofill_type(31U);
@@ -2375,14 +2375,14 @@ TEST_F(FormStructureTest,
AutofillUploadContents::Field* upload_firstname_field = upload.add_field();
test::FillUploadField(upload_firstname_field, 4224610201U, "firstname", "",
- "given-name", 3U, nullptr);
+ "given-name", 3U);
upload_firstname_field->set_form_classifier_outcome(
AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
upload_firstname_field->set_properties_mask(FieldPropertiesFlags::HAD_FOCUS);
AutofillUploadContents::Field* upload_lastname_field = upload.add_field();
test::FillUploadField(upload_lastname_field, 2786066110U, "lastname", "",
- "family-name", 5U, nullptr);
+ "family-name", 5U);
upload_lastname_field->set_form_classifier_outcome(
AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
upload_lastname_field->set_properties_mask(FieldPropertiesFlags::HAD_FOCUS |
@@ -2390,7 +2390,7 @@ TEST_F(FormStructureTest,
AutofillUploadContents::Field* upload_email_field = upload.add_field();
test::FillUploadField(upload_email_field, 1029417091U, "email", "email",
- "email", 9U, nullptr);
+ "email", 9U);
upload_email_field->set_form_classifier_outcome(
AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
upload_email_field->set_properties_mask(FieldPropertiesFlags::HAD_FOCUS |
@@ -2398,7 +2398,7 @@ TEST_F(FormStructureTest,
AutofillUploadContents::Field* upload_username_field = upload.add_field();
test::FillUploadField(upload_username_field, 239111655U, "username", "text",
- "email", 86U, nullptr);
+ "email", 86U);
upload_username_field->set_form_classifier_outcome(
AutofillUploadContents::Field::NON_GENERATION_ELEMENT);
upload_username_field->set_properties_mask(FieldPropertiesFlags::HAD_FOCUS |
@@ -2406,7 +2406,7 @@ TEST_F(FormStructureTest,
AutofillUploadContents::Field* upload_password_field = upload.add_field();
test::FillUploadField(upload_password_field, 2051817934U, "password",
- "password", "email", 76U, nullptr);
+ "password", "email", 76U);
upload_password_field->set_form_classifier_outcome(
AutofillUploadContents::Field::GENERATION_ELEMENT);
upload_password_field->set_generation_type(
@@ -2480,11 +2480,11 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithAutocomplete) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
- "given-name", 3U, nullptr);
+ "given-name", 3U);
test::FillUploadField(upload.add_field(), 3494530716U, "lastname", "text",
- "family-name", 5U, nullptr);
+ "family-name", 5U);
test::FillUploadField(upload.add_field(), 1029417091U, "email", "email",
- "email", 9U, nullptr);
+ "email", 9U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2548,11 +2548,11 @@ TEST_F(FormStructureTest, EncodeUploadRequest_ObservedSubmissionFalse) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 3763331450U, "firstname", "text",
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 3494530716U, "lastname", "text",
- nullptr, 5U, nullptr);
+ nullptr, 5U);
test::FillUploadField(upload.add_field(), 1029417091U, "email", "email",
- nullptr, 9U, nullptr);
+ nullptr, 9U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2613,11 +2613,11 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithLabels) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 5U, nullptr);
+ nullptr, 5U);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 9U, nullptr);
+ nullptr, 9U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2631,7 +2631,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithLabels) {
EXPECT_EQ(expected_upload_string, encoded_upload_string);
}
-TEST_F(FormStructureTest, EncodeUploadRequest_WithCssClasses) {
+TEST_F(FormStructureTest, EncodeUploadRequest_WithCssClassesAndIds) {
std::vector<ServerFieldTypeSet> possible_field_types;
FormData form;
@@ -2643,11 +2643,13 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithCssClasses) {
possible_field_types.back().insert(NAME_FIRST);
field.css_classes = ASCIIToUTF16("last_name_field");
+ field.id = ASCIIToUTF16("lastname_id");
form.fields.push_back(field);
possible_field_types.push_back(ServerFieldTypeSet());
possible_field_types.back().insert(NAME_LAST);
field.css_classes = ASCIIToUTF16("email_field required_field");
+ field.id = ASCIIToUTF16("email_id");
form.fields.push_back(field);
possible_field_types.push_back(ServerFieldTypeSet());
possible_field_types.back().insert(EMAIL_ADDRESS);
@@ -2672,12 +2674,20 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithCssClasses) {
upload.set_data_present("1440");
upload.set_action_signature(15724779818122431245U);
- test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 3U, nullptr);
- test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 5U, "last_name_field");
- test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 9U, "email_field required_field");
+ AutofillUploadContents::Field* firstname_field = upload.add_field();
+ test::FillUploadField(firstname_field, 1318412689U, nullptr, "text", nullptr,
+ 3U);
+
+ AutofillUploadContents::Field* lastname_field = upload.add_field();
+ test::FillUploadField(lastname_field, 1318412689U, nullptr, "text", nullptr,
+ 5U);
+ lastname_field->set_id("lastname_id");
+ lastname_field->set_css_classes("last_name_field");
+
+ AutofillUploadContents::Field* email_field = upload.add_field();
+ test::FillUploadField(email_field, 1318412689U, nullptr, "text", nullptr, 9U);
+ email_field->set_id("email_id");
+ email_field->set_css_classes("email_field required_field");
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2738,11 +2748,11 @@ TEST_F(FormStructureTest, EncodeUploadRequest_WithFormName) {
upload.set_form_name("myform");
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 5U, nullptr);
+ nullptr, 5U);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 9U, nullptr);
+ nullptr, 9U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2808,11 +2818,11 @@ TEST_F(FormStructureTest, EncodeUploadRequestPartialMetadata) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 1318412689U, nullptr, "text",
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 3494530716U, "lastname", "text",
- "family-name", 5U, nullptr);
+ "family-name", 5U);
test::FillUploadField(upload.add_field(), 1545468175U, "lastname", "email",
- "email", 9U, nullptr);
+ "email", 9U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2841,6 +2851,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
field.label = ASCIIToUTF16("First Name");
field.name = ASCIIToUTF16("firstname");
+ field.id = ASCIIToUTF16("first_name");
field.autocomplete_attribute = "given-name";
field.css_classes = ASCIIToUTF16("class1 class2");
form.fields.push_back(field);
@@ -2849,6 +2860,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
field.label = ASCIIToUTF16("Last Name");
field.name = ASCIIToUTF16("lastname");
+ field.id = ASCIIToUTF16("last_name");
field.autocomplete_attribute = "family-name";
field.css_classes = ASCIIToUTF16("class1 class2");
form.fields.push_back(field);
@@ -2857,6 +2869,7 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
field.label = ASCIIToUTF16("Email");
field.name = ASCIIToUTF16("email");
+ field.id = ASCIIToUTF16("e-mail");
field.form_control_type = "email";
field.autocomplete_attribute = "email";
field.css_classes = ASCIIToUTF16("class1 class2");
@@ -2884,11 +2897,11 @@ TEST_F(FormStructureTest, EncodeUploadRequest_DisabledMetadataTrial) {
upload.set_data_present("1440");
test::FillUploadField(upload.add_field(), 3763331450U, nullptr, nullptr,
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 3494530716U, nullptr, nullptr,
- nullptr, 5U, nullptr);
+ nullptr, 5U);
test::FillUploadField(upload.add_field(), 1029417091U, nullptr, nullptr,
- nullptr, 9U, nullptr);
+ nullptr, 9U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -2944,11 +2957,11 @@ TEST_F(FormStructureTest, CheckDataPresence) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 1089846351U, "first", "text",
- nullptr, 1U, nullptr);
+ nullptr, 1U);
test::FillUploadField(upload.add_field(), 2404144663U, "last", "text",
- nullptr, 1U, nullptr);
+ nullptr, 1U);
test::FillUploadField(upload.add_field(), 420638584U, "email", "text",
- nullptr, 1U, nullptr);
+ nullptr, 1U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -3212,13 +3225,13 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
upload.set_action_signature(15724779818122431245U);
test::FillUploadField(upload.add_field(), 420638584U, "email", "text",
- nullptr, 9U, nullptr);
+ nullptr, 9U);
test::FillUploadField(upload.add_field(), 1089846351U, "first", "text",
- nullptr, 3U, nullptr);
+ nullptr, 3U);
test::FillUploadField(upload.add_field(), 2404144663U, "last", "text",
- nullptr, 5U, nullptr);
+ nullptr, 5U);
test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
- nullptr, 30U, nullptr);
+ nullptr, 30U);
std::string expected_upload_string;
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -3240,10 +3253,10 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
upload.mutable_field(2)->set_autofill_type(3);
// Replace the fourth field by the old third field.
test::FillUploadField(upload.mutable_field(3), 2404144663U, "last", "text",
- nullptr, 5U, nullptr);
+ nullptr, 5U);
// Re-add the old fourth field.
test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
- nullptr, 30U, nullptr);
+ nullptr, 30U);
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
@@ -3261,7 +3274,7 @@ TEST_F(FormStructureTest, CheckMultipleTypes) {
// Adjust the expected upload proto.
test::FillUploadField(upload.add_field(), 509334676U, "address", "text",
- nullptr, 31U, nullptr);
+ nullptr, 31U);
ASSERT_TRUE(upload.SerializeToString(&expected_upload_string));
AutofillUploadContents encoded_upload3;
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.cc b/chromium/components/autofill/core/browser/payments/full_card_request.cc
index f2f63805e58..ee21ebaf829 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.cc
@@ -8,10 +8,10 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/autofill_clock.h"
namespace autofill {
namespace payments {
@@ -22,7 +22,8 @@ FullCardRequest::FullCardRequest(AutofillClient* autofill_client,
: autofill_client_(autofill_client),
payments_client_(payments_client),
personal_data_manager_(personal_data_manager),
- delegate_(nullptr),
+ result_delegate_(nullptr),
+ ui_delegate_(nullptr),
should_unmask_card_(false),
weak_ptr_factory_(this) {
DCHECK(autofill_client_);
@@ -34,28 +35,31 @@ FullCardRequest::~FullCardRequest() {}
void FullCardRequest::GetFullCard(const CreditCard& card,
AutofillClient::UnmaskCardReason reason,
- base::WeakPtr<Delegate> delegate) {
- DCHECK(delegate);
-
- // Only request can be active a time. If the member variable |delegate_| is
- // already set, then immediately reject the new request through the method
- // parameter |delegate|.
- if (delegate_) {
- delegate->OnFullCardRequestFailed();
+ base::WeakPtr<ResultDelegate> result_delegate,
+ base::WeakPtr<UIDelegate> ui_delegate) {
+ DCHECK(result_delegate);
+ DCHECK(ui_delegate);
+
+ // Only one request can be active at a time. If the member variable
+ // |result_delegate_| is already set, then immediately reject the new request
+ // through the method parameter |result_delegate_|.
+ if (result_delegate_) {
+ result_delegate_->OnFullCardRequestFailed();
return;
}
- delegate_ = delegate;
+ result_delegate_ = result_delegate;
+ ui_delegate_ = ui_delegate;
request_.reset(new payments::PaymentsClient::UnmaskRequestDetails);
request_->card = card;
should_unmask_card_ = card.record_type() == CreditCard::MASKED_SERVER_CARD ||
(card.record_type() == CreditCard::FULL_SERVER_CARD &&
- card.ShouldUpdateExpiration(base::Time::Now()));
+ card.ShouldUpdateExpiration(AutofillClock::Now()));
if (should_unmask_card_)
payments_client_->Prepare();
- autofill_client_->ShowUnmaskPrompt(request_->card, reason,
- weak_ptr_factory_.GetWeakPtr());
+ ui_delegate_->ShowUnmaskPrompt(request_->card, reason,
+ weak_ptr_factory_.GetWeakPtr());
if (should_unmask_card_) {
autofill_client_->LoadRiskData(
@@ -82,23 +86,26 @@ void FullCardRequest::OnUnmaskResponse(const UnmaskResponse& response) {
}
if (!should_unmask_card_) {
- if (delegate_)
- delegate_->OnFullCardRequestSucceeded(request_->card, response.cvc);
+ if (result_delegate_)
+ result_delegate_->OnFullCardRequestSucceeded(request_->card,
+ response.cvc);
+ if (ui_delegate_)
+ ui_delegate_->OnUnmaskVerificationResult(AutofillClient::SUCCESS);
Reset();
- autofill_client_->OnUnmaskVerificationResult(AutofillClient::SUCCESS);
+
return;
}
request_->user_response = response;
if (!request_->risk_data.empty()) {
- real_pan_request_timestamp_ = base::Time::Now();
+ real_pan_request_timestamp_ = AutofillClock::Now();
payments_client_->UnmaskCard(*request_);
}
}
void FullCardRequest::OnUnmaskPromptClosed() {
- if (delegate_)
- delegate_->OnFullCardRequestFailed();
+ if (result_delegate_)
+ result_delegate_->OnFullCardRequestFailed();
Reset();
}
@@ -106,7 +113,7 @@ void FullCardRequest::OnUnmaskPromptClosed() {
void FullCardRequest::OnDidGetUnmaskRiskData(const std::string& risk_data) {
request_->risk_data = risk_data;
if (!request_->user_response.cvc.empty()) {
- real_pan_request_timestamp_ = base::Time::Now();
+ real_pan_request_timestamp_ = AutofillClock::Now();
payments_client_->UnmaskCard(*request_);
}
}
@@ -114,7 +121,10 @@ void FullCardRequest::OnDidGetUnmaskRiskData(const std::string& risk_data) {
void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) {
AutofillMetrics::LogRealPanDuration(
- base::Time::Now() - real_pan_request_timestamp_, result);
+ AutofillClock::Now() - real_pan_request_timestamp_, result);
+
+ if (ui_delegate_)
+ ui_delegate_->OnUnmaskVerificationResult(result);
switch (result) {
// Wait for user retry.
@@ -125,8 +135,8 @@ void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
case AutofillClient::PERMANENT_FAILURE:
// Intentional fall through.
case AutofillClient::NETWORK_ERROR: {
- if (delegate_)
- delegate_->OnFullCardRequestFailed();
+ if (result_delegate_)
+ result_delegate_->OnFullCardRequestFailed();
Reset();
break;
}
@@ -140,9 +150,9 @@ void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
if (request_->user_response.should_store_pan)
personal_data_manager_->UpdateServerCreditCard(request_->card);
- if (delegate_)
- delegate_->OnFullCardRequestSucceeded(request_->card,
- request_->user_response.cvc);
+ if (result_delegate_)
+ result_delegate_->OnFullCardRequestSucceeded(
+ request_->card, request_->user_response.cvc);
Reset();
break;
}
@@ -151,14 +161,13 @@ void FullCardRequest::OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
NOTREACHED();
break;
}
-
- autofill_client_->OnUnmaskVerificationResult(result);
}
void FullCardRequest::Reset() {
weak_ptr_factory_.InvalidateWeakPtrs();
payments_client_->CancelRequest();
- delegate_ = nullptr;
+ result_delegate_ = nullptr;
+ ui_delegate_ = nullptr;
request_.reset();
should_unmask_card_ = false;
}
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request.h b/chromium/components/autofill/core/browser/payments/full_card_request.h
index 6fd06ae5250..263b3c88fe7 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.h
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.h
@@ -12,12 +12,12 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/card_unmask_delegate.h"
#include "components/autofill/core/browser/payments/payments_client.h"
namespace autofill {
-class AutofillClient;
class CreditCard;
class PersonalDataManager;
@@ -27,13 +27,26 @@ namespace payments {
class FullCardRequest : public CardUnmaskDelegate {
public:
// The interface for receiving the full card details.
- class Delegate {
+ class ResultDelegate {
public:
+ virtual ~ResultDelegate() = default;
virtual void OnFullCardRequestSucceeded(const CreditCard& card,
const base::string16& cvc) = 0;
virtual void OnFullCardRequestFailed() = 0;
};
+ // The delegate responsible for displaying the unmask prompt UI.
+ class UIDelegate {
+ public:
+ virtual ~UIDelegate() = default;
+ virtual void ShowUnmaskPrompt(
+ const CreditCard& card,
+ AutofillClient::UnmaskCardReason reason,
+ base::WeakPtr<CardUnmaskDelegate> delegate) = 0;
+ virtual void OnUnmaskVerificationResult(
+ AutofillClient::PaymentsRpcResult result) = 0;
+ };
+
// The parameters should outlive the FullCardRequest.
FullCardRequest(AutofillClient* autofill_client,
payments::PaymentsClient* payments_client,
@@ -50,7 +63,8 @@ class FullCardRequest : public CardUnmaskDelegate {
// autofill table on disk.
void GetFullCard(const CreditCard& card,
AutofillClient::UnmaskCardReason reason,
- base::WeakPtr<Delegate> delegate);
+ base::WeakPtr<ResultDelegate> result_delegate,
+ base::WeakPtr<UIDelegate> ui_delegate);
// Returns true if there's a pending request to get the full card.
bool IsGettingFullCard() const;
@@ -80,7 +94,10 @@ class FullCardRequest : public CardUnmaskDelegate {
PersonalDataManager* const personal_data_manager_;
// Receiver of the full PAN and CVC.
- base::WeakPtr<Delegate> delegate_;
+ base::WeakPtr<ResultDelegate> result_delegate_;
+
+ // Delegate responsible for displaying the unmask prompt UI.
+ base::WeakPtr<UIDelegate> ui_delegate_;
// The pending request to get a card's full PAN and CVC.
std::unique_ptr<payments::PaymentsClient::UnmaskRequestDetails> request_;
diff --git a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
index 480f71c8aa4..76e3637540b 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -27,14 +27,26 @@ namespace payments {
using testing::_;
// The consumer of the full card request API.
-class MockDelegate : public FullCardRequest::Delegate,
- public base::SupportsWeakPtr<MockDelegate> {
+class MockResultDelegate : public FullCardRequest::ResultDelegate,
+ public base::SupportsWeakPtr<MockResultDelegate> {
public:
MOCK_METHOD2(OnFullCardRequestSucceeded,
void(const CreditCard&, const base::string16&));
MOCK_METHOD0(OnFullCardRequestFailed, void());
};
+// The delegate responsible for displaying the unmask prompt UI.
+class MockUIDelegate : public FullCardRequest::UIDelegate,
+ public base::SupportsWeakPtr<MockUIDelegate> {
+ public:
+ MOCK_METHOD3(ShowUnmaskPrompt,
+ void(const CreditCard&,
+ AutofillClient::UnmaskCardReason,
+ base::WeakPtr<CardUnmaskDelegate>));
+ MOCK_METHOD1(OnUnmaskVerificationResult,
+ void(AutofillClient::PaymentsRpcResult));
+};
+
// The personal data manager.
class MockPersonalDataManager : public PersonalDataManager {
public:
@@ -44,17 +56,6 @@ class MockPersonalDataManager : public PersonalDataManager {
MOCK_METHOD1(UpdateServerCreditCard, void(const CreditCard& credit_card));
};
-// The autofill client.
-class MockAutofillClient : public TestAutofillClient {
- public:
- MOCK_METHOD3(ShowUnmaskPrompt,
- void(const CreditCard&,
- UnmaskCardReason,
- base::WeakPtr<CardUnmaskDelegate>));
- MOCK_METHOD1(OnUnmaskVerificationResult,
- void(AutofillClient::PaymentsRpcResult));
-};
-
// The test fixture for full card request.
class FullCardRequestTest : public testing::Test,
public PaymentsClientDelegate {
@@ -74,15 +75,15 @@ class FullCardRequestTest : public testing::Test,
MockPersonalDataManager* personal_data() { return &personal_data_; }
- MockAutofillClient* client() { return &autofill_client_; }
-
FullCardRequest* request() { return &request_; }
- CardUnmaskDelegate* ui_delegate() {
+ CardUnmaskDelegate* card_unmask_delegate() {
return static_cast<CardUnmaskDelegate*>(&request_);
}
- MockDelegate* delegate() { return &delegate_; }
+ MockResultDelegate* result_delegate() { return &result_delegate_; }
+
+ MockUIDelegate* ui_delegate() { return &ui_delegate_; }
// PaymentsClientDelegate:
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
@@ -107,10 +108,11 @@ class FullCardRequestTest : public testing::Test,
base::MessageLoop message_loop_;
MockPersonalDataManager personal_data_;
- MockAutofillClient autofill_client_;
+ TestAutofillClient autofill_client_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
PaymentsClient payments_client_;
- MockDelegate delegate_;
+ MockResultDelegate result_delegate_;
+ MockUIDelegate ui_delegate_;
FullCardRequest request_;
DISALLOW_COPY_AND_ASSIGN(FullCardRequestTest);
@@ -134,96 +136,106 @@ MATCHER_P4(CardMatches, record_type, number, month, year, "") {
// Verify getting the full PAN and the CVC for a masked server card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCard) {
- EXPECT_CALL(*delegate(),
+ EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify getting the CVC for a local card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForLocalCard) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::LOCAL_CARD, "4111"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(
+ *result_delegate(),
+ OnFullCardRequestSucceeded(CardMatches(CreditCard::LOCAL_CARD, "4111"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
CreditCard card;
test::SetCreditCardInfo(&card, nullptr, "4111", "12", "2050");
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify getting the CVC for an unmasked server card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForFullServerCard) {
- EXPECT_CALL(*delegate(),
+ EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "server_id");
test::SetCreditCardInfo(&full_server_card, nullptr, "4111", "12", "2050");
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify getting the CVC for an unmasked server card with EXPIRED server
// status.
TEST_F(FullCardRequestTest,
GetFullCardPanAndCvcForFullServerCardInExpiredStatus) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111",
- "12", "2051"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestSucceeded(
+ CardMatches(CreditCard::FULL_SERVER_CARD,
+ "4111", "12", "2051"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(), UpdateServerCreditCard(_)).Times(0);
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "server_id");
test::SetCreditCardInfo(&full_server_card, nullptr, "4111", "12", "2050");
full_server_card.SetServerStatus(CreditCard::EXPIRED);
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
response.exp_year = base::ASCIIToUTF16("2051");
response.exp_month = base::ASCIIToUTF16("12");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify getting the CVC for an unmasked server card with OK status, but
// expiration date in the past.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForExpiredFullServerCard) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111",
- "12", "2051"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestSucceeded(
+ CardMatches(CreditCard::FULL_SERVER_CARD,
+ "4111", "12", "2051"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(), UpdateServerCreditCard(_)).Times(0);
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
base::Time::Exploded today;
base::Time::Now().LocalExplode(&today);
@@ -232,203 +244,221 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForExpiredFullServerCard) {
base::StringPrintf("%d", today.year - 1).c_str());
full_server_card.SetServerStatus(CreditCard::OK);
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
response.exp_year = base::ASCIIToUTF16("2051");
response.exp_month = base::ASCIIToUTF16("12");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Only one request at a time should be allowed.
TEST_F(FullCardRequestTest, OneRequestAtATime) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed());
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(_)).Times(0);
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed());
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(), OnUnmaskVerificationResult(_)).Times(0);
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id_1"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id_2"),
- AutofillClient::UNMASK_FOR_PAYMENT_REQUEST, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_PAYMENT_REQUEST,
+ result_delegate()->AsWeakPtr(), ui_delegate()->AsWeakPtr());
}
// After the first request completes, it's OK to start the second request.
TEST_F(FullCardRequestTest, SecondRequestOkAfterFirstFinished) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed()).Times(0);
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::LOCAL_CARD, "4111"),
- base::ASCIIToUTF16("123")))
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed()).Times(0);
+ EXPECT_CALL(
+ *result_delegate(),
+ OnFullCardRequestSucceeded(CardMatches(CreditCard::LOCAL_CARD, "4111"),
+ base::ASCIIToUTF16("123")))
.Times(2);
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _)).Times(2);
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS))
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _)).Times(2);
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS))
.Times(2);
CreditCard card;
test::SetCreditCardInfo(&card, nullptr, "4111", "12", "2050");
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskPromptClosed();
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
- ui_delegate()->OnUnmaskResponse(response);
- ui_delegate()->OnUnmaskPromptClosed();
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
+ card_unmask_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// If the user cancels the CVC prompt,
// FullCardRequest::Delegate::OnFullCardRequestFailed() should be invoked.
TEST_F(FullCardRequestTest, ClosePromptWithoutUserInput) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed());
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(_)).Times(0);
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed());
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(), OnUnmaskVerificationResult(_)).Times(0);
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
- ui_delegate()->OnUnmaskPromptClosed();
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// If the server provides an empty PAN with PERMANENT_FAILURE error,
// FullCardRequest::Delegate::OnFullCardRequestFailed() should be invoked.
TEST_F(FullCardRequestTest, PermanentFailure) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed());
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(),
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed());
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::PERMANENT_FAILURE));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::PERMANENT_FAILURE, "");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// If the server provides an empty PAN with NETWORK_ERROR error,
// FullCardRequest::Delegate::OnFullCardRequestFailed() should be invoked.
TEST_F(FullCardRequestTest, NetworkError) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed());
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(),
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed());
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::NETWORK_ERROR));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::NETWORK_ERROR, "");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// If the server provides an empty PAN with TRY_AGAIN_FAILURE, the user can
// manually cancel out of the dialog.
TEST_F(FullCardRequestTest, TryAgainFailureGiveUp) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed());
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(),
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed());
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::TRY_AGAIN_FAILURE));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::TRY_AGAIN_FAILURE, "");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// If the server provides an empty PAN with TRY_AGAIN_FAILURE, the user can
// correct their mistake and resubmit.
TEST_F(FullCardRequestTest, TryAgainFailureRetry) {
- EXPECT_CALL(*delegate(), OnFullCardRequestFailed()).Times(0);
- EXPECT_CALL(*delegate(),
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestFailed()).Times(0);
+ EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(),
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::TRY_AGAIN_FAILURE));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("789");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::TRY_AGAIN_FAILURE, "");
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify updating expiration date for a masked server card.
TEST_F(FullCardRequestTest, UpdateExpDateForMaskedServerCard) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111",
- "12", "2050"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestSucceeded(
+ CardMatches(CreditCard::FULL_SERVER_CARD,
+ "4111", "12", "2050"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
response.exp_month = base::ASCIIToUTF16("12");
response.exp_year = base::ASCIIToUTF16("2050");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify updating expiration date for an unmasked server card.
TEST_F(FullCardRequestTest, UpdateExpDateForFullServerCard) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111",
- "12", "2050"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestSucceeded(
+ CardMatches(CreditCard::FULL_SERVER_CARD,
+ "4111", "12", "2050"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "server_id");
test::SetCreditCardInfo(&full_server_card, nullptr, "4111", "10", "2000");
request()->GetFullCard(full_server_card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
response.exp_month = base::ASCIIToUTF16("12");
response.exp_year = base::ASCIIToUTF16("2050");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify updating expiration date for a local card.
TEST_F(FullCardRequestTest, UpdateExpDateForLocalCard) {
- EXPECT_CALL(*delegate(),
+ EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
CardMatches(CreditCard::LOCAL_CARD, "4111", "12", "2051"),
base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(),
UpdateCreditCard(
CardMatches(CreditCard::LOCAL_CARD, "4111", "12", "2051")));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
base::Time::Exploded today;
base::Time::Now().LocalExplode(&today);
@@ -436,80 +466,87 @@ TEST_F(FullCardRequestTest, UpdateExpDateForLocalCard) {
test::SetCreditCardInfo(&card, nullptr, "4111", "10",
base::StringPrintf("%d", today.year - 1).c_str());
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
response.exp_month = base::ASCIIToUTF16("12");
response.exp_year = base::ASCIIToUTF16("2051");
- ui_delegate()->OnUnmaskResponse(response);
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify saving full PAN on disk.
TEST_F(FullCardRequestTest, SaveRealPan) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111",
- "12", "2050"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*result_delegate(), OnFullCardRequestSucceeded(
+ CardMatches(CreditCard::FULL_SERVER_CARD,
+ "4111", "12", "2050"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(),
UpdateServerCreditCard(CardMatches(CreditCard::FULL_SERVER_CARD,
"4111", "12", "2050")));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
response.exp_month = base::ASCIIToUTF16("12");
response.exp_year = base::ASCIIToUTF16("2050");
response.should_store_pan = true;
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify getting full PAN and CVC for PaymentRequest.
TEST_F(FullCardRequestTest, UnmaskForPaymentRequest) {
- EXPECT_CALL(*delegate(),
+ EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_PAYMENT_REQUEST, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_PAYMENT_REQUEST,
+ result_delegate()->AsWeakPtr(), ui_delegate()->AsWeakPtr());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
OnDidGetRealPan(AutofillClient::SUCCESS, "4111");
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
}
// Verify that FullCardRequest::IsGettingFullCard() is true until the server
// returns the full PAN for a masked card.
TEST_F(FullCardRequestTest, IsGettingFullCardForMaskedServerCard) {
- EXPECT_CALL(*delegate(),
+ EXPECT_CALL(*result_delegate(),
OnFullCardRequestSucceeded(
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
EXPECT_FALSE(request()->IsGettingFullCard());
request()->GetFullCard(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
- AutofillClient::UNMASK_FOR_AUTOFILL, delegate()->AsWeakPtr());
+ AutofillClient::UNMASK_FOR_AUTOFILL, result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
EXPECT_TRUE(request()->IsGettingFullCard());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
EXPECT_TRUE(request()->IsGettingFullCard());
@@ -517,7 +554,7 @@ TEST_F(FullCardRequestTest, IsGettingFullCardForMaskedServerCard) {
EXPECT_FALSE(request()->IsGettingFullCard());
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
EXPECT_FALSE(request()->IsGettingFullCard());
}
@@ -525,28 +562,31 @@ TEST_F(FullCardRequestTest, IsGettingFullCardForMaskedServerCard) {
// Verify that FullCardRequest::IsGettingFullCard() is true until the user types
// in the CVC for a card that is not masked.
TEST_F(FullCardRequestTest, IsGettingFullCardForLocalCard) {
- EXPECT_CALL(*delegate(), OnFullCardRequestSucceeded(
- CardMatches(CreditCard::LOCAL_CARD, "4111"),
- base::ASCIIToUTF16("123")));
- EXPECT_CALL(*client(), ShowUnmaskPrompt(_, _, _));
- EXPECT_CALL(*client(), OnUnmaskVerificationResult(AutofillClient::SUCCESS));
+ EXPECT_CALL(
+ *result_delegate(),
+ OnFullCardRequestSucceeded(CardMatches(CreditCard::LOCAL_CARD, "4111"),
+ base::ASCIIToUTF16("123")));
+ EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
+ EXPECT_CALL(*ui_delegate(),
+ OnUnmaskVerificationResult(AutofillClient::SUCCESS));
EXPECT_FALSE(request()->IsGettingFullCard());
CreditCard card;
test::SetCreditCardInfo(&card, nullptr, "4111", "12", "2050");
request()->GetFullCard(card, AutofillClient::UNMASK_FOR_AUTOFILL,
- delegate()->AsWeakPtr());
+ result_delegate()->AsWeakPtr(),
+ ui_delegate()->AsWeakPtr());
EXPECT_TRUE(request()->IsGettingFullCard());
CardUnmaskDelegate::UnmaskResponse response;
response.cvc = base::ASCIIToUTF16("123");
- ui_delegate()->OnUnmaskResponse(response);
+ card_unmask_delegate()->OnUnmaskResponse(response);
EXPECT_FALSE(request()->IsGettingFullCard());
- ui_delegate()->OnUnmaskPromptClosed();
+ card_unmask_delegate()->OnUnmaskPromptClosed();
EXPECT_FALSE(request()->IsGettingFullCard());
}
diff --git a/chromium/components/autofill/core/browser/payments/payments_service_url.cc b/chromium/components/autofill/core/browser/payments/payments_service_url.cc
index 2ea46233df0..f545e9a16d7 100644
--- a/chromium/components/autofill/core/browser/payments/payments_service_url.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_service_url.cc
@@ -21,10 +21,10 @@
namespace autofill {
namespace {
-const char kProdPaymentsServiceUrl[] = "https://wallet.google.com/";
+const char kProdPaymentsServiceUrl[] = "https://payments.google.com/";
const char kSandboxPaymentsSecureServiceUrl[] =
- "https://wallet-web.sandbox.google.com/";
+ "https://payments.sandbox.google.com/";
} // namespace
@@ -46,14 +46,13 @@ GURL GetBaseSecureUrl() {
GURL GetManageInstrumentsUrl(size_t user_index) {
std::string path =
- base::StringPrintf("manage/w/%" PRIuS "/paymentMethods", user_index);
+ base::StringPrintf("u/%" PRIuS "#paymentMethods", user_index);
return GetBaseSecureUrl().Resolve(path);
}
GURL GetManageAddressesUrl(size_t user_index) {
- std::string path =
- base::StringPrintf("manage/w/%" PRIuS "/settings/addresses", user_index);
- return GetBaseSecureUrl().Resolve(path);
+ // Billing addresses are now managed as a part of the payment instrument.
+ return GetManageInstrumentsUrl(user_index);
}
} // namespace payments
diff --git a/chromium/components/autofill/core/browser/payments/payments_service_url_unittest.cc b/chromium/components/autofill/core/browser/payments/payments_service_url_unittest.cc
index 09dc91b5b86..8cdc5001257 100644
--- a/chromium/components/autofill/core/browser/payments/payments_service_url_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_service_url_unittest.cc
@@ -15,21 +15,21 @@ TEST(PaymentsServiceSandboxUrl, CheckSandboxUrls) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kWalletServiceUseSandbox, "1");
- EXPECT_EQ("https://wallet-web.sandbox.google.com/manage/w/1/paymentMethods",
- GetManageInstrumentsUrl(1).spec());
- EXPECT_EQ("https://wallet-web.sandbox.google.com/manage/w/1/settings/"
- "addresses",
- GetManageAddressesUrl(1).spec());
+ const char kExpectedSandboxURL[] =
+ "https://payments.sandbox.google.com/u/1#paymentMethods";
+
+ EXPECT_EQ(kExpectedSandboxURL, GetManageInstrumentsUrl(1).spec());
+ EXPECT_EQ(kExpectedSandboxURL, GetManageAddressesUrl(1).spec());
}
TEST(PaymentsServiceSandboxUrl, CheckProdUrls) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kWalletServiceUseSandbox, "0");
- EXPECT_EQ("https://wallet.google.com/manage/w/1/paymentMethods",
- GetManageInstrumentsUrl(1).spec());
- EXPECT_EQ("https://wallet.google.com/manage/w/1/settings/addresses",
- GetManageAddressesUrl(1).spec());
+ const char kExpectedURL[] = "https://payments.google.com/u/1#paymentMethods";
+
+ EXPECT_EQ(kExpectedURL, GetManageInstrumentsUrl(1).spec());
+ EXPECT_EQ(kExpectedURL, GetManageAddressesUrl(1).spec());
}
} // namespace payments
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index 88096ec268a..1ea5a2f555f 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -34,6 +34,7 @@
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
@@ -54,6 +55,9 @@ using ::i18n::addressinput::AddressField;
using ::i18n::addressinput::GetStreetAddressLinesAsSingleLine;
using ::i18n::addressinput::STREET_ADDRESS;
+// The length of a local profile GUID.
+const int LOCAL_GUID_LENGTH = 36;
+
template<typename T>
class FormGroupMatchesByGUIDFunctor {
public:
@@ -254,15 +258,15 @@ const char kFrecencyFieldTrialName[] = "AutofillProfileOrderByFrecency";
const char kFrecencyFieldTrialLimitParam[] = "limit";
PersonalDataManager::PersonalDataManager(const std::string& app_locale)
- : database_(NULL),
+ : database_(nullptr),
is_data_loaded_(false),
pending_profiles_query_(0),
pending_server_profiles_query_(0),
pending_creditcards_query_(0),
pending_server_creditcards_query_(0),
app_locale_(app_locale),
- pref_service_(NULL),
- account_tracker_(NULL),
+ pref_service_(nullptr),
+ account_tracker_(nullptr),
is_off_the_record_(false),
has_logged_profile_count_(false),
has_logged_local_credit_card_count_(false),
@@ -373,21 +377,6 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
} else {
ReceiveLoadedDbValues(h, result.get(), &pending_server_profiles_query_,
&server_profiles_);
-
- if (!server_profiles_.empty()) {
- std::string account_id = signin_manager_->GetAuthenticatedAccountId();
- base::string16 email =
- base::UTF8ToUTF16(
- account_tracker_->GetAccountInfo(account_id).email);
-
- // User may have signed out during the fulfillment of the web data
- // request, in which case there is no point updating
- // |server_profiles_| as it will be cleared.
- if (!email.empty()) {
- for (auto& profile : server_profiles_)
- profile->SetRawInfo(EMAIL_ADDRESS, email);
- }
- }
}
break;
case AUTOFILL_CREDITCARDS_RESULT:
@@ -423,6 +412,7 @@ void PersonalDataManager::OnWebDataServiceRequestDone(
}
void PersonalDataManager::AutofillMultipleChanged() {
+ has_synced_new_data_ = true;
Refresh();
}
@@ -554,10 +544,16 @@ void PersonalDataManager::UpdateProfile(const AutofillProfile& profile) {
AutofillProfile* PersonalDataManager::GetProfileByGUID(
const std::string& guid) {
- const std::vector<AutofillProfile*>& profiles = GetProfiles();
+ return GetProfileFromProfilesByGUID(guid, GetProfiles());
+}
+
+// static
+AutofillProfile* PersonalDataManager::GetProfileFromProfilesByGUID(
+ const std::string& guid,
+ const std::vector<AutofillProfile*>& profiles) {
std::vector<AutofillProfile*>::const_iterator iter =
FindElementByGUID<AutofillProfile>(profiles, guid);
- return (iter != profiles.end()) ? *iter : NULL;
+ return iter != profiles.end() ? *iter : nullptr;
}
void PersonalDataManager::AddCreditCard(const CreditCard& credit_card) {
@@ -726,7 +722,7 @@ CreditCard* PersonalDataManager::GetCreditCardByGUID(const std::string& guid) {
const std::vector<CreditCard*>& credit_cards = GetCreditCards();
std::vector<CreditCard*>::const_iterator iter =
FindElementByGUID<CreditCard>(credit_cards, guid);
- return (iter != credit_cards.end()) ? *iter : NULL;
+ return iter != credit_cards.end() ? *iter : nullptr;
}
void PersonalDataManager::GetNonEmptyTypes(
@@ -752,6 +748,13 @@ std::vector<AutofillProfile*> PersonalDataManager::web_profiles() const {
return result;
}
+std::vector<AutofillProfile*> PersonalDataManager::GetServerProfiles() const {
+ std::vector<AutofillProfile*> result;
+ for (const auto& profile : server_profiles_)
+ result.push_back(profile.get());
+ return result;
+}
+
std::vector<CreditCard*> PersonalDataManager::GetLocalCreditCards() const {
std::vector<CreditCard*> result;
for (const auto& card : local_credit_cards_)
@@ -770,10 +773,6 @@ const std::vector<CreditCard*>& PersonalDataManager::GetCreditCards() const {
return credit_cards_;
}
-bool PersonalDataManager::HasServerData() const {
- return !server_credit_cards_.empty() || !server_profiles_.empty();
-}
-
void PersonalDataManager::Refresh() {
LoadProfiles();
LoadCreditCards();
@@ -784,7 +783,7 @@ const std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest()
std::vector<AutofillProfile*> profiles = GetProfiles(true);
// Rank the suggestions by frecency (see AutofillDataModel for details).
- base::Time comparison_time = base::Time::Now();
+ base::Time comparison_time = AutofillClock::Now();
std::sort(profiles.begin(), profiles.end(),
[comparison_time](const AutofillDataModel* a,
const AutofillDataModel* b) {
@@ -908,7 +907,7 @@ const std::vector<CreditCard*> PersonalDataManager::GetCreditCardsToSuggest()
// Rank the cards by frecency (see AutofillDataModel for details). All expired
// cards should be suggested last, also by frecency.
- base::Time comparison_time = base::Time::Now();
+ base::Time comparison_time = AutofillClock::Now();
std::stable_sort(cards_to_suggest.begin(), cards_to_suggest.end(),
[comparison_time](const CreditCard* a, const CreditCard* b) {
bool a_is_expired = a->IsExpired(comparison_time);
@@ -943,7 +942,7 @@ void PersonalDataManager::SetPrefService(PrefService* pref_service) {
enabled_pref_.reset(new BooleanPrefMember);
wallet_enabled_pref_.reset(new BooleanPrefMember);
pref_service_ = pref_service;
- // |pref_service_| can be NULL in tests.
+ // |pref_service_| can be nullptr in tests.
if (pref_service_) {
enabled_pref_->Init(prefs::kAutofillEnabled, pref_service_,
base::Bind(&PersonalDataManager::EnabledPrefChanged,
@@ -991,7 +990,7 @@ std::string PersonalDataManager::MergeProfile(
// verified profiles get deduped among themselves before reaching the verified
// profiles.
// TODO(crbug.com/620521): Remove the check for verified from the sort.
- base::Time comparison_time = base::Time::Now();
+ base::Time comparison_time = AutofillClock::Now();
std::sort(existing_profiles->begin(), existing_profiles->end(),
[comparison_time](const std::unique_ptr<AutofillProfile>& a,
const std::unique_ptr<AutofillProfile>& b) {
@@ -1024,7 +1023,7 @@ std::string PersonalDataManager::MergeProfile(
// recently. After writing to the database and refreshing the local copies
// the profile will have a very slightly newer time reflecting what's
// actually stored in the database.
- existing_profile->set_modification_date(base::Time::Now());
+ existing_profile->set_modification_date(AutofillClock::Now());
}
merged_profiles->push_back(*existing_profile);
}
@@ -1034,7 +1033,7 @@ std::string PersonalDataManager::MergeProfile(
merged_profiles->push_back(new_profile);
// Similar to updating merged profiles above, set the modification date on
// new profiles.
- merged_profiles->back().set_modification_date(base::Time::Now());
+ merged_profiles->back().set_modification_date(AutofillClock::Now());
AutofillMetrics::LogProfileActionOnFormSubmitted(
AutofillMetrics::NEW_PROFILE_CREATED);
}
@@ -1239,15 +1238,6 @@ std::string PersonalDataManager::SaveImportedProfile(
if (is_off_the_record_)
return std::string();
- // Don't save a web profile if the data in the profile is a subset of a
- // server profile, but do record the fact that it was used.
- for (const auto& profile : server_profiles_) {
- if (imported_profile.IsSubsetOf(*profile, app_locale_)) {
- RecordUseOf(*profile);
- return profile->guid();
- }
- }
-
std::vector<AutofillProfile> profiles;
std::string guid =
MergeProfile(imported_profile, &web_profiles_, app_locale_, &profiles);
@@ -1258,6 +1248,13 @@ std::string PersonalDataManager::SaveImportedProfile(
void PersonalDataManager::NotifyPersonalDataChanged() {
for (PersonalDataManagerObserver& observer : observers_)
observer.OnPersonalDataChanged();
+
+ // If new data was synced, try to convert new server profiles and update
+ // server cards.
+ if (has_synced_new_data_) {
+ has_synced_new_data_ = false;
+ ConvertWalletAddressesAndUpdateWalletCards();
+ }
}
std::string PersonalDataManager::SaveImportedCreditCard(
@@ -1575,10 +1572,6 @@ const std::vector<AutofillProfile*>& PersonalDataManager::GetProfiles(
profiles_.clear();
for (const auto& profile : web_profiles_)
profiles_.push_back(profile.get());
- if (pref_service_->GetBoolean(prefs::kAutofillWalletImportEnabled)) {
- for (const auto& profile : server_profiles_)
- profiles_.push_back(profile.get());
- }
return profiles_;
}
@@ -1618,8 +1611,13 @@ std::vector<Suggestion> PersonalDataManager::GetSuggestionsForCards(
// cardholder name. The label should never repeat the value.
if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
suggestion->value = credit_card->TypeAndLastFourDigits();
- suggestion->label = credit_card->GetInfo(
- AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
+ if (IsAutofillCreditCardLastUsedDateDisplayExperimentEnabled()) {
+ suggestion->label =
+ credit_card->GetLastUsedDateForDisplay(app_locale_);
+ } else {
+ suggestion->label = credit_card->GetInfo(
+ AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale_);
+ }
if (IsAutofillCreditCardPopupLayoutExperimentEnabled())
ModifyAutofillCreditCardSuggestion(suggestion);
} else if (credit_card->number().empty()) {
@@ -1661,7 +1659,8 @@ void PersonalDataManager::ApplyProfileUseDatesFix() {
bool has_changed_data = false;
for (AutofillProfile* profile : web_profiles()) {
if (profile->use_date() == base::Time()) {
- profile->set_use_date(base::Time::Now() - base::TimeDelta::FromDays(14));
+ profile->set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(14));
has_changed_data = true;
}
profiles.push_back(*profile);
@@ -1742,7 +1741,7 @@ void PersonalDataManager::DedupeProfiles(
// profiles, so the loop can be stopped when we reach those. However they need
// to be in the vector because an unverified profile trying to merge into a
// similar verified profile will be discarded.
- base::Time comparison_time = base::Time::Now();
+ base::Time comparison_time = AutofillClock::Now();
std::sort(existing_profiles->begin(), existing_profiles->end(),
[comparison_time](const std::unique_ptr<AutofillProfile>& a,
const std::unique_ptr<AutofillProfile>& b) {
@@ -1820,7 +1819,7 @@ void PersonalDataManager::UpdateCardsBillingAddressReference(
C -> D
*/
- for (auto& credit_card : local_credit_cards_) {
+ for (auto* credit_card : GetCreditCards()) {
// If the credit card is not associated with a billing address, skip it.
if (credit_card->billing_address_id().empty())
break;
@@ -1847,9 +1846,176 @@ void PersonalDataManager::UpdateCardsBillingAddressReference(
// If the card was modified, apply the changes to the database.
if (was_modified) {
- database_->UpdateCreditCard(*credit_card);
+ if (credit_card->record_type() == CreditCard::LOCAL_CARD)
+ database_->UpdateCreditCard(*credit_card);
+ else
+ database_->UpdateServerCardMetadata(*credit_card);
+ }
+ }
+}
+
+void PersonalDataManager::ConvertWalletAddressesAndUpdateWalletCards() {
+ // Copy the local profiles into a vector<AutofillProfile>. Theses are the
+ // existing profiles. Get them sorted in decreasing order of frecency, so the
+ // "best" profiles are checked first. Put the verified profiles last so the
+ // server addresses have a chance to merge into the non-verified local
+ // profiles.
+ std::vector<AutofillProfile> local_profiles;
+ for (AutofillProfile* existing_profile : GetProfilesToSuggest()) {
+ local_profiles.push_back(*existing_profile);
+ }
+
+ // Since we are already iterating on all the server profiles to convert Wallet
+ // addresses and we will need to access them by guid later to update the
+ // Wallet cards, create a map here.
+ std::unordered_map<std::string, AutofillProfile*> server_id_profiles_map;
+
+ // Create the map used to update credit card's billing addresses after the
+ // convertion/merge.
+ std::unordered_map<std::string, std::string> guids_merge_map;
+
+ bool has_converted_addresses = ConvertWalletAddressesToLocalProfiles(
+ &local_profiles, &server_id_profiles_map, &guids_merge_map);
+ bool should_update_cards = UpdateWalletCardsAlreadyConvertedBillingAddresses(
+ &local_profiles, &server_id_profiles_map, &guids_merge_map);
+
+ if (has_converted_addresses) {
+ // Save the local profiles to the DB.
+ SetProfiles(&local_profiles);
+ }
+
+ if (should_update_cards || has_converted_addresses) {
+ // Update the credit cards billing address relationship.
+ UpdateCardsBillingAddressReference(guids_merge_map);
+
+ // Force a reload of the profiles and cards.
+ Refresh();
+ }
+}
+
+bool PersonalDataManager::ConvertWalletAddressesToLocalProfiles(
+ std::vector<AutofillProfile>* local_profiles,
+ std::unordered_map<std::string, AutofillProfile*>* server_id_profiles_map,
+ std::unordered_map<std::string, std::string>* guids_merge_map) {
+ bool has_converted_addresses = false;
+ for (std::unique_ptr<AutofillProfile>& wallet_address : server_profiles_) {
+ // Add the profile to the map.
+ server_id_profiles_map->insert(
+ std::make_pair(wallet_address->server_id(), wallet_address.get()));
+
+ // If the address has not been converted yet, convert it.
+ if (!wallet_address->has_converted()) {
+ // Try to merge the server address into a similar local profile, or create
+ // a new local profile if no similar profile is found.
+ std::string address_guid =
+ MergeServerAddressesIntoProfiles(*wallet_address, local_profiles);
+
+ // Update the map to transfer the billing address relationship from the
+ // server address to the converted/merged local profile.
+ guids_merge_map->insert(std::pair<std::string, std::string>(
+ wallet_address->server_id(), address_guid));
+
+ // Update the wallet addresses metadata to record the conversion.
+ wallet_address->set_has_converted(true);
+ database_->UpdateServerAddressMetadata(*wallet_address);
+
+ has_converted_addresses = true;
+ }
+ }
+
+ return has_converted_addresses;
+}
+
+bool PersonalDataManager::UpdateWalletCardsAlreadyConvertedBillingAddresses(
+ std::vector<AutofillProfile>* local_profiles,
+ std::unordered_map<std::string, AutofillProfile*>* server_id_profiles_map,
+ std::unordered_map<std::string, std::string>* guids_merge_map) {
+ // Look for server cards that still refer to server addresses but for which
+ // there is no mapping. This can happen if it's a new card for which the
+ // billing address has already been converted. This should be a no-op for most
+ // situations. Otherwise, it should affect only one Wallet card, sinces users
+ // do not add a lot of credit cards.
+ AutofillProfileComparator comparator(app_locale_);
+ bool should_update_cards = false;
+ for (std::unique_ptr<CreditCard>& wallet_card : server_credit_cards_) {
+ std::string billing_address_id = wallet_card->billing_address_id();
+
+ // If billing address refers to a server id and that id is not a key in the
+ // guids_merge_map, it means that the card is new but the address was
+ // already converted. Look for the matching converted profile.
+ if (!billing_address_id.empty() &&
+ billing_address_id.length() != LOCAL_GUID_LENGTH &&
+ guids_merge_map->find(billing_address_id) == guids_merge_map->end()) {
+ // Get the profile.
+ auto it = server_id_profiles_map->find(billing_address_id);
+ if (it != server_id_profiles_map->end()) {
+ AutofillProfile* billing_address = it->second;
+
+ // Look for a matching local profile (DO NOT MERGE).
+ bool matching_profile_found = false;
+ for (auto& local_profile : *local_profiles) {
+ if (!matching_profile_found &&
+ comparator.AreMergeable(*billing_address, local_profile)) {
+ matching_profile_found = true;
+
+ // The Wallet address matches this local profile. Add this to the
+ // merge mapping.
+ guids_merge_map->insert(std::pair<std::string, std::string>(
+ billing_address_id, local_profile.guid()));
+ should_update_cards = true;
+ }
+ }
+ }
}
}
+
+ return should_update_cards;
+}
+
+// TODO(crbug.com/687975): Reuse MergeProfiles in this function.
+std::string PersonalDataManager::MergeServerAddressesIntoProfiles(
+ const AutofillProfile& server_address,
+ std::vector<AutofillProfile>* existing_profiles) {
+ // Set to true if |existing_profiles| already contains an equivalent profile.
+ bool matching_profile_found = false;
+ std::string guid = server_address.guid();
+
+ // If there is already a local profile that is very similar, merge in any
+ // missing values. Only merge with the first match.
+ AutofillProfileComparator comparator(app_locale_);
+ for (auto& local_profile : *existing_profiles) {
+ if (!matching_profile_found &&
+ comparator.AreMergeable(server_address, local_profile) &&
+ local_profile.SaveAdditionalInfo(server_address, app_locale_)) {
+ matching_profile_found = true;
+ local_profile.set_modification_date(AutofillClock::Now());
+ guid = local_profile.guid();
+ AutofillMetrics::LogWalletAddressConversionType(
+ AutofillMetrics::CONVERTED_ADDRESS_MERGED);
+ }
+ }
+
+ // If the server address was not merged with a local profile, add it to the
+ // list.
+ if (!matching_profile_found) {
+ existing_profiles->push_back(server_address);
+ // Set the profile as being local.
+ existing_profiles->back().set_record_type(AutofillProfile::LOCAL_PROFILE);
+ existing_profiles->back().set_modification_date(AutofillClock::Now());
+
+ // Wallet addresses don't have an email address, use the one from the
+ // currently signed-in account.
+ std::string account_id = signin_manager_->GetAuthenticatedAccountId();
+ base::string16 email =
+ base::UTF8ToUTF16(account_tracker_->GetAccountInfo(account_id).email);
+ if (!email.empty())
+ existing_profiles->back().SetRawInfo(EMAIL_ADDRESS, email);
+
+ AutofillMetrics::LogWalletAddressConversionType(
+ AutofillMetrics::CONVERTED_ADDRESS_ADDED);
+ }
+
+ return guid;
}
} // 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 165862f6217..a7f9808e53a 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -136,11 +136,17 @@ class PersonalDataManager : public KeyedService,
// Removes the profile or credit card represented by |guid|.
virtual void RemoveByGUID(const std::string& guid);
- // Returns the profile with the specified |guid|, or NULL if there is no
+ // Returns the profile with the specified |guid|, or nullptr if there is no
// profile with the specified |guid|. Both web and auxiliary profiles may
// be returned.
AutofillProfile* GetProfileByGUID(const std::string& guid);
+ // Returns the profile with the specified |guid| from the given |profiles|, or
+ // nullptr if there is no profile with the specified |guid|.
+ static AutofillProfile* GetProfileFromProfilesByGUID(
+ const std::string& guid,
+ const std::vector<AutofillProfile*>& profiles);
+
// Adds |credit_card| to the web database.
void AddCreditCard(const CreditCard& credit_card);
@@ -168,7 +174,7 @@ class PersonalDataManager : public KeyedService,
// Sets a server credit card for test.
void AddServerCreditCardForTest(std::unique_ptr<CreditCard> credit_card);
- // Returns the credit card with the specified |guid|, or NULL if there is
+ // Returns the credit card with the specified |guid|, or nullptr if there is
// no credit card with the specified |guid|.
virtual CreditCard* GetCreditCardByGUID(const std::string& guid);
@@ -183,18 +189,18 @@ 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. |GetProfiles()| returns both web and
- // auxiliary profiles. |web_profiles()| returns only web profiles.
+ // 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;
+ // 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;
- // Returns true if there is some data synced from Wallet.
- bool HasServerData() const;
-
// Returns the profiles to suggest to the user, ordered by frecency.
const std::vector<AutofillProfile*> GetProfilesToSuggest() const;
@@ -316,6 +322,21 @@ class PersonalDataManager : public KeyedService,
ApplyDedupingRoutine_OncePerVersion);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
ApplyDedupingRoutine_MultipleDedupes);
+ FRIEND_TEST_ALL_PREFIXES(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_NewProfile);
+ FRIEND_TEST_ALL_PREFIXES(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_MergedProfile);
+ FRIEND_TEST_ALL_PREFIXES(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_NewCard_AddressAlreadyConverted);
+ FRIEND_TEST_ALL_PREFIXES(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_AlreadyConverted);
+ FRIEND_TEST_ALL_PREFIXES(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_MultipleSimilarWalletAddresses);
friend class autofill::AutofillInteractiveTest;
friend class autofill::AutofillTest;
friend class autofill::PersonalDataManagerFactory;
@@ -416,7 +437,7 @@ class PersonalDataManager : public KeyedService,
std::vector<std::unique_ptr<CreditCard>> server_credit_cards_;
// A combination of local and server credit cards. The pointers are owned
- // by the local/sverver_credit_cards_ vectors.
+ // by the local/server_credit_cards_ vectors.
mutable std::vector<CreditCard*> credit_cards_;
// When the manager makes a request from WebDataServiceBase, the database
@@ -462,7 +483,7 @@ class PersonalDataManager : public KeyedService,
// 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.
- const std::vector<AutofillProfile*>& GetProfiles(
+ virtual const std::vector<AutofillProfile*>& GetProfiles(
bool record_metrics) const;
// Returns credit card suggestions based on the |cards_to_suggest| and the
@@ -502,6 +523,41 @@ class PersonalDataManager : public KeyedService,
void UpdateCardsBillingAddressReference(
const std::unordered_map<std::string, std::string>& guids_merge_map);
+ // Converts the Wallet addresses to local autofill profiles. This should be
+ // called after all the syncable data has been processed (local cards and
+ // profiles, Wallet data and metadata). Also updates Wallet cards' billing
+ // address id to point to the local profiles.
+ void ConvertWalletAddressesAndUpdateWalletCards();
+
+ // Converts the Wallet addresses into local profiles either by merging with an
+ // existing |local_profiles| of by adding a new one. Populates the
+ // |server_id_profiles_map| to be used when updating cards where the address
+ // was already converted. Also populates the |guids_merge_map| to keep the
+ // link between the Wallet address and the equivalent local profile (from
+ // merge or creation).
+ bool ConvertWalletAddressesToLocalProfiles(
+ std::vector<AutofillProfile>* local_profiles,
+ std::unordered_map<std::string, AutofillProfile*>* server_id_profiles_map,
+ std::unordered_map<std::string, std::string>* guids_merge_map);
+
+ // Goes through the Wallet cards to find cards where the billing address is a
+ // Wallet address which was already converted in a previous pass. Looks for a
+ // matching local profile and updates the |guids_merge_map| to make the card
+ // refert to it.
+ bool UpdateWalletCardsAlreadyConvertedBillingAddresses(
+ std::vector<AutofillProfile>* local_profiles,
+ std::unordered_map<std::string, AutofillProfile*>* server_id_profiles_map,
+ std::unordered_map<std::string, std::string>* guids_merge_map);
+
+ // Tries to merge the |server_address| into the |existing_profiles| if
+ // possible. Adds it to the list if no match is found. The existing profiles
+ // should be sorted by decreasing frecency outside of this method, since this
+ // will be called multiple times in a row. Returns the guid of the new or
+ // updated profile.
+ std::string MergeServerAddressesIntoProfiles(
+ const AutofillProfile& server_address,
+ std::vector<AutofillProfile>* existing_profiles);
+
const std::string app_locale_;
// The default country code for new addresses.
@@ -541,6 +597,9 @@ class PersonalDataManager : public KeyedService,
// True if autofill profile cleanup needs to be performed.
bool is_autofill_profile_cleanup_pending_ = false;
+ // Whether new information was received from the sync server.
+ bool has_synced_new_data_ = false;
+
#if defined(OS_ANDROID)
// The context for the request to be used to fetch libaddressinput's address
// validation rules.
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 18bb0aebdd4..6bb7a52b7e0 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -17,23 +17,27 @@
#include "base/command_line.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
+#include "base/i18n/time_formatting.h"
#include "base/memory/ptr_util.h"
-#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/histogram_tester.h"
+#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
@@ -44,8 +48,7 @@
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/signin/core/common/signin_pref_names.h"
-#include "components/variations/entropy_provider.h"
-#include "components/variations/variations_associated_data.h"
+#include "components/variations/variations_params_manager.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_database_service.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -66,6 +69,10 @@ const std::string kUTF8MidlineEllipsis =
"\xE2\x80\xA2\xE2\x80\x86"
"\xE2\x80\xA2\xE2\x80\x86";
+const base::Time kArbitraryTime = base::Time::FromDoubleT(25);
+const base::Time kSomeLaterTime = base::Time::FromDoubleT(1000);
+const base::Time kMuchLaterTime = base::Time::FromDoubleT(5000);
+
ACTION(QuitMainMessageLoop) {
base::MessageLoop::current()->QuitWhenIdle();
}
@@ -146,9 +153,6 @@ class PersonalDataManagerTest : public testing::Test {
test::DisableSystemServices(prefs_.get());
ResetPersonalDataManager(USER_MODE_NORMAL);
- // There are no field trials enabled by default.
- field_trial_list_.reset();
-
// Reset the deduping pref to its default value.
personal_data_->pref_service_->SetInteger(
prefs::kAutofillLastVersionDeduped, 0);
@@ -263,13 +267,14 @@ class PersonalDataManagerTest : public testing::Test {
"347666888555" /* American Express */, "04",
"2999");
credit_card0.set_use_count(3);
- credit_card0.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ credit_card0.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
personal_data_->AddCreditCard(credit_card0);
CreditCard credit_card1("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
credit_card1.set_use_count(300);
- credit_card1.set_use_date(base::Time::Now() -
+ credit_card1.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(10));
test::SetCreditCardInfo(&credit_card1, "John Dillinger",
"423456789012" /* Visa */, "01", "2999");
@@ -278,7 +283,8 @@ class PersonalDataManagerTest : public testing::Test {
CreditCard credit_card2("002149C1-EE28-4213-A3B9-DA243FFF021B",
"https://www.example.com");
credit_card2.set_use_count(1);
- credit_card2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ credit_card2.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
test::SetCreditCardInfo(&credit_card2, "Bonnie Parker",
"518765432109" /* Mastercard */, "12", "2999");
personal_data_->AddCreditCard(credit_card2);
@@ -303,28 +309,6 @@ class PersonalDataManagerTest : public testing::Test {
imported_credit_card);
}
- // Sets up the profile order field trial group and parameter. Sets up the
- // suggestions limit parameter to |limit_param|.
- void EnableAutofillProfileLimitFieldTrial(const std::string& limit_param) {
- DCHECK(!limit_param.empty());
-
- // Clear the existing |field_trial_list_| and variation parameters.
- field_trial_list_.reset(NULL);
- field_trial_list_.reset(
- new base::FieldTrialList(
- base::MakeUnique<metrics::SHA1EntropyProvider>("foo")));
- variations::testing::ClearAllVariationParams();
-
- std::map<std::string, std::string> params;
- params[kFrecencyFieldTrialLimitParam] = limit_param;
- variations::AssociateVariationParams(kFrecencyFieldTrialName, "LimitToN",
- params);
-
- field_trial_ = base::FieldTrialList::CreateFieldTrial(
- kFrecencyFieldTrialName, "LimitToN");
- field_trial_->group();
- }
-
void SubmitFormAndExpectImportedCardWithData(const FormData& form,
const char* exp_name,
const char* exp_cc_num,
@@ -364,8 +348,7 @@ class PersonalDataManagerTest : public testing::Test {
PersonalDataLoadedObserverMock personal_data_observer_;
std::unique_ptr<PersonalDataManager> personal_data_;
- std::unique_ptr<base::FieldTrialList> field_trial_list_;
- scoped_refptr<base::FieldTrial> field_trial_;
+ variations::testing::VariationParamsManager variation_params_;
};
TEST_F(PersonalDataManagerTest, AddProfile) {
@@ -417,6 +400,10 @@ TEST_F(PersonalDataManagerTest, AddProfile) {
// Test that a new profile has its basic information set.
TEST_F(PersonalDataManagerTest, AddProfile_BasicInformation) {
+ // Create the test clock and set the time to a specific value.
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime);
+
// Add a profile to the database.
AutofillProfile profile(test::GetFullProfile());
profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("j@s.com"));
@@ -432,52 +419,8 @@ TEST_F(PersonalDataManagerTest, AddProfile_BasicInformation) {
// Make sure the use count and use date were set.
EXPECT_EQ(1U, results[0]->use_count());
- EXPECT_NE(base::Time(), results[0]->use_date());
- EXPECT_NE(base::Time(), results[0]->modification_date());
-}
-
-TEST_F(PersonalDataManagerTest, DontDuplicateServerProfile) {
- EnableWalletCardImport();
-
- std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, "a123"));
- test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
- "ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
- "77401", "US", "");
- // Wallet only provides a full name, so the above first and last names
- // will be ignored when the profile is written to the DB.
- server_profiles.back().SetRawInfo(NAME_FULL, ASCIIToUTF16("John Doe"));
- autofill_table_->SetServerProfiles(server_profiles);
- personal_data_->Refresh();
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
- base::RunLoop().Run();
- EXPECT_EQ(1U, personal_data_->GetProfiles().size());
-
- // Add profile with identical values. Duplicates should not get saved.
- AutofillProfile scraped_profile(base::GenerateGUID(),
- "https://www.example.com");
- test::SetProfileInfo(&scraped_profile, "John", "", "Doe", "", "ACME Corp",
- "500 Oak View", "Apt 8", "Houston", "TX", "77401", "US",
- "");
- EXPECT_TRUE(scraped_profile.IsSubsetOf(server_profiles.back(), "en-US"));
- std::string saved_guid = personal_data_->SaveImportedProfile(scraped_profile);
- EXPECT_NE(scraped_profile.guid(), saved_guid);
-
- personal_data_->Refresh();
- EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
- .WillOnce(QuitMainMessageLoop());
- base::RunLoop().Run();
-
- // Verify the non-addition.
- EXPECT_EQ(0U, personal_data_->web_profiles().size());
- ASSERT_EQ(1U, personal_data_->GetProfiles().size());
-
- // Verify that the server profile's use date was updated.
- const AutofillProfile* server_profile = personal_data_->GetProfiles()[0];
- EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
- base::Time::Now() - server_profile->use_date());
+ EXPECT_EQ(kArbitraryTime, results[0]->use_date());
+ EXPECT_EQ(kArbitraryTime, results[0]->modification_date());
}
// Tests that SaveImportedProfile sets the modification date on new profiles.
@@ -489,7 +432,7 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfileSetModificationDate) {
const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
ASSERT_EQ(1U, profiles.size());
EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
- base::Time::Now() - profiles[0]->modification_date());
+ AutofillClock::Now() - profiles[0]->modification_date());
}
TEST_F(PersonalDataManagerTest, AddUpdateRemoveProfiles) {
@@ -607,6 +550,10 @@ TEST_F(PersonalDataManagerTest, AddUpdateRemoveCreditCards) {
// Test that a new credit card has its basic information set.
TEST_F(PersonalDataManagerTest, AddCreditCard_BasicInformation) {
+ // Create the test clock and set the time to a specific value.
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime);
+
// Add a credit to the database.
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card, "John Dillinger",
@@ -623,8 +570,8 @@ TEST_F(PersonalDataManagerTest, AddCreditCard_BasicInformation) {
// Make sure the use count and use date were set.
EXPECT_EQ(1U, results[0]->use_count());
- EXPECT_NE(base::Time(), results[0]->use_date());
- EXPECT_NE(base::Time(), results[0]->modification_date());
+ EXPECT_EQ(kArbitraryTime, results[0]->use_date());
+ EXPECT_EQ(kArbitraryTime, results[0]->modification_date());
}
TEST_F(PersonalDataManagerTest, UpdateUnverifiedProfilesAndCreditCards) {
@@ -3416,7 +3363,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
profile3.set_use_count(5);
personal_data_->AddProfile(profile3);
@@ -3425,7 +3372,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
profile1.set_use_count(10);
personal_data_->AddProfile(profile1);
@@ -3434,7 +3381,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_Ranking) {
"johnwayne@me.xyz", "Fox",
"123 Zoo St.\nSecond Line\nThird line", "unit 5",
"Hollywood", "CA", "91601", "US", "12345678910");
- profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
+ profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(15));
profile2.set_use_count(300);
personal_data_->AddProfile(profile2);
@@ -3482,7 +3429,8 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_NumberOfSuggestions) {
EXPECT_EQ(3U, suggestions.size());
// Verify that only two profiles are suggested.
- EnableAutofillProfileLimitFieldTrial("2");
+ variation_params_.SetVariationParams(kFrecencyFieldTrialName,
+ {{kFrecencyFieldTrialLimitParam, "2"}});
suggestions = personal_data_->GetProfileSuggestions(
AutofillType(NAME_FIRST), base::string16(), false,
@@ -3495,7 +3443,8 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_NumberOfSuggestions) {
// than three profiles.
TEST_F(PersonalDataManagerTest,
GetProfileSuggestions_LimitIsMoreThanProfileSuggestions) {
- EnableAutofillProfileLimitFieldTrial("3");
+ variation_params_.SetVariationParams(kFrecencyFieldTrialName,
+ {{kFrecencyFieldTrialLimitParam, "3"}});
// Set up 2 different profiles.
AutofillProfile profile1(base::GenerateGUID(), "https://www.example.com");
@@ -3583,7 +3532,7 @@ TEST_F(PersonalDataManagerTest,
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999");
server_cards.back().set_use_count(2);
- server_cards.back().set_use_date(base::Time::Now() -
+ server_cards.back().set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(1));
server_cards.back().SetTypeForMaskedCard(kVisaCard);
@@ -3591,7 +3540,7 @@ TEST_F(PersonalDataManagerTest,
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999");
server_cards.back().set_use_count(6);
- server_cards.back().set_use_date(base::Time::Now() -
+ server_cards.back().set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(1));
test::SetServerCreditCards(autofill_table_, server_cards);
@@ -3632,14 +3581,16 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ExpiredCards) {
test::SetCreditCardInfo(&credit_card1, "Clyde Barrow",
"347666888555" /* American Express */, "04", "1999");
credit_card1.set_use_count(300);
- credit_card1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(10));
+ credit_card1.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(10));
personal_data_->AddCreditCard(credit_card1);
// Add an expired card with a lower frecency score.
CreditCard credit_card2("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
credit_card2.set_use_count(3);
- credit_card2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ credit_card2.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
test::SetCreditCardInfo(&credit_card2, "John Dillinger",
"423456789012" /* Visa */, "01", "1998");
personal_data_->AddCreditCard(credit_card2);
@@ -3675,13 +3626,15 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_NumberMissing) {
test::SetCreditCardInfo(&credit_card0, "Clyde Barrow",
"347666888555" /* American Express */, "04", "2999");
credit_card0.set_use_count(3);
- credit_card0.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ credit_card0.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
personal_data_->AddCreditCard(credit_card0);
CreditCard credit_card1("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
credit_card1.set_use_count(300);
- credit_card1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(10));
+ credit_card1.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(10));
test::SetCreditCardInfo(&credit_card1, "John Dillinger", "", "01", "2999");
personal_data_->AddCreditCard(credit_card1);
@@ -3718,7 +3671,7 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"9012" /* Visa */, "01", "2999");
server_cards.back().set_use_count(2);
- server_cards.back().set_use_date(base::Time::Now() -
+ server_cards.back().set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(15));
server_cards.back().SetTypeForMaskedCard(kVisaCard);
@@ -3728,7 +3681,7 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
test::SetCreditCardInfo(&server_cards.back(), "Bonnie Parker", "2109", "12",
"2999");
server_cards.back().set_use_count(3);
- server_cards.back().set_use_date(base::Time::Now() -
+ server_cards.back().set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(15));
server_cards.back().SetTypeForMaskedCard(kVisaCard);
@@ -3739,7 +3692,7 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "2999");
server_cards.back().set_use_count(1);
- server_cards.back().set_use_date(base::Time::Now() -
+ server_cards.back().set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(15));
test::SetServerCreditCards(autofill_table_, server_cards);
@@ -3826,7 +3779,7 @@ TEST_F(PersonalDataManagerTest,
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"423456789012" /* Visa */, "01", "2999");
local_card.set_use_count(3);
- local_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ local_card.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
credit_cards.push_back(&local_card);
// Create a full server card that is a duplicate of one of the local cards.
@@ -3834,7 +3787,7 @@ TEST_F(PersonalDataManagerTest,
test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
"423456789012" /* Visa */, "01", "2999");
full_server_card.set_use_count(1);
- full_server_card.set_use_date(base::Time::Now() -
+ full_server_card.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(15));
credit_cards.push_back(&full_server_card);
@@ -3853,7 +3806,7 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_LocalShadowsMasked) {
CreditCard local_card("1141084B-72D7-4B73-90CF-3D6AC154673B",
"https://www.example.com");
local_card.set_use_count(300);
- local_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(10));
+ local_card.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(10));
test::SetCreditCardInfo(&local_card, "Homer Simpson",
"423456789012" /* Visa */, "01", "2999");
credit_cards.push_back(&local_card);
@@ -3863,7 +3816,8 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_LocalShadowsMasked) {
test::SetCreditCardInfo(&masked_card, "Homer Simpson", "9012" /* Visa */,
"01", "2999");
masked_card.set_use_count(2);
- masked_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
+ masked_card.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(15));
masked_card.SetTypeForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
@@ -3883,7 +3837,7 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_FullServerAndMasked) {
test::SetCreditCardInfo(&full_server_card, "Homer Simpson",
"423456789012" /* Visa */, "01", "2999");
full_server_card.set_use_count(1);
- full_server_card.set_use_date(base::Time::Now() -
+ full_server_card.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(15));
credit_cards.push_back(&full_server_card);
@@ -3892,7 +3846,8 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_FullServerAndMasked) {
test::SetCreditCardInfo(&masked_card, "Homer Simpson", "9012" /* Visa */,
"01", "2999");
masked_card.set_use_count(2);
- masked_card.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
+ masked_card.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(15));
masked_card.SetTypeForMaskedCard(kVisaCard);
credit_cards.push_back(&masked_card);
@@ -3908,7 +3863,8 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
CreditCard credit_card2("002149C1-EE28-4213-A3B9-DA243FFF021B",
"https://www.example.com");
credit_card2.set_use_count(1);
- credit_card2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ credit_card2.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(1));
test::SetCreditCardInfo(&credit_card2, "Homer Simpson",
"518765432109" /* Mastercard */, "", "");
credit_cards.push_back(&credit_card2);
@@ -3917,7 +3873,8 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
CreditCard credit_card4(CreditCard::MASKED_SERVER_CARD, "b456");
test::SetCreditCardInfo(&credit_card4, "Homer Simpson", "2109", "12", "2999");
credit_card4.set_use_count(3);
- credit_card4.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
+ credit_card4.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(15));
credit_card4.SetTypeForMaskedCard(kVisaCard);
credit_cards.push_back(&credit_card4);
@@ -3927,7 +3884,8 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
test::SetCreditCardInfo(&credit_card5, "Homer Simpson",
"347666888555" /* American Express */, "04", "2999");
credit_card5.set_use_count(1);
- credit_card5.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(15));
+ credit_card5.set_use_date(AutofillClock::Now() -
+ base::TimeDelta::FromDays(15));
credit_cards.push_back(&credit_card5);
PersonalDataManager::DedupeCreditCardToSuggest(&credit_cards);
@@ -3935,38 +3893,39 @@ TEST_F(PersonalDataManagerTest, DedupeCreditCardToSuggest_DifferentCards) {
}
TEST_F(PersonalDataManagerTest, RecordUseOf) {
- base::Time creation_time = base::Time::FromTimeT(12345);
+ // Create the test clock and set the time to a specific value.
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime);
AutofillProfile profile(test::GetFullProfile());
- profile.set_use_date(creation_time);
- profile.set_modification_date(creation_time);
EXPECT_EQ(1U, profile.use_count());
- EXPECT_EQ(creation_time, profile.use_date());
- EXPECT_EQ(creation_time, profile.modification_date());
+ EXPECT_EQ(kArbitraryTime, profile.use_date());
+ EXPECT_EQ(kArbitraryTime, profile.modification_date());
personal_data_->AddProfile(profile);
CreditCard credit_card(base::GenerateGUID(), "https://www.example.com");
test::SetCreditCardInfo(&credit_card, "John Dillinger",
"423456789012" /* Visa */, "01", "2999");
- credit_card.set_use_date(creation_time);
- credit_card.set_modification_date(creation_time);
EXPECT_EQ(1U, credit_card.use_count());
- EXPECT_EQ(creation_time, credit_card.use_date());
- EXPECT_EQ(creation_time, credit_card.modification_date());
+ EXPECT_EQ(kArbitraryTime, credit_card.use_date());
+ EXPECT_EQ(kArbitraryTime, credit_card.modification_date());
personal_data_->AddCreditCard(credit_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::RunLoop().Run();
+ // Set the current time to another value.
+ test_clock.SetNow(kSomeLaterTime);
+
// Notify the PDM that the profile and credit card were used.
AutofillProfile* added_profile =
personal_data_->GetProfileByGUID(profile.guid());
ASSERT_TRUE(added_profile);
EXPECT_EQ(*added_profile, profile);
EXPECT_EQ(1U, added_profile->use_count());
- EXPECT_EQ(creation_time, added_profile->use_date());
- EXPECT_NE(creation_time, added_profile->modification_date());
+ EXPECT_EQ(kArbitraryTime, added_profile->use_date());
+ EXPECT_EQ(kArbitraryTime, added_profile->modification_date());
personal_data_->RecordUseOf(profile);
CreditCard* added_card =
@@ -3974,8 +3933,8 @@ TEST_F(PersonalDataManagerTest, RecordUseOf) {
ASSERT_TRUE(added_card);
EXPECT_EQ(*added_card, credit_card);
EXPECT_EQ(1U, added_card->use_count());
- EXPECT_EQ(creation_time, added_card->use_date());
- EXPECT_NE(creation_time, added_card->modification_date());
+ EXPECT_EQ(kArbitraryTime, added_card->use_date());
+ EXPECT_EQ(kArbitraryTime, added_card->modification_date());
personal_data_->RecordUseOf(credit_card);
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
@@ -3986,14 +3945,14 @@ TEST_F(PersonalDataManagerTest, RecordUseOf) {
added_profile = personal_data_->GetProfileByGUID(profile.guid());
ASSERT_TRUE(added_profile);
EXPECT_EQ(2U, added_profile->use_count());
- EXPECT_NE(creation_time, added_profile->use_date());
- EXPECT_NE(creation_time, added_profile->modification_date());
+ EXPECT_EQ(kSomeLaterTime, added_profile->use_date());
+ EXPECT_EQ(kArbitraryTime, added_profile->modification_date());
added_card = personal_data_->GetCreditCardByGUID(credit_card.guid());
ASSERT_TRUE(added_card);
EXPECT_EQ(2U, added_card->use_count());
- EXPECT_NE(creation_time, added_card->use_date());
- EXPECT_NE(creation_time, added_card->modification_date());
+ EXPECT_EQ(kSomeLaterTime, added_card->use_date());
+ EXPECT_EQ(kArbitraryTime, added_card->modification_date());
}
TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
@@ -4014,6 +3973,10 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"347666888555" /* American Express */, "04", "2999");
+ // Create the test clock and set the time to a specific value.
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime);
+
test::SetServerCreditCards(autofill_table_, server_cards);
personal_data_->Refresh();
@@ -4052,17 +4015,21 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
// For an unmasked card, usage data starts out as 2 because of the unmasking
- // which is considered a use.
+ // which is considered a use. The use date should now be the specified Now()
+ // time kArbitraryTime.
EXPECT_EQ(2U, personal_data_->GetCreditCards()[0]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[0]->use_date());
+ EXPECT_EQ(kArbitraryTime, personal_data_->GetCreditCards()[0]->use_date());
EXPECT_EQ(1U, personal_data_->GetCreditCards()[1]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
+ EXPECT_NE(kArbitraryTime, personal_data_->GetCreditCards()[1]->use_date());
- // Having unmasked this card, usage stats should be 2 and Now().
+ // Having unmasked this card, usage stats should be 2 and
+ // kArbitraryTime.
EXPECT_EQ(2U, personal_data_->GetCreditCards()[2]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[2]->use_date());
- base::Time initial_use_date = personal_data_->GetCreditCards()[2]->use_date();
+ EXPECT_EQ(kArbitraryTime, personal_data_->GetCreditCards()[2]->use_date());
+
+ // Change the Now() value for a second time.
+ test_clock.SetNow(kSomeLaterTime);
server_cards.back().set_guid(personal_data_->GetCreditCards()[2]->guid());
personal_data_->RecordUseOf(server_cards.back());
@@ -4072,15 +4039,15 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards()[0]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[0]->use_date());
+ EXPECT_EQ(kArbitraryTime, personal_data_->GetCreditCards()[0]->use_date());
EXPECT_EQ(1U, personal_data_->GetCreditCards()[1]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
+ EXPECT_NE(kArbitraryTime, personal_data_->GetCreditCards()[1]->use_date());
+ // The RecordUseOf call should have incremented the use_count to 3 and set the
+ // use_date to kSomeLaterTime.
EXPECT_EQ(3U, personal_data_->GetCreditCards()[2]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[2]->use_date());
- // Time may or may not have elapsed between unmasking and RecordUseOf.
- EXPECT_LE(initial_use_date, personal_data_->GetCreditCards()[2]->use_date());
+ EXPECT_EQ(kSomeLaterTime, personal_data_->GetCreditCards()[2]->use_date());
// Can record usage stats on masked cards.
server_cards[1].set_guid(personal_data_->GetCreditCards()[1]->guid());
@@ -4090,7 +4057,10 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
base::RunLoop().Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(2U, personal_data_->GetCreditCards()[1]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
+ EXPECT_EQ(kSomeLaterTime, personal_data_->GetCreditCards()[1]->use_date());
+
+ // Change Now()'s return value for a third time.
+ test_clock.SetNow(kMuchLaterTime);
// Upgrading to unmasked retains the usage stats (and increments them).
CreditCard* unmasked_card2 = &server_cards[1];
@@ -4105,7 +4075,7 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
base::RunLoop().Run();
ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(3U, personal_data_->GetCreditCards()[1]->use_count());
- EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
+ EXPECT_EQ(kMuchLaterTime, personal_data_->GetCreditCards()[1]->use_date());
}
TEST_F(PersonalDataManagerTest, ClearAllServerData) {
@@ -4121,26 +4091,15 @@ TEST_F(PersonalDataManagerTest, ClearAllServerData) {
// Need to set the google services username
EnableWalletCardImport();
- // Add a server profile.
- std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, "a123"));
- test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
- "ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
- "77401", "US", "");
- autofill_table_->SetServerProfiles(server_profiles);
-
// The card and profile should be there.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_FALSE(personal_data_->GetCreditCards().empty());
- EXPECT_FALSE(personal_data_->GetProfiles().empty());
personal_data_->ClearAllServerData();
// Reload the database, everything should be gone.
ResetPersonalDataManager(USER_MODE_NORMAL);
EXPECT_TRUE(personal_data_->GetCreditCards().empty());
- EXPECT_TRUE(personal_data_->GetProfiles().empty());
}
TEST_F(PersonalDataManagerTest, DontDuplicateServerCard) {
@@ -4473,7 +4432,13 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfile) {
{{COMPANY_NAME, "Stark Inc."}}},
};
+ // Create the test clock.
+ TestAutofillClock test_clock;
+
for (TestCase test_case : test_cases) {
+ // Set the time to a specific value.
+ test_clock.SetNow(kArbitraryTime);
+
SetupReferenceProfile();
const std::vector<AutofillProfile*>& initial_profiles =
personal_data_->GetProfiles();
@@ -4484,6 +4449,9 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfile) {
change.field_type, base::UTF8ToUTF16(change.field_value));
}
+ // Set the time to a bigger value.
+ test_clock.SetNow(kSomeLaterTime);
+
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St", "unit 5",
@@ -4515,11 +4483,8 @@ TEST_F(PersonalDataManagerTest, SaveImportedProfile) {
// Verify that the merged profile's use count, use date and modification
// date were properly updated.
EXPECT_EQ(1U, saved_profiles.front()->use_count());
- EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
- base::Time::Now() - saved_profiles.front()->use_date());
- EXPECT_GT(
- base::TimeDelta::FromMilliseconds(500),
- base::Time::Now() - saved_profiles.front()->modification_date());
+ EXPECT_EQ(kSomeLaterTime, saved_profiles.front()->use_date());
+ EXPECT_EQ(kSomeLaterTime, saved_profiles.front()->modification_date());
}
// Erase the profiles for the next test.
@@ -4568,7 +4533,17 @@ TEST_F(PersonalDataManagerTest, MergeProfile_Frecency) {
// Tests that MergeProfile produces a merged profile with the expected usage
// statistics.
-TEST_F(PersonalDataManagerTest, MergeProfile_UsageStats) {
+// Flaky on TSan, see crbug.com/686226.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_MergeProfile_UsageStats DISABLED_MergeProfile_UsageStats
+#else
+#define MAYBE_MergeProfile_UsageStats MergeProfile_UsageStats
+#endif
+TEST_F(PersonalDataManagerTest, MAYBE_MergeProfile_UsageStats) {
+ // Create the test clock and set the time to a specific value.
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kArbitraryTime);
+
// Create an initial profile with a use count of 10, an old use date and an
// old modification date of 4 days ago.
AutofillProfile* profile =
@@ -4577,14 +4552,16 @@ TEST_F(PersonalDataManagerTest, MergeProfile_UsageStats) {
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
profile->set_use_count(4U);
- profile->set_use_date(base::Time::Now() - base::TimeDelta::FromDays(4));
- profile->set_modification_date(base::Time::Now() -
- base::TimeDelta::FromDays(4));
+ EXPECT_EQ(kArbitraryTime, profile->use_date());
+ EXPECT_EQ(kArbitraryTime, profile->modification_date());
// Create the |existing_profiles| vector.
std::vector<std::unique_ptr<AutofillProfile>> existing_profiles;
existing_profiles.push_back(base::WrapUnique(profile));
+ // Change the current date.
+ test_clock.SetNow(kSomeLaterTime);
+
// Create a new imported profile that will get merged with the existing one.
AutofillProfile imported_profile(base::GenerateGUID(),
"https://www.example.com");
@@ -4592,6 +4569,9 @@ TEST_F(PersonalDataManagerTest, MergeProfile_UsageStats) {
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "US", "12345678910");
+ // Change the current date.
+ test_clock.SetNow(kMuchLaterTime);
+
// Merge the imported profile into the existing profiles.
std::vector<AutofillProfile> profiles;
std::string guid = personal_data_->MergeProfile(
@@ -4601,12 +4581,12 @@ TEST_F(PersonalDataManagerTest, MergeProfile_UsageStats) {
EXPECT_EQ(profile->guid(), guid);
// The use count should have be max(4, 1) => 4.
EXPECT_EQ(4U, profile->use_count());
- // The use date and modification dates should have been set to less than 500
- // milliseconds ago.
- EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
- base::Time::Now() - profile->use_date());
- EXPECT_GT(base::TimeDelta::FromMilliseconds(500),
- base::Time::Now() - profile->modification_date());
+ // The use date should be the one of the most recent profile, which is
+ // kSecondArbitraryTime.
+ EXPECT_EQ(kSomeLaterTime, profile->use_date());
+ // Since the merge is considered a modification, the modification_date should
+ // be set to kMuchLaterTime.
+ EXPECT_EQ(kMuchLaterTime, profile->modification_date());
}
// Tests that DedupeProfiles sets the correct profile guids to
@@ -4803,9 +4783,11 @@ TEST_F(PersonalDataManagerTest, UpdateCardsBillingAddressReference) {
// Add the credit cards to the database.
personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card1));
- personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card2));
+ personal_data_->server_credit_cards_.push_back(
+ base::WrapUnique(credit_card2));
personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card3));
- personal_data_->local_credit_cards_.push_back(base::WrapUnique(credit_card4));
+ personal_data_->server_credit_cards_.push_back(
+ base::WrapUnique(credit_card4));
personal_data_->UpdateCardsBillingAddressReference(guids_merge_map);
@@ -4838,7 +4820,7 @@ TEST_F(PersonalDataManagerTest,
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
profile1.set_use_count(12);
- profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
// Create a profile with a medium frecency score.
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
@@ -4846,7 +4828,7 @@ TEST_F(PersonalDataManagerTest,
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
profile2.set_use_count(5);
- profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
// Create a profile with a lower frecency score.
AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
@@ -4854,7 +4836,7 @@ TEST_F(PersonalDataManagerTest,
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile3.set_use_count(3);
- profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ profile3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(5));
// Create a set of two profiles to be merged together.
// Create a profile with a higher frecency score.
@@ -4863,7 +4845,7 @@ TEST_F(PersonalDataManagerTest,
"marge.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
profile4.set_use_count(11);
- profile4.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile4.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
// Create a profile with a lower frecency score.
AutofillProfile profile5(base::GenerateGUID(), "https://www.example.com");
@@ -4871,7 +4853,7 @@ TEST_F(PersonalDataManagerTest,
"marge.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile5.set_use_count(5);
- profile5.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile5.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
// Create a unique profile.
AutofillProfile profile6(base::GenerateGUID(), "https://www.example.com");
@@ -4879,7 +4861,7 @@ TEST_F(PersonalDataManagerTest,
"bart.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile6.set_use_count(10);
- profile6.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile6.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
// Add three credit cards. Give them a frecency score so that they are
// suggested in order (1, 2, 3). This will ensure a deterministic order for
@@ -4970,7 +4952,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MergedProfileValues) {
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
profile1.set_use_count(10);
- profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
// Create a profile with a medium frecency score.
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
@@ -4978,7 +4960,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MergedProfileValues) {
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
profile2.set_use_count(5);
- profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
// Create a profile with a lower frecency score.
AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
@@ -4986,7 +4968,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MergedProfileValues) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile3.set_use_count(3);
- profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ profile3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(5));
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
@@ -5062,7 +5044,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileFirst) {
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
profile1.set_use_count(7);
- profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ profile1.set_use_date(kMuchLaterTime);
// Create a similar non verified profile with a medium frecency score.
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
@@ -5070,7 +5052,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileFirst) {
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
profile2.set_use_count(5);
- profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile2.set_use_date(kSomeLaterTime);
// Create a similar non verified profile with a lower frecency score.
AutofillProfile profile3(base::GenerateGUID(), "https://www.example.com");
@@ -5078,7 +5060,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileFirst) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile3.set_use_count(3);
- profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ profile3.set_use_date(kArbitraryTime);
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
@@ -5118,10 +5100,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileFirst) {
EXPECT_EQ(profile1.guid(), profiles[0]->guid());
EXPECT_TRUE(profile1 == *profiles[0]);
EXPECT_EQ(profile1.use_count(), profiles[0]->use_count());
- EXPECT_LT(profile1.use_date() - TimeDelta::FromSeconds(2),
- profiles[0]->use_date());
- EXPECT_GT(profile1.use_date() + TimeDelta::FromSeconds(2),
- profiles[0]->use_date());
+ EXPECT_EQ(profile1.use_date(), profiles[0]->use_date());
}
// Tests that ApplyDedupingRoutine only keeps the verified profile with its
@@ -5134,7 +5113,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileLast) {
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
profile1.set_use_count(5);
- profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile1.set_use_date(kMuchLaterTime);
// Create a similar non verified profile with a medium frecency score.
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
@@ -5142,7 +5121,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileLast) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile2.set_use_count(5);
- profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile2.set_use_date(kSomeLaterTime);
// Create a similar verified profile with a lower frecency score.
AutofillProfile profile3(base::GenerateGUID(), kSettingsOrigin);
@@ -5150,7 +5129,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileLast) {
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
profile3.set_use_count(3);
- profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ profile3.set_use_date(kArbitraryTime);
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
@@ -5186,14 +5165,11 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_VerifiedProfileLast) {
histogram_tester.ExpectUniqueSample(
"Autofill.NumberOfProfilesRemovedDuringDedupe", 2, 1);
- // Only the verified |profile2| with it's original data should have been kept.
+ // Only the verified |profile3| with it's original data should have been kept.
EXPECT_EQ(profile3.guid(), profiles[0]->guid());
EXPECT_TRUE(profile3 == *profiles[0]);
EXPECT_EQ(profile3.use_count(), profiles[0]->use_count());
- EXPECT_LT(profile3.use_date() - TimeDelta::FromSeconds(2),
- profiles[0]->use_date());
- EXPECT_GT(profile3.use_date() + TimeDelta::FromSeconds(2),
- profiles[0]->use_date());
+ EXPECT_EQ(profile3.use_date(), profiles[0]->use_date());
}
// Tests that ApplyDedupingRoutine does not merge unverified data into
@@ -5205,7 +5181,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleVerifiedProfiles) {
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
profile1.set_use_count(5);
- profile1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile1.set_use_date(kMuchLaterTime);
// Create a similar verified profile with a medium frecency score.
AutofillProfile profile2(base::GenerateGUID(), kSettingsOrigin);
@@ -5213,7 +5189,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleVerifiedProfiles) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
profile2.set_use_count(5);
- profile2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ profile2.set_use_date(kSomeLaterTime);
// Create a similar verified profile with a lower frecency score.
AutofillProfile profile3(base::GenerateGUID(), kSettingsOrigin);
@@ -5221,7 +5197,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleVerifiedProfiles) {
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
profile3.set_use_count(3);
- profile3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ profile3.set_use_date(kArbitraryTime);
personal_data_->AddProfile(profile1);
personal_data_->AddProfile(profile2);
@@ -5268,14 +5244,8 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleVerifiedProfiles) {
EXPECT_TRUE(profile3 == *profiles[1]);
EXPECT_EQ(profile2.use_count(), profiles[0]->use_count());
EXPECT_EQ(profile3.use_count(), profiles[1]->use_count());
- EXPECT_LT(profile2.use_date() - TimeDelta::FromSeconds(2),
- profiles[0]->use_date());
- EXPECT_GT(profile2.use_date() + TimeDelta::FromSeconds(2),
- profiles[0]->use_date());
- EXPECT_LT(profile3.use_date() - TimeDelta::FromSeconds(2),
- profiles[1]->use_date());
- EXPECT_GT(profile3.use_date() + TimeDelta::FromSeconds(2),
- profiles[1]->use_date());
+ EXPECT_EQ(profile2.use_date(), profiles[0]->use_date());
+ EXPECT_EQ(profile3.use_date(), profiles[1]->use_date());
}
// Tests that ApplyProfileUseDatesFix sets the use date of profiles from an
@@ -5292,6 +5262,7 @@ TEST_F(PersonalDataManagerTest, ApplyProfileUseDatesFix) {
test::SetProfileInfo(&profile1, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
+ profile1.set_use_date(kArbitraryTime);
// Create another profile and set its use date to the default value.
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
@@ -5314,14 +5285,17 @@ TEST_F(PersonalDataManagerTest, ApplyProfileUseDatesFix) {
ASSERT_EQ(2U, saved_profiles.size());
// The use dates should not have been modified.
- EXPECT_LE(base::Time::Now() - base::TimeDelta::FromDays(1),
- saved_profiles[0]->use_date());
- EXPECT_EQ(base::Time(), saved_profiles[1]->use_date());
+ EXPECT_EQ(profile1.use_date(), saved_profiles[0]->use_date());
+ EXPECT_EQ(profile2.use_date(), saved_profiles[1]->use_date());
// Set the pref to false to indicate the fix has never been run.
personal_data_->pref_service_->SetBoolean(
prefs::kAutofillProfileUseDatesFixed, false);
+ // Create the test clock and set the time to a specific value.
+ TestAutofillClock test_clock;
+ test_clock.SetNow(kSomeLaterTime);
+
personal_data_->ApplyProfileUseDatesFix();
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
@@ -5333,12 +5307,9 @@ TEST_F(PersonalDataManagerTest, ApplyProfileUseDatesFix) {
ASSERT_EQ(2U, saved_profiles.size());
// |profile1|'s use date should not have been modified.
- EXPECT_LE(base::Time::Now() - base::TimeDelta::FromDays(1),
- saved_profiles[0]->use_date());
+ EXPECT_LE(profile1.use_date(), saved_profiles[0]->use_date());
// |profile2|'s use date should have been set to two weeks before now.
- EXPECT_LE(base::Time::Now() - base::TimeDelta::FromDays(15),
- saved_profiles[1]->use_date());
- EXPECT_GE(base::Time::Now() - base::TimeDelta::FromDays(13),
+ EXPECT_EQ(kSomeLaterTime - base::TimeDelta::FromDays(14),
saved_profiles[1]->use_date());
}
@@ -5355,6 +5326,7 @@ TEST_F(PersonalDataManagerTest, ApplyProfileUseDatesFix_NotAppliedTwice) {
test::SetProfileInfo(&profile1, "Homer", "Jay", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "12345678910");
+ profile1.set_use_date(kArbitraryTime);
AutofillProfile profile2(base::GenerateGUID(), "https://www.example.com");
test::SetProfileInfo(&profile2, "Marge", "", "Simpson",
"homer.simpson@abc.com", "SNP", "742 Evergreen Terrace",
@@ -5375,8 +5347,7 @@ TEST_F(PersonalDataManagerTest, ApplyProfileUseDatesFix_NotAppliedTwice) {
ASSERT_EQ(2U, saved_profiles.size());
// The use dates should not have been modified.
- EXPECT_LE(base::Time::Now() - base::TimeDelta::FromDays(1),
- saved_profiles[0]->use_date());
+ EXPECT_EQ(profile1.use_date(), saved_profiles[0]->use_date());
EXPECT_EQ(base::Time(), saved_profiles[1]->use_date());
}
@@ -5392,7 +5363,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"homer.simpson@abc.com", "", "742. Evergreen Terrace",
"", "Springfield", "IL", "91601", "US", "");
Homer1.set_use_count(10);
- Homer1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(1));
+ Homer1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(1));
// Create a Homer home profile with a medium frecency score compared to other
// Homer profiles.
@@ -5401,7 +5372,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"homer.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
Homer2.set_use_count(5);
- Homer2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ Homer2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
// Create a Homer home profile with a lower frecency score than other Homer
// profiles.
@@ -5410,7 +5381,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"homer.simpson@abc.com", "Fox", "742 Evergreen Terrace.",
"", "Springfield", "IL", "91601", "", "");
Homer3.set_use_count(3);
- Homer3.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ Homer3.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(5));
// Create a Homer work profile (different address).
AutofillProfile Homer4(base::GenerateGUID(), "https://www.example.com");
@@ -5418,7 +5389,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"homer.simpson@abc.com", "Fox", "12 Nuclear Plant.", "",
"Springfield", "IL", "91601", "US", "9876543");
Homer4.set_use_count(3);
- Homer4.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(5));
+ Homer4.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(5));
// Create a Marge profile with a lower frecency score that other Marge
// profiles.
@@ -5427,7 +5398,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"marge.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
Marge1.set_use_count(4);
- Marge1.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ Marge1.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
// Create a verified Marge home profile with a lower frecency score that the
// other Marge profile.
@@ -5436,7 +5407,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"marge.simpson@abc.com", "", "742 Evergreen Terrace", "",
"Springfield", "IL", "91601", "", "12345678910");
Marge2.set_use_count(2);
- Marge2.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(3));
+ Marge2.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(3));
// Create a Barney profile (guest user).
AutofillProfile Barney(base::GenerateGUID(), "https://www.example.com");
@@ -5444,7 +5415,7 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_MultipleDedupes) {
"ABC", "123 Other Street", "", "Springfield", "IL",
"91601", "", "");
Barney.set_use_count(1);
- Barney.set_use_date(base::Time::Now() - base::TimeDelta::FromDays(180));
+ Barney.set_use_date(AutofillClock::Now() - base::TimeDelta::FromDays(180));
personal_data_->AddProfile(Homer1);
personal_data_->AddProfile(Homer2);
@@ -5645,4 +5616,509 @@ TEST_F(PersonalDataManagerTest, ApplyDedupingRoutine_OncePerVersion) {
EXPECT_EQ(2U, personal_data_->GetProfiles().size());
}
+// 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.
+TEST_F(PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_NewProfile) {
+ ///////////////////////////////////////////////////////////////////////
+ // Setup.
+ ///////////////////////////////////////////////////////////////////////
+ EnableWalletCardImport();
+ base::HistogramTester histogram_tester;
+ const std::string kServerAddressId("server_address1");
+
+ // Add two different profiles, a local and a server one. Set the use stats so
+ // the server profile has a higher frecency, to have a predictable ordering to
+ // validate results.
+ AutofillProfile local_profile(base::GenerateGUID(),
+ "https://www.example.com");
+ test::SetProfileInfo(&local_profile, "Josephine", "Alicia", "Saenz",
+ "joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
+ "Orlando", "FL", "32801", "US", "19482937549");
+ local_profile.set_use_count(1);
+ personal_data_->AddProfile(local_profile);
+
+ // Add a different server profile.
+ std::vector<AutofillProfile> GetServerProfiles;
+ GetServerProfiles.push_back(
+ AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ test::SetProfileInfo(&GetServerProfiles.back(), "John", "", "Doe", "",
+ "ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
+ "77401", "US", "");
+ // Wallet only provides a full name, so the above first and last names
+ // will be ignored when the profile is written to the DB.
+ GetServerProfiles.back().SetRawInfo(NAME_FULL, ASCIIToUTF16("John Doe"));
+ GetServerProfiles.back().set_use_count(100);
+ autofill_table_->SetServerProfiles(GetServerProfiles);
+
+ // Add a server and a local card that have the server address as billing
+ // address.
+ CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&local_card, "Clyde Barrow",
+ "347666888555" /* American Express */, "04", "2999");
+ local_card.set_billing_address_id(kServerAddressId);
+ personal_data_->AddCreditCard(local_card);
+
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
+ "1111" /* Visa */, "01", "2999");
+ server_cards.back().SetTypeForMaskedCard(kVisaCard);
+ server_cards.back().set_billing_address_id(kServerAddressId);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is setup correctly.
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+ EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tested method.
+ ///////////////////////////////////////////////////////////////////////
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+
+ ///////////////////////////////////////////////////////////////////////
+ // Validation.
+ ///////////////////////////////////////////////////////////////////////
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // The Wallet address should have been added as a new local profile.
+ EXPECT_EQ(2U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
+ histogram_tester.ExpectUniqueSample("Autofill.WalletAddressConversionType",
+ AutofillMetrics::CONVERTED_ADDRESS_ADDED,
+ 1);
+
+ // The conversion should be recorded in the Wallet address.
+ EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
+
+ // Get the profiles, sorted by frecency to have a deterministic order.
+ std::vector<AutofillProfile*> profiles =
+ personal_data_->GetProfilesToSuggest();
+
+ // Make sure that the two profiles have not merged.
+ ASSERT_EQ(2U, profiles.size());
+ EXPECT_EQ(UTF8ToUTF16("John"), profiles[0]->GetRawInfo(NAME_FIRST));
+ EXPECT_EQ(local_profile, *profiles[1]);
+
+ // Make sure that the billing address id of the two cards now point to the
+ // converted profile.
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[0]->billing_address_id());
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[1]->billing_address_id());
+
+ // Make sure that the added address has the email address of the currently
+ // signed-in user.
+ EXPECT_EQ(UTF8ToUTF16("syncuser@example.com"),
+ profiles[0]->GetRawInfo(EMAIL_ADDRESS));
+}
+
+// Tests that the converted wallet address is merged into an existing local
+// profile if they are considered equivalent. Also tests that the billing
+// address relationship was transferred to the converted address.
+TEST_F(PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_MergedProfile) {
+ ///////////////////////////////////////////////////////////////////////
+ // Setup.
+ ///////////////////////////////////////////////////////////////////////
+ EnableWalletCardImport();
+ base::HistogramTester histogram_tester;
+ const std::string kServerAddressId("server_address1");
+
+ // Add two similar profile, a local and a server one. Set the use stats so
+ // the server card has a higher frecency, to have a predicatble ordering to
+ // validate results.
+ // Add a local profile.
+ AutofillProfile local_profile(base::GenerateGUID(),
+ "https://www.example.com");
+ test::SetProfileInfo(&local_profile, "John", "", "Doe", "john@doe.com", "",
+ "1212 Center.", "Bld. 5", "Orlando", "FL", "32801", "US",
+ "19482937549");
+ local_profile.set_use_count(1);
+ personal_data_->AddProfile(local_profile);
+
+ // Add a different server profile.
+ std::vector<AutofillProfile> GetServerProfiles;
+ GetServerProfiles.push_back(
+ AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ test::SetProfileInfo(&GetServerProfiles.back(), "John", "", "Doe", "", "Fox",
+ "1212 Center", "Bld. 5", "Orlando", "FL", "", "US", "");
+ // Wallet only provides a full name, so the above first and last names
+ // will be ignored when the profile is written to the DB.
+ GetServerProfiles.back().SetRawInfo(NAME_FULL, ASCIIToUTF16("John Doe"));
+ GetServerProfiles.back().set_use_count(100);
+ autofill_table_->SetServerProfiles(GetServerProfiles);
+
+ // Add a server and a local card that have the server address as billing
+ // address.
+ CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&local_card, "Clyde Barrow",
+ "347666888555" /* American Express */, "04", "2999");
+ local_card.set_billing_address_id(kServerAddressId);
+ personal_data_->AddCreditCard(local_card);
+
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
+ "1111" /* Visa */, "01", "2999");
+ server_cards.back().SetTypeForMaskedCard(kVisaCard);
+ server_cards.back().set_billing_address_id(kServerAddressId);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is setup correctly.
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+ EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tested method.
+ ///////////////////////////////////////////////////////////////////////
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+
+ ///////////////////////////////////////////////////////////////////////
+ // Validation.
+ ///////////////////////////////////////////////////////////////////////
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // 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_->GetServerProfiles().size());
+ histogram_tester.ExpectUniqueSample("Autofill.WalletAddressConversionType",
+ AutofillMetrics::CONVERTED_ADDRESS_MERGED,
+ 1);
+
+ // The conversion should be recorded in the Wallet address.
+ EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
+
+ // Get the profiles, sorted by frecency to have a deterministic order.
+ std::vector<AutofillProfile*> profiles =
+ personal_data_->GetProfilesToSuggest();
+
+ // Make sure that the two profiles have merged.
+ ASSERT_EQ(1U, profiles.size());
+
+ // Check that the values were merged.
+ EXPECT_EQ(UTF8ToUTF16("john@doe.com"),
+ profiles[0]->GetRawInfo(EMAIL_ADDRESS));
+ EXPECT_EQ(UTF8ToUTF16("Fox"), profiles[0]->GetRawInfo(COMPANY_NAME));
+ EXPECT_EQ(UTF8ToUTF16("32801"), profiles[0]->GetRawInfo(ADDRESS_HOME_ZIP));
+
+ // Make sure that the billing address id of the two cards now point to the
+ // converted profile.
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[0]->billing_address_id());
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[1]->billing_address_id());
+}
+
+// Tests that a Wallet address that has already converted does not get converted
+// a second time.
+TEST_F(PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_AlreadyConverted) {
+ ///////////////////////////////////////////////////////////////////////
+ // Setup.
+ ///////////////////////////////////////////////////////////////////////
+ EnableWalletCardImport();
+ base::HistogramTester histogram_tester;
+ const std::string kServerAddressId("server_address1");
+
+ // Add a server profile that has already been converted.
+ std::vector<AutofillProfile> GetServerProfiles;
+ GetServerProfiles.push_back(
+ AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ test::SetProfileInfo(&GetServerProfiles.back(), "John", "Ray", "Doe",
+ "john@doe.com", "Fox", "1212 Center", "Bld. 5",
+ "Orlando", "FL", "32801", "US", "");
+ GetServerProfiles.back().set_has_converted(true);
+ // Wallet only provides a full name, so the above first and last names
+ // will be ignored when the profile is written to the DB.
+ autofill_table_->SetServerProfiles(GetServerProfiles);
+
+ // Make sure everything is setup correctly.
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+ EXPECT_EQ(0U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tested method.
+ ///////////////////////////////////////////////////////////////////////
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+
+ ///////////////////////////////////////////////////////////////////////
+ // Validation.
+ ///////////////////////////////////////////////////////////////////////
+ // Since there should be no change in data, OnPersonalDataChanged should not
+ // have been called.
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(0);
+
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // There should be no local profiles added.
+ EXPECT_EQ(0U, personal_data_->web_profiles().size());
+ EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
+}
+
+// Tests that when the user has multiple similar Wallet addresses, they get
+// merged into a single local profile, and that the billing address relationship
+// is merged too.
+TEST_F(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_MultipleSimilarWalletAddresses) {
+ ///////////////////////////////////////////////////////////////////////
+ // Setup.
+ ///////////////////////////////////////////////////////////////////////
+ EnableWalletCardImport();
+ base::HistogramTester histogram_tester;
+ const std::string kServerAddressId("server_address1");
+ const std::string kServerAddressId2("server_address2");
+
+ // Add a unique local profile and two similar server profiles. Set the use
+ // stats to have a predicatble ordering to validate results.
+ // Add a local profile.
+ AutofillProfile local_profile(base::GenerateGUID(),
+ "https://www.example.com");
+ test::SetProfileInfo(&local_profile, "Bob", "", "Doe", "", "Fox",
+ "1212 Center.", "Bld. 5", "Orlando", "FL", "32801", "US",
+ "19482937549");
+ local_profile.set_use_count(1);
+ personal_data_->AddProfile(local_profile);
+
+ // Add a server profile.
+ std::vector<AutofillProfile> GetServerProfiles;
+ GetServerProfiles.push_back(
+ AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ test::SetProfileInfo(&GetServerProfiles.back(), "John", "", "Doe", "", "",
+ "1212 Center", "Bld. 5", "Orlando", "FL", "32801", "US",
+ "");
+ // Wallet only provides a full name, so the above first and last names
+ // will be ignored when the profile is written to the DB.
+ GetServerProfiles.back().SetRawInfo(NAME_FULL, ASCIIToUTF16("John Doe"));
+ GetServerProfiles.back().set_use_count(100);
+
+ // Add a similar server profile.
+ GetServerProfiles.push_back(
+ AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId2));
+ test::SetProfileInfo(&GetServerProfiles.back(), "John", "", "Doe",
+ "john@doe.com", "Fox", "1212 Center", "Bld. 5",
+ "Orlando", "FL", "", "US", "");
+ // Wallet only provides a full name, so the above first and last names
+ // will be ignored when the profile is written to the DB.
+ GetServerProfiles.back().SetRawInfo(NAME_FULL, ASCIIToUTF16("John Doe"));
+ GetServerProfiles.back().set_use_count(200);
+ autofill_table_->SetServerProfiles(GetServerProfiles);
+
+ // Add a server and a local card that have the first and second Wallet address
+ // as a billing address.
+ CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
+ "https://www.example.com");
+ test::SetCreditCardInfo(&local_card, "Clyde Barrow",
+ "347666888555" /* American Express */, "04", "2999");
+ local_card.set_billing_address_id(kServerAddressId);
+ personal_data_->AddCreditCard(local_card);
+
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
+ "1111" /* Visa */, "01", "2999");
+ server_cards.back().SetTypeForMaskedCard(kVisaCard);
+ server_cards.back().set_billing_address_id(kServerAddressId2);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is setup correctly.
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+ EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(2U, personal_data_->GetServerProfiles().size());
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tested method.
+ ///////////////////////////////////////////////////////////////////////
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+
+ ///////////////////////////////////////////////////////////////////////
+ // Validation.
+ ///////////////////////////////////////////////////////////////////////
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // 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_->GetServerProfiles().size());
+ histogram_tester.ExpectBucketCount("Autofill.WalletAddressConversionType",
+ AutofillMetrics::CONVERTED_ADDRESS_ADDED,
+ 1);
+ histogram_tester.ExpectBucketCount("Autofill.WalletAddressConversionType",
+ AutofillMetrics::CONVERTED_ADDRESS_MERGED,
+ 1);
+
+ // The conversion should be recorded in the Wallet addresses.
+ EXPECT_TRUE(personal_data_->GetServerProfiles()[0]->has_converted());
+ EXPECT_TRUE(personal_data_->GetServerProfiles()[1]->has_converted());
+
+ // Get the profiles, sorted by frecency to have a deterministic order.
+ std::vector<AutofillProfile*> profiles =
+ personal_data_->GetProfilesToSuggest();
+
+ // Make sure that the two Wallet addresses merged together and were added as
+ // a new local profile.
+ ASSERT_EQ(2U, profiles.size());
+ EXPECT_EQ(UTF8ToUTF16("John"), profiles[0]->GetRawInfo(NAME_FIRST));
+ EXPECT_EQ(local_profile, *profiles[1]);
+
+ // Check that the values were merged.
+ EXPECT_EQ(UTF8ToUTF16("Fox"), profiles[0]->GetRawInfo(COMPANY_NAME));
+ EXPECT_EQ(UTF8ToUTF16("32801"), profiles[0]->GetRawInfo(ADDRESS_HOME_ZIP));
+
+ // Make sure that the billing address id of the two cards now point to the
+ // converted profile.
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[0]->billing_address_id());
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[1]->billing_address_id());
+}
+
+// Tests a new server card's billing address is updated propely even if the
+// address was already converted in the past.
+TEST_F(
+ PersonalDataManagerTest,
+ ConvertWalletAddressesAndUpdateWalletCards_NewCard_AddressAlreadyConverted) {
+ ///////////////////////////////////////////////////////////////////////
+ // Setup.
+ ///////////////////////////////////////////////////////////////////////
+ // Go through the conversion process for a server address and card. Then add
+ // a new server card that refers to the already converted server address as
+ // its billing address.
+ EnableWalletCardImport();
+ base::HistogramTester histogram_tester;
+ const std::string kServerAddressId("server_address1");
+
+ // Add a server profile.
+ std::vector<AutofillProfile> GetServerProfiles;
+ GetServerProfiles.push_back(
+ AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ test::SetProfileInfo(&GetServerProfiles.back(), "John", "", "Doe", "", "Fox",
+ "1212 Center", "Bld. 5", "Orlando", "FL", "", "US", "");
+ // Wallet only provides a full name, so the above first and last names
+ // will be ignored when the profile is written to the DB.
+ GetServerProfiles.back().SetRawInfo(NAME_FULL, ASCIIToUTF16("John Doe"));
+ GetServerProfiles.back().set_use_count(100);
+ autofill_table_->SetServerProfiles(GetServerProfiles);
+
+ // Add a server card that have the server address as billing address.
+ std::vector<CreditCard> server_cards;
+ server_cards.push_back(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
+ "1111" /* Visa */, "01", "2999");
+ server_cards.back().SetTypeForMaskedCard(kVisaCard);
+ server_cards.back().set_billing_address_id(kServerAddressId);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is setup correctly.
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+ EXPECT_EQ(1U, personal_data_->GetServerProfiles().size());
+ EXPECT_EQ(1U, personal_data_->GetCreditCards().size());
+
+ // Run the conversion.
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // The Wallet address should have been converted to a new local profile.
+ EXPECT_EQ(1U, personal_data_->web_profiles().size());
+
+ // The conversion should be recorded in the Wallet address.
+ EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
+
+ // Make sure that the billing address id of the card now point to the
+ // converted profile.
+ std::vector<AutofillProfile*> profiles =
+ personal_data_->GetProfilesToSuggest();
+ ASSERT_EQ(1U, profiles.size());
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[0]->billing_address_id());
+
+ // Add a new server card that has the same billing address as the old one.
+ server_cards.push_back(
+ CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card2"));
+ test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
+ "1112" /* Visa */, "01", "2888");
+ server_cards.back().SetTypeForMaskedCard(kVisaCard);
+ server_cards.back().set_billing_address_id(kServerAddressId);
+ test::SetServerCreditCards(autofill_table_, server_cards);
+
+ // Make sure everything is setup correctly.
+ personal_data_->Refresh();
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+ EXPECT_EQ(1U, personal_data_->web_profiles().size());
+ EXPECT_EQ(2U, personal_data_->GetCreditCards().size());
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tested method.
+ ///////////////////////////////////////////////////////////////////////
+ personal_data_->ConvertWalletAddressesAndUpdateWalletCards();
+
+ ///////////////////////////////////////////////////////////////////////
+ // Validation.
+ ///////////////////////////////////////////////////////////////////////
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::RunLoop().Run();
+
+ // The conversion should still be recorded in the Wallet address.
+ EXPECT_TRUE(personal_data_->GetServerProfiles().back()->has_converted());
+
+ // Get the profiles, sorted by frecency to have a deterministic order.
+ profiles = personal_data_->GetProfilesToSuggest();
+
+ // Make sure that there is still only one profile.
+ ASSERT_EQ(1U, profiles.size());
+
+ // Make sure that the billing address id of the first server card still refers
+ // to the converted address.
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[0]->billing_address_id());
+ // Make sure that the billing address id of the new server card still refers
+ // to the converted address.
+ EXPECT_EQ(profiles[0]->guid(),
+ personal_data_->GetCreditCards()[1]->billing_address_id());
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/proto/server.proto b/chromium/components/autofill/core/browser/proto/server.proto
index 75451977735..e84e2025a79 100644
--- a/chromium/components/autofill/core/browser/proto/server.proto
+++ b/chromium/components/autofill/core/browser/proto/server.proto
@@ -33,7 +33,7 @@ message AutofillQueryResponseContents {
// This message contains information about the field types in a single form.
// It is sent by the toolbar to contribute to the field type statistics.
-// Next available id: 21
+// Next available id: 22
message AutofillUploadContents {
required string client_version = 1;
required fixed64 form_signature = 2;
@@ -59,7 +59,8 @@ message AutofillUploadContents {
// AutoFillFieldType
required fixed32 autofill_type = 7;
- // The value of the name attribute on the field, if present.
+ // The value of the name attribute on the field, if present. Otherwise, the
+ // value of the id attribute. See HTMLFormControlElement::nameForAutofill.
optional string name = 8;
// The value of the autocomplete attribute on the field, if present.
@@ -93,6 +94,10 @@ message AutofillUploadContents {
// The properties mask (i.e. whether the field was autofilled, user
// modified, etc.) See FieldPropertiesFlags.
optional uint32 properties_mask = 20;
+
+ // The value of the id attribute, if it differs from the name attribute.
+ // Otherwise, this field is absent.
+ optional string id = 21;
}
// Signature of the form action host (e.g. Hash64Bit("example.com")).
optional fixed64 action_signature = 13;
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index 7df6c300ce4..72b2da47cc1 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -41,6 +41,10 @@ rappor::RapporServiceImpl* TestAutofillClient::GetRapporServiceImpl() {
return rappor_service_.get();
}
+ukm::UkmService* TestAutofillClient::GetUkmService() {
+ return ukm_service_test_harness_.test_ukm_service();
+}
+
void TestAutofillClient::ShowAutofillSettings() {
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index 72cdd8c3f57..5b25ecfabab 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -16,6 +16,7 @@
#include "components/autofill/core/browser/autofill_client.h"
#include "components/prefs/pref_service.h"
#include "components/rappor/test_rappor_service.h"
+#include "components/ukm/test_ukm_service.h"
#include "google_apis/gaia/fake_identity_provider.h"
#include "google_apis/gaia/fake_oauth2_token_service.h"
@@ -34,6 +35,7 @@ class TestAutofillClient : public AutofillClient {
syncer::SyncService* GetSyncService() override;
IdentityProvider* GetIdentityProvider() override;
rappor::RapporServiceImpl* GetRapporServiceImpl() override;
+ ukm::UkmService* GetUkmService() override;
void ShowAutofillSettings() override;
void ShowUnmaskPrompt(const CreditCard& card,
UnmaskCardReason reason,
@@ -85,12 +87,17 @@ class TestAutofillClient : public AutofillClient {
void set_form_origin(const GURL& url) { form_origin_ = url; }
+ ukm::TestUkmService* GetTestUkmService() {
+ return ukm_service_test_harness_.test_ukm_service();
+ }
+
private:
// NULL by default.
std::unique_ptr<PrefService> prefs_;
std::unique_ptr<FakeOAuth2TokenService> token_service_;
std::unique_ptr<FakeIdentityProvider> identity_provider_;
std::unique_ptr<rappor::TestRapporServiceImpl> rappor_service_;
+ ukm::UkmServiceTestingHarness ukm_service_test_harness_;
GURL form_origin_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillClient);
diff --git a/chromium/components/autofill/core/browser/test_autofill_clock.cc b/chromium/components/autofill/core/browser/test_autofill_clock.cc
new file mode 100644
index 00000000000..4d5829b8a26
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_autofill_clock.cc
@@ -0,0 +1,33 @@
+// 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_autofill_clock.h"
+
+#include <utility>
+
+#include "base/test/simple_test_clock.h"
+#include "components/autofill/core/common/autofill_clock.h"
+
+namespace autofill {
+
+TestAutofillClock::TestAutofillClock() {
+ // Create a new test clock and set it as the AutofillClock clock and keep a
+ // pointer to manipulate the time it returns.
+ std::unique_ptr<base::SimpleTestClock> unique_test_clock(
+ new base::SimpleTestClock());
+ // Keep a pointer to the clock to be able to use its SetNow() function.
+ test_clock_ = unique_test_clock.get();
+ AutofillClock::SetTestClock(std::move(unique_test_clock));
+}
+
+TestAutofillClock::~TestAutofillClock() {
+ // Destroys the test clock and resets a normal clock.
+ AutofillClock::SetClock();
+}
+
+void TestAutofillClock::SetNow(base::Time now) {
+ test_clock_->SetNow(now);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_clock.h b/chromium/components/autofill/core/browser/test_autofill_clock.h
new file mode 100644
index 00000000000..a40f54fbd2f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_autofill_clock.h
@@ -0,0 +1,39 @@
+// 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_AUTOFILL_CLOCK_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_CLOCK_H_
+
+#include <memory>
+
+#include "base/macros.h"
+
+namespace base {
+class SimpleTestClock;
+class Time;
+} // namespace base
+
+namespace autofill {
+
+// Handles the customization of the time in tests. Replaces the clock in
+// AutofillClock with a test version that can be manipulated from this class.
+// Automatically resets a normal clock to AutofillClock when this gets
+// destroyed,
+class TestAutofillClock {
+ public:
+ TestAutofillClock();
+ ~TestAutofillClock();
+
+ // Set the time to be returned from AutofillClock::Now() calls.
+ void SetNow(base::Time now);
+
+ private:
+ base::SimpleTestClock* test_clock_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAutofillClock);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_CLOCK_H_
diff --git a/chromium/components/autofill/core/browser/test_personal_data_manager.cc b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
index 1463fdbec48..d663cdefe55 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
@@ -35,7 +35,7 @@ void TestPersonalDataManager::AddTestingServerCreditCard(
const std::vector<AutofillProfile*>& TestPersonalDataManager::GetProfiles()
const {
- return profiles_;
+ return GetProfiles(false);
}
std::vector<AutofillProfile*> TestPersonalDataManager::web_profiles() const {
@@ -72,4 +72,9 @@ 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 f3192922267..71e06180cbe 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h
@@ -56,6 +56,9 @@ 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/ui/card_unmask_prompt_controller_impl.cc b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
index 435e00caf82..38778caf3bd 100644
--- a/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
+++ b/chromium/components/autofill/core/browser/ui/card_unmask_prompt_controller_impl.cc
@@ -16,10 +16,11 @@
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/ui/card_unmask_prompt_view.h"
#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/grit/components_scaled_resources.h"
#include "components/prefs/pref_service.h"
-#include "grit/components_scaled_resources.h"
-#include "grit/components_strings.h"
+#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace autofill {
@@ -50,7 +51,7 @@ void CardUnmaskPromptControllerImpl::ShowPrompt(
card_unmask_view_->ControllerGone();
new_card_link_clicked_ = false;
- shown_timestamp_ = base::Time::Now();
+ shown_timestamp_ = AutofillClock::Now();
pending_response_ = CardUnmaskDelegate::UnmaskResponse();
card_unmask_view_ = card_unmask_view;
card_ = card;
@@ -107,8 +108,8 @@ void CardUnmaskPromptControllerImpl::OnVerificationResult(
unmasking_result_ = result;
AutofillMetrics::LogRealPanResult(result);
- AutofillMetrics::LogUnmaskingDuration(base::Time::Now() - verify_timestamp_,
- result);
+ AutofillMetrics::LogUnmaskingDuration(
+ AutofillClock::Now() - verify_timestamp_, result);
card_unmask_view_->GotVerificationResult(error_message,
AllowsRetry(result));
}
@@ -124,14 +125,14 @@ void CardUnmaskPromptControllerImpl::LogOnCloseEvents() {
AutofillMetrics::UnmaskPromptEvent close_reason_event = GetCloseReasonEvent();
AutofillMetrics::LogUnmaskPromptEvent(close_reason_event);
AutofillMetrics::LogUnmaskPromptEventDuration(
- base::Time::Now() - shown_timestamp_, close_reason_event);
+ AutofillClock::Now() - shown_timestamp_, close_reason_event);
if (close_reason_event == AutofillMetrics::UNMASK_PROMPT_CLOSED_NO_ATTEMPTS)
return;
if (close_reason_event ==
AutofillMetrics::UNMASK_PROMPT_CLOSED_ABANDON_UNMASKING) {
- AutofillMetrics::LogTimeBeforeAbandonUnmasking(base::Time::Now() -
+ AutofillMetrics::LogTimeBeforeAbandonUnmasking(AutofillClock::Now() -
verify_timestamp_);
}
@@ -186,7 +187,7 @@ void CardUnmaskPromptControllerImpl::OnUnmaskResponse(
const base::string16& exp_month,
const base::string16& exp_year,
bool should_store_pan) {
- verify_timestamp_ = base::Time::Now();
+ verify_timestamp_ = AutofillClock::Now();
unmasking_number_of_attempts_++;
unmasking_result_ = AutofillClient::NONE;
card_unmask_view_->DisableAndWaitForVerification();
@@ -256,7 +257,7 @@ int CardUnmaskPromptControllerImpl::GetCvcImageRid() const {
}
bool CardUnmaskPromptControllerImpl::ShouldRequestExpirationDate() const {
- return card_.ShouldUpdateExpiration(base::Time::Now()) ||
+ return card_.ShouldUpdateExpiration(AutofillClock::Now()) ||
new_card_link_clicked_;
}
@@ -300,12 +301,12 @@ bool CardUnmaskPromptControllerImpl::InputExpirationIsValid(
// Convert 2 digit year to 4 digit year.
if (year_value < 100) {
base::Time::Exploded now;
- base::Time::Now().LocalExplode(&now);
+ AutofillClock::Now().LocalExplode(&now);
year_value += (now.year / 100) * 100;
}
return IsValidCreditCardExpirationDate(year_value, month_value,
- base::Time::Now());
+ AutofillClock::Now());
}
base::TimeDelta CardUnmaskPromptControllerImpl::GetSuccessMessageDuration()
diff --git a/chromium/components/autofill/core/browser/validation.cc b/chromium/components/autofill/core/browser/validation.cc
index 15a96e6ab22..d18ccbab5cf 100644
--- a/chromium/components/autofill/core/browser/validation.cc
+++ b/chromium/components/autofill/core/browser/validation.cc
@@ -6,14 +6,19 @@
#include <stddef.h>
+#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/state_names.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_regexes.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
namespace autofill {
@@ -94,6 +99,31 @@ bool IsValidCreditCardSecurityCode(const base::string16& code,
base::ContainsOnlyChars(code, base::ASCIIToUTF16("0123456789"));
}
+bool IsValidCreditCardNumberForBasicCardNetworks(
+ const base::string16& text,
+ const std::set<std::string>& supported_basic_card_networks,
+ base::string16* error_message) {
+ DCHECK(error_message);
+
+ // The type check is cheaper than the credit card number check.
+ const std::string basic_card_payment_type =
+ autofill::data_util::GetPaymentRequestData(
+ CreditCard::GetCreditCardType(text))
+ .basic_card_payment_type;
+ if (!supported_basic_card_networks.count(basic_card_payment_type)) {
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_VALIDATION_UNSUPPORTED_CREDIT_CARD_TYPE);
+ return false;
+ }
+
+ if (IsValidCreditCardNumber(text))
+ return true;
+
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE);
+ return false;
+}
+
bool IsValidEmailAddress(const base::string16& text) {
// E-Mail pattern as defined by the WhatWG. (4.10.7.1.5 E-Mail state)
const base::string16 kEmailPattern = base::ASCIIToUTF16(
@@ -174,4 +204,108 @@ bool IsSSN(const base::string16& text) {
return true;
}
+bool IsValidForType(const base::string16& value,
+ ServerFieldType type,
+ base::string16* error_message) {
+ switch (type) {
+ case CREDIT_CARD_NAME_FULL:
+ if (!value.empty())
+ return true;
+
+ if (error_message) {
+ *error_message =
+ l10n_util::GetStringUTF16(IDS_PAYMENTS_VALIDATION_INVALID_NAME);
+ }
+ break;
+
+ case CREDIT_CARD_EXP_MONTH: {
+ CreditCard temp;
+ // Expiration month was in an invalid format.
+ temp.SetExpirationMonthFromString(value, /* app_locale= */ std::string());
+ if (temp.expiration_month() == 0) {
+ if (error_message) {
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH);
+ }
+ break;
+ }
+ return true;
+ }
+
+ case CREDIT_CARD_EXP_2_DIGIT_YEAR:
+ case CREDIT_CARD_EXP_4_DIGIT_YEAR: {
+ CreditCard temp;
+ temp.SetExpirationYearFromString(value);
+ // Expiration year was in an invalid format.
+ if ((temp.expiration_year() == 0) ||
+ (type == CREDIT_CARD_EXP_2_DIGIT_YEAR && value.size() != 2u) ||
+ (type == CREDIT_CARD_EXP_4_DIGIT_YEAR && value.size() != 4u)) {
+ if (error_message) {
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR);
+ }
+ break;
+ }
+
+ base::Time::Exploded now_exploded;
+ AutofillClock::Now().LocalExplode(&now_exploded);
+ if (temp.expiration_year() >= now_exploded.year)
+ return true;
+
+ // If the year is before this year, it's expired.
+ if (error_message) {
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED);
+ }
+ break;
+ }
+
+ case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR:
+ case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR: {
+ const base::string16 pattern =
+ type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR
+ ? base::UTF8ToUTF16("^[0-9]{1,2}[-/|]?[0-9]{2}$")
+ : base::UTF8ToUTF16("^[0-9]{1,2}[-/|]?[0-9]{4}$");
+
+ CreditCard temp;
+ temp.SetExpirationDateFromString(value);
+
+ // Expiration date was in an invalid format.
+ if (temp.expiration_month() == 0 || temp.expiration_year() == 0 ||
+ !MatchesPattern(value, pattern)) {
+ if (error_message) {
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE);
+ }
+ break;
+ }
+
+ // Checking for card expiration.
+ if (IsValidCreditCardExpirationDate(temp.expiration_year(),
+ temp.expiration_month(),
+ AutofillClock::Now())) {
+ return true;
+ }
+
+ if (error_message) {
+ *error_message = l10n_util::GetStringUTF16(
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED);
+ }
+ break;
+ }
+
+ case CREDIT_CARD_NUMBER:
+ NOTREACHED() << "IsValidCreditCardNumberForBasicCardNetworks should be "
+ << "used to validate credit card numbers";
+ break;
+
+ default:
+ // Other types such as CREDIT_CARD_TYPE and CREDIT_CARD_VERIFICATION_CODE
+ // are not validated for now.
+ NOTREACHED() << "Attempting to validate unsupported type " << type;
+ break;
+ }
+ return false;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/validation.h b/chromium/components/autofill/core/browser/validation.h
index a09ae75cbb3..0b496e2b950 100644
--- a/chromium/components/autofill/core/browser/validation.h
+++ b/chromium/components/autofill/core/browser/validation.h
@@ -7,6 +7,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
+#include "components/autofill/core/browser/field_types.h"
namespace base {
class Time;
@@ -29,11 +30,19 @@ bool IsValidCreditCardNumber(const base::string16& text);
bool IsValidCreditCardSecurityCode(const base::string16& code,
const base::StringPiece card_type);
+// Returns true if |text| is a supported card type and a valid credit card
+// number. |error_message| can't be null and will be filled with the appropriate
+// error message.
+bool IsValidCreditCardNumberForBasicCardNetworks(
+ const base::string16& text,
+ const std::set<std::string>& supported_basic_card_networks,
+ base::string16* error_message);
+
// Returns true if |text| looks like a valid e-mail address.
bool IsValidEmailAddress(const base::string16& text);
-// Returns true if |text| is a valid US state name or abbreviation. It is
-// case insensitive. Valid for US states only.
+// Returns true if |text| is a valid US state name or abbreviation. It is case
+// insensitive. Valid for US states only.
bool IsValidState(const base::string16& text);
// Returns true if |text| looks like a valid zip code.
@@ -43,6 +52,12 @@ bool IsValidZip(const base::string16& text);
// Returns true if |text| looks like an SSN, with or without separators.
bool IsSSN(const base::string16& text);
+// Returns whether |value| is valid for the given |type|. If not null,
+// |error_message| is populated when the function returns false.
+bool IsValidForType(const base::string16& value,
+ ServerFieldType type,
+ base::string16* error_message);
+
} // namespace autofill
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_VALIDATION_H_
diff --git a/chromium/components/autofill/core/browser/validation_unittest.cc b/chromium/components/autofill/core/browser/validation_unittest.cc
index 798f53462bd..ec6ff0a346f 100644
--- a/chromium/components/autofill/core/browser/validation_unittest.cc
+++ b/chromium/components/autofill/core/browser/validation_unittest.cc
@@ -2,14 +2,19 @@
// 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/validation.h"
+
#include <stddef.h>
#include "base/macros.h"
+#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/credit_card.h"
-#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/strings/grit/components_strings.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
using base::ASCIIToUTF16;
@@ -33,24 +38,24 @@ struct SecurityCodeCardTypePair {
// From https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
const char* const kValidNumbers[] = {
- "378282246310005",
- "3714 4963 5398 431",
- "3787-3449-3671-000",
- "5610591081018250",
- "3056 9309 0259 04",
- "3852-0000-0232-37",
- "6011111111111117",
- "6011 0009 9013 9424",
- "3530-1113-3330-0000",
- "3566002020360505",
- "5555 5555 5555 4444",
- "5105-1051-0510-5100",
- "4111111111111111",
- "4012 8888 8888 1881",
- "4222-2222-2222-2",
- "5019717010103742",
- "6331101999990016",
- "6247130048162403",
+ "378282246310005",
+ "3714 4963 5398 431",
+ "3787-3449-3671-000",
+ "5610591081018250",
+ "3056 9309 0259 04",
+ "3852-0000-0232-37",
+ "6011111111111117",
+ "6011 0009 9013 9424",
+ "3530-1113-3330-0000",
+ "3566002020360505",
+ "5555 5555 5555 4444", // Mastercard.
+ "5105-1051-0510-5100",
+ "4111111111111111", // Visa.
+ "4012 8888 8888 1881",
+ "4222-2222-2222-2",
+ "5019717010103742",
+ "6331101999990016",
+ "6247130048162403",
};
const char* const kInvalidNumbers[] = {
"4111 1111 112", /* too short */
@@ -148,4 +153,263 @@ TEST(AutofillValidation, IsValidEmailAddress) {
}
}
+struct ValidationCase {
+ ValidationCase(const char* value,
+ ServerFieldType field_type,
+ bool expected_valid,
+ int expected_error_id)
+ : value(value),
+ field_type(field_type),
+ expected_valid(expected_valid),
+ expected_error_id(expected_error_id) {}
+ ~ValidationCase() {}
+
+ const char* const value;
+ const ServerFieldType field_type;
+ const bool expected_valid;
+ const int expected_error_id;
+};
+
+class AutofillTypeValidationTest
+ : public testing::TestWithParam<ValidationCase> {};
+
+TEST_P(AutofillTypeValidationTest, IsValidForType) {
+ base::string16 error_message;
+ EXPECT_EQ(GetParam().expected_valid,
+ IsValidForType(ASCIIToUTF16(GetParam().value),
+ GetParam().field_type, &error_message))
+ << "Failed to validate " << GetParam().value << " (type "
+ << GetParam().field_type << ")";
+ if (!GetParam().expected_valid) {
+ EXPECT_EQ(l10n_util::GetStringUTF16(GetParam().expected_error_id),
+ error_message);
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(
+ CreditCardExpDate,
+ AutofillTypeValidationTest,
+ testing::Values(
+ ValidationCase("05/2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase("05-2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase("052087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase("05|2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+
+ ValidationCase("05/2012",
+ CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
+ ValidationCase("MM/2012",
+ CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
+ ValidationCase("05/12",
+ CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
+ ValidationCase("05/45",
+ CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
+ ValidationCase("05/1987",
+ CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
+
+ ValidationCase("05/87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase("05-87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase("0587", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase("05|87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase("05/1987",
+ CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
+ ValidationCase("05/12",
+ CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED)));
+
+INSTANTIATE_TEST_CASE_P(
+ CreditCardMonth,
+ AutofillTypeValidationTest,
+ testing::Values(
+ ValidationCase("01", CREDIT_CARD_EXP_MONTH, true, 0),
+ ValidationCase("1", CREDIT_CARD_EXP_MONTH, true, 0),
+ ValidationCase("12", CREDIT_CARD_EXP_MONTH, true, 0),
+ ValidationCase(
+ "0",
+ CREDIT_CARD_EXP_MONTH,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH),
+ ValidationCase(
+ "-1",
+ CREDIT_CARD_EXP_MONTH,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH),
+ ValidationCase(
+ "13",
+ CREDIT_CARD_EXP_MONTH,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH)));
+
+INSTANTIATE_TEST_CASE_P(
+ CreditCardYear,
+ AutofillTypeValidationTest,
+ testing::Values(
+ /* 2-digit year */
+ ValidationCase("87", CREDIT_CARD_EXP_2_DIGIT_YEAR, true, 0),
+ // These are considered expired in the context of this millenium.
+ ValidationCase("02",
+ CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
+ ValidationCase("15",
+ CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
+ // Invalid formats.
+ ValidationCase(
+ "1",
+ CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
+ ValidationCase(
+ "123",
+ CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
+ ValidationCase(
+ "2087",
+ CREDIT_CARD_EXP_2_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
+
+ /* 4-digit year */
+ ValidationCase("2087", CREDIT_CARD_EXP_4_DIGIT_YEAR, true, 0),
+ // Expired.
+ ValidationCase("2000",
+ CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
+ ValidationCase("2015",
+ CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
+ // Invalid formats.
+ ValidationCase(
+ "00",
+ CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
+ ValidationCase(
+ "123",
+ CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
+ ValidationCase(
+ "87",
+ CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ false,
+ IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR)));
+
+struct CCNumberCase {
+ CCNumberCase(const char* value,
+ const std::set<std::string> supported_basic_card_networks,
+ bool expected_valid,
+ int expected_error_id)
+ : value(value),
+ supported_basic_card_networks(supported_basic_card_networks),
+ expected_valid(expected_valid),
+ expected_error_id(expected_error_id) {}
+ ~CCNumberCase() {}
+
+ const char* const value;
+ const std::set<std::string> supported_basic_card_networks;
+ const bool expected_valid;
+ const int expected_error_id;
+};
+
+class AutofillCCNumberValidationTest
+ : public testing::TestWithParam<CCNumberCase> {};
+
+TEST_P(AutofillCCNumberValidationTest, IsValidCreditCardNumber) {
+ base::string16 error_message;
+ EXPECT_EQ(GetParam().expected_valid,
+ IsValidCreditCardNumberForBasicCardNetworks(
+ ASCIIToUTF16(GetParam().value),
+ GetParam().supported_basic_card_networks, &error_message))
+ << "Failed to validate CC number " << GetParam().value;
+ if (!GetParam().expected_valid) {
+ EXPECT_EQ(l10n_util::GetStringUTF16(GetParam().expected_error_id),
+ error_message);
+ }
+}
+
+const static std::set<std::string> kAllBasicCardNetworks{
+ "amex", "discover", "diners", "jcb",
+ "mastercard", "mir", "unionpay", "visa"};
+
+INSTANTIATE_TEST_CASE_P(
+ CreditCardNumber,
+ AutofillCCNumberValidationTest,
+ testing::Values(
+ CCNumberCase(kValidNumbers[0], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[1], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[2], kAllBasicCardNetworks, true, 0),
+ // Generic card not supported.
+ CCNumberCase(kValidNumbers[3],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_VALIDATION_UNSUPPORTED_CREDIT_CARD_TYPE),
+
+ CCNumberCase(kValidNumbers[4], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[5], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[6], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[7], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[8], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[9], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[10], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[11], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[12], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[13], kAllBasicCardNetworks, true, 0),
+ CCNumberCase(kValidNumbers[14], kAllBasicCardNetworks, true, 0),
+ // Generic cards not supported.
+ CCNumberCase(kValidNumbers[15],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_VALIDATION_UNSUPPORTED_CREDIT_CARD_TYPE),
+ CCNumberCase(kValidNumbers[16],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_VALIDATION_UNSUPPORTED_CREDIT_CARD_TYPE),
+
+ CCNumberCase(kValidNumbers[17], kAllBasicCardNetworks, true, 0),
+
+ CCNumberCase(kInvalidNumbers[0],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE),
+ CCNumberCase(kInvalidNumbers[1],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE),
+ CCNumberCase(kInvalidNumbers[2],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE),
+ CCNumberCase(kInvalidNumbers[3],
+ kAllBasicCardNetworks,
+ false,
+ IDS_PAYMENTS_CARD_NUMBER_INVALID_VALIDATION_MESSAGE),
+
+ // Valid numbers can still be invalid if the type is not supported.
+ CCNumberCase(kValidNumbers[10], // Mastercard number.
+ {"visa"},
+ false,
+ IDS_PAYMENTS_VALIDATION_UNSUPPORTED_CREDIT_CARD_TYPE),
+ CCNumberCase(kValidNumbers[12], // Visa number.
+ {"jcb", "diners", "unionpay", "mastercard"},
+ false,
+ IDS_PAYMENTS_VALIDATION_UNSUPPORTED_CREDIT_CARD_TYPE)));
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
index 0bf47d314ba..589df1628af 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -35,6 +35,7 @@ using syncer::EntityDataMap;
using syncer::MetadataChangeList;
using syncer::ModelError;
using syncer::ModelTypeChangeProcessor;
+using syncer::ModelTypeSyncBridge;
using syncer::MutableDataBatch;
namespace autofill {
@@ -57,15 +58,21 @@ void* UserDataKey() {
return reinterpret_cast<void*>(&user_data_key);
}
+std::string EscapeIdentifiers(const AutofillSpecifics& specifics) {
+ return net::EscapePath(specifics.name()) +
+ std::string(kAutocompleteTagDelimiter) +
+ net::EscapePath(specifics.value());
+}
+
std::unique_ptr<EntityData> CreateEntityData(const AutofillEntry& entry) {
auto entity_data = base::MakeUnique<EntityData>();
- entity_data->non_unique_name = base::UTF16ToUTF8(entry.key().name());
AutofillSpecifics* autofill = entity_data->specifics.mutable_autofill();
autofill->set_name(base::UTF16ToUTF8(entry.key().name()));
autofill->set_value(base::UTF16ToUTF8(entry.key().value()));
autofill->add_usage_timestamp(entry.date_created().ToInternalValue());
if (entry.date_created() != entry.date_last_used())
autofill->add_usage_timestamp(entry.date_last_used().ToInternalValue());
+ entity_data->non_unique_name = EscapeIdentifiers(*autofill);
return entity_data;
}
@@ -143,17 +150,19 @@ class SyncDifferenceTracker {
return ModelError(FROM_HERE, "Failed reading from WebDatabase.");
} else if (!local) {
save_to_local_.push_back(remote);
- } else if (remote != local.value()) {
- if (specifics.usage_timestamp().empty()) {
- // Skip merging if there are no timestamps. We don't want to wipe out
- // a local value of |date_created| if the remote copy is oddly formed.
- save_to_sync_.push_back(local.value());
- } else {
- const AutofillEntry merged = MergeEntryDates(local.value(), remote);
- save_to_local_.push_back(merged);
- save_to_sync_.push_back(merged);
- }
+ } else {
unique_to_local_.erase(local.value());
+ if (remote != local.value()) {
+ if (specifics.usage_timestamp().empty()) {
+ // Skip merging if there are no timestamps. We don't want to wipe out
+ // a local value of |date_created| if the remote copy is oddly formed.
+ save_to_sync_.push_back(local.value());
+ } else {
+ const AutofillEntry merged = MergeEntryDates(local.value(), remote);
+ save_to_local_.push_back(merged);
+ save_to_sync_.push_back(merged);
+ }
+ }
}
return {};
}
@@ -283,10 +292,11 @@ void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend(
}
// static
-AutocompleteSyncBridge* AutocompleteSyncBridge::FromWebDataService(
+base::WeakPtr<ModelTypeSyncBridge> AutocompleteSyncBridge::FromWebDataService(
AutofillWebDataService* web_data_service) {
return static_cast<AutocompleteSyncBridge*>(
- web_data_service->GetDBUserData()->GetUserData(UserDataKey()));
+ web_data_service->GetDBUserData()->GetUserData(UserDataKey()))
+ ->AsWeakPtr();
}
AutocompleteSyncBridge::AutocompleteSyncBridge(
@@ -318,8 +328,7 @@ Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
EntityDataMap entity_data_map) {
DCHECK(thread_checker_.CalledOnValidThread());
- // TODO(skym, crbug.com/680218): Uncomment and add unit tests.
- /*SyncDifferenceTracker tracker(GetAutofillTable());
+ SyncDifferenceTracker tracker(GetAutofillTable());
for (auto kv : entity_data_map) {
DCHECK(kv.second->specifics.has_autofill());
RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics(
@@ -330,7 +339,7 @@ Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
RETURN_IF_ERROR(tracker.FlushToSync(true, std::move(metadata_change_list),
change_processor()));
web_data_backend_->RemoveExpiredFormElements();
- web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL);*/
+ web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL);
return {};
}
@@ -449,11 +458,8 @@ void AutocompleteSyncBridge::LoadMetadata() {
std::string AutocompleteSyncBridge::GetClientTag(
const EntityData& entity_data) {
DCHECK(entity_data.specifics.has_autofill());
- const AutofillSpecifics specifics = entity_data.specifics.autofill();
return std::string(kAutocompleteEntryNamespaceTag) +
- net::EscapePath(specifics.name()) +
- std::string(kAutocompleteTagDelimiter) +
- net::EscapePath(specifics.value());
+ EscapeIdentifiers(entity_data.specifics.autofill());
}
std::string AutocompleteSyncBridge::GetStorageKey(
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
index cd350bec322..2ec41c5ae51 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "base/supports_user_data.h"
@@ -39,7 +40,7 @@ class AutocompleteSyncBridge : public base::SupportsUserData::Data,
AutofillWebDataService* web_data_service,
AutofillWebDataBackend* web_data_backend);
- static AutocompleteSyncBridge* FromWebDataService(
+ static base::WeakPtr<syncer::ModelTypeSyncBridge> FromWebDataService(
AutofillWebDataService* web_data_service);
// syncer::ModelTypeSyncBridge implementation.
diff --git a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
index b12d0ef223f..a4334eaa230 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <map>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -33,12 +34,15 @@ using base::ScopedTempDir;
using base::Time;
using base::TimeDelta;
using sync_pb::AutofillSpecifics;
+using sync_pb::EntityMetadata;
using sync_pb::EntitySpecifics;
+using sync_pb::ModelTypeState;
using syncer::DataBatch;
-using syncer::EntityData;
-using syncer::EntityDataPtr;
using syncer::EntityChange;
using syncer::EntityChangeList;
+using syncer::EntityData;
+using syncer::EntityDataPtr;
+using syncer::EntityDataMap;
using syncer::FakeModelTypeChangeProcessor;
using syncer::KeyAndData;
using syncer::ModelError;
@@ -130,20 +134,18 @@ class AutocompleteSyncBridgeTest : public testing::Test {
db_.AddTable(&table_);
db_.Init(temp_dir_.GetPath().AppendASCII("SyncTestWebDatabase"));
backend_.SetWebDatabase(&db_);
-
- sync_pb::ModelTypeState model_type_state;
- model_type_state.set_initial_sync_done(true);
- table_.UpdateModelTypeState(syncer::AUTOFILL, model_type_state);
-
- bridge_.reset(new AutocompleteSyncBridge(
- &backend_,
- base::Bind(
- &AutocompleteSyncBridgeTest::CreateModelTypeChangeProcessor,
- base::Unretained(this))));
+ ResetBridge();
}
}
~AutocompleteSyncBridgeTest() override {}
+ void ResetBridge() {
+ bridge_.reset(new AutocompleteSyncBridge(
+ &backend_,
+ base::Bind(&AutocompleteSyncBridgeTest::CreateModelTypeChangeProcessor,
+ base::Unretained(this))));
+ }
+
void SaveSpecificsToTable(
const std::vector<AutofillSpecifics>& specifics_list) {
std::vector<AutofillEntry> new_entries;
@@ -177,6 +179,13 @@ class AutocompleteSyncBridgeTest : public testing::Test {
return CreateSpecifics(suffix, std::vector<int>{0});
}
+ std::string GetClientTag(const AutofillSpecifics& specifics) {
+ std::string tag =
+ bridge()->GetClientTag(SpecificsToEntity(specifics).value());
+ EXPECT_FALSE(tag.empty());
+ return tag;
+ }
+
std::string GetStorageKey(const AutofillSpecifics& specifics) {
std::string key =
bridge()->GetStorageKey(SpecificsToEntity(specifics).value());
@@ -194,6 +203,15 @@ class AutocompleteSyncBridgeTest : public testing::Test {
return changes;
}
+ EntityDataMap CreateEntityDataMap(
+ const std::vector<AutofillSpecifics>& specifics_vector) {
+ EntityDataMap map;
+ for (const auto& specifics : specifics_vector) {
+ map[GetStorageKey(specifics)] = SpecificsToEntity(specifics);
+ }
+ return map;
+ }
+
void VerifyApplyChanges(const std::vector<EntityChange>& changes) {
const auto error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), changes);
@@ -204,6 +222,12 @@ class AutocompleteSyncBridgeTest : public testing::Test {
VerifyApplyChanges(EntityAddList(specifics));
}
+ void VerifyMerge(const std::vector<AutofillSpecifics>& specifics) {
+ const auto error = bridge()->MergeSyncData(
+ bridge()->CreateMetadataChangeList(), CreateEntityDataMap(specifics));
+ EXPECT_FALSE(error);
+ }
+
std::map<std::string, AutofillSpecifics> ExpectedMap(
const std::vector<AutofillSpecifics>& specifics_vector) {
std::map<std::string, AutofillSpecifics> map;
@@ -265,7 +289,50 @@ class AutocompleteSyncBridgeTest : public testing::Test {
};
TEST_F(AutocompleteSyncBridgeTest, GetClientTag) {
- // TODO(skym, crbug.com/675991): Implementation.
+ std::string tag = GetClientTag(CreateSpecifics(1));
+ EXPECT_EQ(tag, GetClientTag(CreateSpecifics(1)));
+ EXPECT_NE(tag, GetClientTag(CreateSpecifics(2)));
+}
+
+TEST_F(AutocompleteSyncBridgeTest, GetClientTagNotAffectedByTimestamp) {
+ AutofillSpecifics specifics = CreateSpecifics(1);
+ std::string tag = GetClientTag(specifics);
+
+ specifics.add_usage_timestamp(1);
+ EXPECT_EQ(tag, GetClientTag(specifics));
+
+ specifics.add_usage_timestamp(0);
+ EXPECT_EQ(tag, GetClientTag(specifics));
+
+ specifics.add_usage_timestamp(-1);
+ EXPECT_EQ(tag, GetClientTag(specifics));
+}
+
+TEST_F(AutocompleteSyncBridgeTest, GetClientTagRespectsNullCharacter) {
+ AutofillSpecifics specifics;
+ std::string tag = GetClientTag(specifics);
+
+ specifics.set_value(std::string("\0", 1));
+ EXPECT_NE(tag, GetClientTag(specifics));
+}
+
+// The client tags should never change as long as we want to maintain backwards
+// compatibility with the previous iteration of autocomplete-sync integration,
+// AutocompleteSyncableService and Sync's Directory. This is because old clients
+// will re-generate client tags and then hashes on local changes, and this
+// process must create identical values to what this client has created. If this
+// test case starts failing, you should not alter the fixed values here unless
+// you know what you're doing.
+TEST_F(AutocompleteSyncBridgeTest, GetClientTagFixed) {
+ EXPECT_EQ("autofill_entry|name%201|value%201",
+ GetClientTag(CreateSpecifics(1)));
+ EXPECT_EQ("autofill_entry|name%202|value%202",
+ GetClientTag(CreateSpecifics(2)));
+ EXPECT_EQ("autofill_entry||", GetClientTag(AutofillSpecifics()));
+ AutofillSpecifics specifics;
+ specifics.set_name("\xEC\xA4\x91");
+ specifics.set_value("\xD0\x80");
+ EXPECT_EQ("autofill_entry|%EC%A4%91|%D0%80", GetClientTag(specifics));
}
TEST_F(AutocompleteSyncBridgeTest, GetStorageKey) {
@@ -274,8 +341,7 @@ TEST_F(AutocompleteSyncBridgeTest, GetStorageKey) {
EXPECT_NE(key, GetStorageKey(CreateSpecifics(2)));
}
-// Timestamps should not affect storage keys.
-TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyTimestamp) {
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyNotAffectedByTimestamp) {
AutofillSpecifics specifics = CreateSpecifics(1);
std::string key = GetStorageKey(specifics);
@@ -289,8 +355,7 @@ TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyTimestamp) {
EXPECT_EQ(key, GetStorageKey(specifics));
}
-// Verify that the \0 character is respected as a difference.
-TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyNull) {
+TEST_F(AutocompleteSyncBridgeTest, GetStorageKeyRespectsNullCharacter) {
AutofillSpecifics specifics;
std::string key = GetStorageKey(specifics);
@@ -517,8 +582,108 @@ TEST_F(AutocompleteSyncBridgeTest, LocalEntryDeleted) {
}
TEST_F(AutocompleteSyncBridgeTest, LoadMetadataCalled) {
- EXPECT_NE(processor()->metadata(), nullptr);
+ EXPECT_NE(nullptr, processor()->metadata());
+ EXPECT_FALSE(
+ processor()->metadata()->GetModelTypeState().initial_sync_done());
+ EXPECT_EQ(0u, processor()->metadata()->TakeAllMetadata().size());
+
+ ModelTypeState model_type_state;
+ model_type_state.set_initial_sync_done(true);
+ EXPECT_TRUE(
+ table()->UpdateModelTypeState(syncer::AUTOFILL, model_type_state));
+ EXPECT_TRUE(
+ table()->UpdateSyncMetadata(syncer::AUTOFILL, "key", EntityMetadata()));
+
+ ResetBridge();
+
+ EXPECT_NE(nullptr, processor()->metadata());
EXPECT_TRUE(processor()->metadata()->GetModelTypeState().initial_sync_done());
+ EXPECT_EQ(1u, processor()->metadata()->TakeAllMetadata().size());
+}
+
+TEST_F(AutocompleteSyncBridgeTest, MergeSyncDataEmpty) {
+ VerifyMerge(std::vector<AutofillSpecifics>());
+
+ VerifyAllData(std::vector<AutofillSpecifics>());
+ EXPECT_EQ(0u, processor()->delete_set().size());
+ EXPECT_EQ(0u, processor()->put_multimap().size());
+}
+
+TEST_F(AutocompleteSyncBridgeTest, MergeSyncDataRemoteOnly) {
+ const AutofillSpecifics specifics1 = CreateSpecifics(1, {2});
+ const AutofillSpecifics specifics2 = CreateSpecifics(2, {3, 4});
+
+ VerifyMerge({specifics1, specifics2});
+
+ VerifyAllData({specifics1, specifics2});
+ EXPECT_EQ(0u, processor()->delete_set().size());
+ EXPECT_EQ(0u, processor()->put_multimap().size());
+}
+
+TEST_F(AutocompleteSyncBridgeTest, MergeSyncDataLocalOnly) {
+ const AutofillSpecifics specifics1 = CreateSpecifics(1, {2});
+ const AutofillSpecifics specifics2 = CreateSpecifics(2, {3, 4});
+ VerifyApplyAdds({specifics1, specifics2});
+ VerifyAllData({specifics1, specifics2});
+
+ VerifyMerge(std::vector<AutofillSpecifics>());
+
+ VerifyAllData({specifics1, specifics2});
+ EXPECT_EQ(2u, processor()->put_multimap().size());
+ VerifyProcessorRecordedPut(specifics1);
+ VerifyProcessorRecordedPut(specifics2);
+ EXPECT_EQ(0u, processor()->delete_set().size());
+}
+
+TEST_F(AutocompleteSyncBridgeTest, MergeSyncDataAllMerged) {
+ const AutofillSpecifics local1 = CreateSpecifics(1, {2});
+ const AutofillSpecifics local2 = CreateSpecifics(2, {3, 4});
+ const AutofillSpecifics local3 = CreateSpecifics(3, {4});
+ const AutofillSpecifics local4 = CreateSpecifics(4, {5, 6});
+ const AutofillSpecifics local5 = CreateSpecifics(5, {6, 9});
+ const AutofillSpecifics local6 = CreateSpecifics(6, {7, 9});
+ const AutofillSpecifics remote1 = local1;
+ const AutofillSpecifics remote2 = local2;
+ const AutofillSpecifics remote3 = CreateSpecifics(3, {5});
+ const AutofillSpecifics remote4 = CreateSpecifics(4, {7, 8});
+ const AutofillSpecifics remote5 = CreateSpecifics(5, {8, 9});
+ const AutofillSpecifics remote6 = CreateSpecifics(6, {8, 10});
+ const AutofillSpecifics merged1 = local1;
+ const AutofillSpecifics merged2 = local2;
+ const AutofillSpecifics merged3 = CreateSpecifics(3, {4, 5});
+ const AutofillSpecifics merged4 = CreateSpecifics(4, {5, 8});
+ const AutofillSpecifics merged5 = local5;
+ const AutofillSpecifics merged6 = CreateSpecifics(6, {7, 10});
+ VerifyApplyAdds({local1, local2, local3, local4, local5, local6});
+
+ VerifyMerge({remote1, remote2, remote3, remote4, remote5, remote6});
+
+ VerifyAllData({merged1, merged2, merged3, merged4, merged5, merged6});
+ EXPECT_EQ(4u, processor()->put_multimap().size());
+ VerifyProcessorRecordedPut(merged3);
+ VerifyProcessorRecordedPut(merged4);
+ VerifyProcessorRecordedPut(merged5);
+ VerifyProcessorRecordedPut(merged6);
+ EXPECT_EQ(0u, processor()->delete_set().size());
+}
+
+TEST_F(AutocompleteSyncBridgeTest, MergeSyncDataMixed) {
+ const AutofillSpecifics local1 = CreateSpecifics(1, {2, 3});
+ const AutofillSpecifics remote2 = CreateSpecifics(2, {2, 3});
+ const AutofillSpecifics specifics3 = CreateSpecifics(3, {2, 3});
+ const AutofillSpecifics local4 = CreateSpecifics(4, {1, 3});
+ const AutofillSpecifics remote4 = CreateSpecifics(4, {2, 4});
+ const AutofillSpecifics merged4 = CreateSpecifics(4, {1, 4});
+
+ VerifyApplyAdds({local1, specifics3, local4});
+
+ VerifyMerge({remote2, specifics3, remote4});
+
+ VerifyAllData({local1, remote2, specifics3, merged4});
+ EXPECT_EQ(2u, processor()->put_multimap().size());
+ VerifyProcessorRecordedPut(local1);
+ VerifyProcessorRecordedPut(merged4);
+ EXPECT_EQ(0u, processor()->delete_set().size());
}
} // namespace autofill
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 aff312184ea..d303d165ae5 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_syncable_service.cc
@@ -309,8 +309,7 @@ void AutocompleteSyncableService::CreateOrUpdateEntry(
return;
}
- AutofillKey key(autofill_specifics.name().c_str(),
- autofill_specifics.value().c_str());
+ AutofillKey key(autofill_specifics.name(), autofill_specifics.value());
AutocompleteEntryMap::iterator it = loaded_data->find(key);
const google::protobuf::RepeatedField<int64_t>& timestamps =
autofill_specifics.usage_timestamp();
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_entry.cc b/chromium/components/autofill/core/browser/webdata/autofill_entry.cc
index 58494a7c93e..3a48a50c10e 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_entry.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_entry.cc
@@ -4,6 +4,7 @@
#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include <string>
#include <tuple>
#include "base/strings/utf_string_conversions.h"
@@ -18,7 +19,8 @@ AutofillKey::AutofillKey(const base::string16& name,
value_(value) {
}
-AutofillKey::AutofillKey(const char* name, const char* value)
+AutofillKey::AutofillKey(const std::string& name,
+ const std::string& value)
: name_(base::UTF8ToUTF16(name)),
value_(base::UTF8ToUTF16(value)) {
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_entry.h b/chromium/components/autofill/core/browser/webdata/autofill_entry.h
index 4a934dd4510..a7932fde2cd 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_entry.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_entry.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_ENTRY_H__
#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_ENTRY_H__
+#include <string>
+
#include "base/strings/string16.h"
#include "base/time/time.h"
@@ -14,7 +16,7 @@ class AutofillKey {
public:
AutofillKey();
AutofillKey(const base::string16& name, const base::string16& value);
- AutofillKey(const char* name, const char* value);
+ AutofillKey(const std::string& name, const std::string& value);
AutofillKey(const AutofillKey& key);
virtual ~AutofillKey();
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index 503eb0fa9e7..72cf35b3c7b 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -11,8 +11,7 @@
#include <limits>
#include <map>
#include <set>
-#include <string>
-#include <vector>
+#include <utility>
#include "base/command_line.h"
#include "base/guid.h"
@@ -31,12 +30,13 @@
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
+#include "components/autofill/core/browser/webdata/autofill_table_encryptor.h"
+#include "components/autofill/core/browser/webdata/autofill_table_encryptor_factory.h"
+#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_field_data.h"
-#include "components/os_crypt/os_crypt.h"
#include "components/sync/base/model_type.h"
-#include "components/sync/model/metadata_batch.h"
#include "components/sync/protocol/entity_metadata.pb.h"
#include "components/sync/protocol/model_type_state.pb.h"
#include "components/webdata/common/web_database.h"
@@ -130,17 +130,19 @@ std::unique_ptr<AutofillProfile> AutofillProfileFromStatement(
}
void BindEncryptedCardToColumn(sql::Statement* s,
- int column_index,
- const base::string16& number) {
+ int column_index,
+ const base::string16& number,
+ const AutofillTableEncryptor& encryptor) {
std::string encrypted_data;
- OSCrypt::EncryptString16(number, &encrypted_data);
+ encryptor.EncryptString16(number, &encrypted_data);
s->BindBlob(column_index, encrypted_data.data(),
static_cast<int>(encrypted_data.length()));
}
void BindCreditCardToStatement(const CreditCard& credit_card,
const Time& modification_date,
- sql::Statement* s) {
+ sql::Statement* s,
+ const AutofillTableEncryptor& encryptor) {
DCHECK(base::IsValidGUID(credit_card.guid()));
int index = 0;
s->BindString(index++, credit_card.guid());
@@ -148,8 +150,8 @@ void BindCreditCardToStatement(const CreditCard& credit_card,
s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_NAME_FULL));
s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_MONTH));
s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_4_DIGIT_YEAR));
- BindEncryptedCardToColumn(s, index++,
- credit_card.GetRawInfo(CREDIT_CARD_NUMBER));
+ BindEncryptedCardToColumn(
+ s, index++, credit_card.GetRawInfo(CREDIT_CARD_NUMBER), encryptor);
s->BindInt64(index++, credit_card.use_count());
s->BindInt64(index++, credit_card.use_date().ToTimeT());
@@ -158,8 +160,10 @@ void BindCreditCardToStatement(const CreditCard& credit_card,
s->BindString(index++, credit_card.billing_address_id());
}
-base::string16 UnencryptedCardFromColumn(const sql::Statement& s,
- int column_index) {
+base::string16 UnencryptedCardFromColumn(
+ const sql::Statement& s,
+ int column_index,
+ const AutofillTableEncryptor& encryptor) {
base::string16 credit_card_number;
int encrypted_number_len = s.ColumnByteLength(column_index);
if (encrypted_number_len) {
@@ -167,12 +171,14 @@ base::string16 UnencryptedCardFromColumn(const sql::Statement& s,
encrypted_number.resize(encrypted_number_len);
memcpy(&encrypted_number[0], s.ColumnBlob(column_index),
encrypted_number_len);
- OSCrypt::DecryptString16(encrypted_number, &credit_card_number);
+ encryptor.DecryptString16(encrypted_number, &credit_card_number);
}
return credit_card_number;
}
-std::unique_ptr<CreditCard> CreditCardFromStatement(const sql::Statement& s) {
+std::unique_ptr<CreditCard> CreditCardFromStatement(
+ const sql::Statement& s,
+ const AutofillTableEncryptor& encryptor) {
std::unique_ptr<CreditCard> credit_card(new CreditCard);
int index = 0;
@@ -184,7 +190,7 @@ std::unique_ptr<CreditCard> CreditCardFromStatement(const sql::Statement& s) {
credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR,
s.ColumnString16(index++));
credit_card->SetRawInfo(CREDIT_CARD_NUMBER,
- UnencryptedCardFromColumn(s, index++));
+ UnencryptedCardFromColumn(s, index++, encryptor));
credit_card->set_use_count(s.ColumnInt64(index++));
credit_card->set_use_date(Time::FromTimeT(s.ColumnInt64(index++)));
credit_card->set_modification_date(Time::FromTimeT(s.ColumnInt64(index++)));
@@ -400,7 +406,10 @@ base::string16 Substitute(const base::string16& s,
// static
const size_t AutofillTable::kMaxDataLength = 1024;
-AutofillTable::AutofillTable() {
+AutofillTable::AutofillTable()
+ : autofill_table_encryptor_(
+ AutofillTableEncryptorFactory::GetInstance()->Create()) {
+ DCHECK(autofill_table_encryptor_);
}
AutofillTable::~AutofillTable() {
@@ -481,12 +490,12 @@ bool AutofillTable::MigrateToVersion(int version,
bool AutofillTable::AddFormFieldValues(
const std::vector<FormFieldData>& elements,
std::vector<AutofillChange>* changes) {
- return AddFormFieldValuesTime(elements, changes, Time::Now());
+ return AddFormFieldValuesTime(elements, changes, AutofillClock::Now());
}
bool AutofillTable::AddFormFieldValue(const FormFieldData& element,
std::vector<AutofillChange>* changes) {
- return AddFormFieldValueTime(element, changes, Time::Now());
+ return AddFormFieldValueTime(element, changes, AutofillClock::Now());
}
bool AutofillTable::GetFormValuesForElementName(
@@ -674,7 +683,7 @@ bool AutofillTable::RemoveFormElementsAddedBetween(
bool AutofillTable::RemoveExpiredFormElements(
std::vector<AutofillChange>* changes) {
Time expiration_time =
- Time::Now() - TimeDelta::FromDays(kExpirationPeriodInDays);
+ AutofillClock::Now() - TimeDelta::FromDays(kExpirationPeriodInDays);
// Query for the name and value of all form elements that were last used
// before the |expiration_time|.
@@ -886,7 +895,7 @@ bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) {
" zipcode, sorting_code, country_code, use_count, use_date, "
" date_modified, origin, language_code)"
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
- BindAutofillProfileToStatement(profile, Time::Now(), &s);
+ BindAutofillProfileToStatement(profile, AutofillClock::Now(), &s);
if (!s.Run())
return false;
@@ -950,21 +959,22 @@ bool AutofillTable::GetServerProfiles(
sql::Statement s(db_->GetUniqueStatement(
"SELECT "
- "id,"
- "use_count,"
- "use_date,"
- "recipient_name,"
- "company_name,"
- "street_address,"
- "address_1," // ADDRESS_HOME_STATE
- "address_2," // ADDRESS_HOME_CITY
- "address_3," // ADDRESS_HOME_DEPENDENT_LOCALITY
- "address_4," // Not supported in AutofillProfile yet.
- "postal_code," // ADDRESS_HOME_ZIP
- "sorting_code," // ADDRESS_HOME_SORTING_CODE
- "country_code," // ADDRESS_HOME_COUNTRY
- "phone_number," // PHONE_HOME_WHOLE_NUMBER
- "language_code "
+ "id,"
+ "use_count,"
+ "use_date,"
+ "recipient_name,"
+ "company_name,"
+ "street_address,"
+ "address_1," // ADDRESS_HOME_STATE
+ "address_2," // ADDRESS_HOME_CITY
+ "address_3," // ADDRESS_HOME_DEPENDENT_LOCALITY
+ "address_4," // Not supported in AutofillProfile yet.
+ "postal_code," // ADDRESS_HOME_ZIP
+ "sorting_code," // ADDRESS_HOME_SORTING_CODE
+ "country_code," // ADDRESS_HOME_COUNTRY
+ "phone_number," // PHONE_HOME_WHOLE_NUMBER
+ "language_code, "
+ "has_converted "
"FROM server_addresses addresses "
"LEFT OUTER JOIN server_address_metadata USING (id)"));
@@ -976,7 +986,7 @@ bool AutofillTable::GetServerProfiles(
profile->set_use_count(s.ColumnInt64(index++));
profile->set_use_date(Time::FromInternalValue(s.ColumnInt64(index++)));
// Modification date is not tracked for server profiles. Explicitly set it
- // here to override the default value of Time::Now().
+ // here to override the default value of AutofillClock::Now().
profile->set_modification_date(Time());
base::string16 recipient_name = s.ColumnString16(index++);
@@ -992,6 +1002,7 @@ bool AutofillTable::GetServerProfiles(
profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++));
base::string16 phone_number = s.ColumnString16(index++);
profile->set_language_code(s.ColumnString(index++));
+ profile->set_has_converted(s.ColumnBool(index++));
// SetInfo instead of SetRawInfo so the constituent pieces will be parsed
// for these data types.
@@ -1055,6 +1066,9 @@ void AutofillTable::SetServerProfiles(
insert.Run();
insert.Reset(true);
+
+ // Save the use count and use date of the profile.
+ UpdateServerAddressMetadata(profile);
}
// Delete metadata that's no longer relevant.
@@ -1087,10 +1101,11 @@ bool AutofillTable::UpdateAutofillProfile(const AutofillProfile& profile) {
" city=?, state=?, zipcode=?, sorting_code=?, country_code=?, "
" use_count=?, use_date=?, date_modified=?, origin=?, language_code=? "
"WHERE guid=?"));
- BindAutofillProfileToStatement(
- profile,
- update_modification_date ? Time::Now() : old_profile->modification_date(),
- &s);
+ BindAutofillProfileToStatement(profile,
+ update_modification_date
+ ? AutofillClock::Now()
+ : old_profile->modification_date(),
+ &s);
s.BindString(14, profile.guid());
bool result = s.Run();
@@ -1160,7 +1175,8 @@ bool AutofillTable::AddCreditCard(const CreditCard& credit_card) {
" card_number_encrypted, use_count, use_date, date_modified, origin,"
" billing_address_id)"
"VALUES (?,?,?,?,?,?,?,?,?,?)"));
- BindCreditCardToStatement(credit_card, Time::Now(), &s);
+ BindCreditCardToStatement(credit_card, AutofillClock::Now(), &s,
+ *autofill_table_encryptor_);
if (!s.Run())
return false;
@@ -1183,7 +1199,7 @@ std::unique_ptr<CreditCard> AutofillTable::GetCreditCard(
if (!s.Step())
return std::unique_ptr<CreditCard>();
- return CreditCardFromStatement(s);
+ return CreditCardFromStatement(s, *autofill_table_encryptor_);
}
bool AutofillTable::GetCreditCards(
@@ -1232,7 +1248,8 @@ bool AutofillTable::GetServerCreditCards(
// If the card_number_encrypted field is nonempty, we can assume this card
// is a full card, otherwise it's masked.
- base::string16 full_card_number = UnencryptedCardFromColumn(s, index++);
+ base::string16 full_card_number =
+ UnencryptedCardFromColumn(s, index++, *autofill_table_encryptor_);
base::string16 last_four = s.ColumnString16(index++);
CreditCard::RecordType record_type = full_card_number.empty() ?
CreditCard::MASKED_SERVER_CARD :
@@ -1248,7 +1265,7 @@ bool AutofillTable::GetServerCreditCards(
card->set_use_count(s.ColumnInt64(index++));
card->set_use_date(Time::FromInternalValue(s.ColumnInt64(index++)));
// Modification date is not tracked for server cards. Explicitly set it here
- // to override the default value of Time::Now().
+ // to override the default value of AutofillClock::Now().
card->set_modification_date(Time());
std::string card_type = s.ColumnString(index++);
@@ -1339,10 +1356,10 @@ bool AutofillTable::UnmaskServerCreditCard(const CreditCard& masked,
s.BindString(0, masked.server_id());
std::string encrypted_data;
- OSCrypt::EncryptString16(full_number, &encrypted_data);
+ autofill_table_encryptor_->EncryptString16(full_number, &encrypted_data);
s.BindBlob(1, encrypted_data.data(),
static_cast<int>(encrypted_data.length()));
- s.BindInt64(2, Time::Now().ToInternalValue()); // unmask_date
+ s.BindInt64(2, AutofillClock::Now().ToInternalValue()); // unmask_date
s.Run();
@@ -1410,7 +1427,7 @@ bool AutofillTable::UpdateServerAddressMetadata(
"VALUES (?,?,?,?)"));
s.BindInt64(0, profile.use_count());
s.BindInt64(1, profile.use_date().ToInternalValue());
- s.BindBool(2, false);
+ s.BindBool(2, profile.has_converted());
s.BindString(3, profile.server_id());
s.Run();
@@ -1469,11 +1486,11 @@ bool AutofillTable::UpdateCreditCard(const CreditCard& credit_card) {
"expiration_year=?, card_number_encrypted=?, use_count=?, use_date=?,"
"date_modified=?, origin=?, billing_address_id=?"
"WHERE guid=?1"));
- BindCreditCardToStatement(
- credit_card,
- update_modification_date ? Time::Now() :
- old_credit_card->modification_date(),
- &s);
+ BindCreditCardToStatement(credit_card,
+ update_modification_date
+ ? AutofillClock::Now()
+ : old_credit_card->modification_date(),
+ &s, *autofill_table_encryptor_);
bool result = s.Run();
DCHECK_GT(db_->GetLastChangeCount(), 0);
@@ -1686,7 +1703,7 @@ bool AutofillTable::GetAllSyncMetadata(syncer::ModelType model_type,
syncer::EntityMetadataMap metadata_records;
if (GetAllSyncEntityMetadata(model_type, &metadata_records)) {
for (const auto& pair : metadata_records) {
- // todo(pnoland): add batch transfer of metadata map
+ // TODO(pnoland): Add batch transfer of metadata map.
metadata_batch->AddMetadata(pair.first, pair.second);
}
} else {
@@ -1762,7 +1779,7 @@ bool AutofillTable::GetModelTypeState(syncer::ModelType model_type,
"SELECT value FROM autofill_model_type_state WHERE id=1"));
if (!s.Step()) {
- return false;
+ return true;
}
std::string serialized_state = s.ColumnString(0);
@@ -2527,4 +2544,4 @@ bool AutofillTable::
return transaction.Commit();
}
-} // namespace autofill \ No newline at end of file
+} // 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 2f5fff15431..f3f8a14dcc4 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <memory>
+#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
@@ -23,16 +24,12 @@ namespace base {
class Time;
}
-namespace sync_pb {
-class EntityMetadata;
-class ModelTypeState;
-}
-
namespace autofill {
class AutofillChange;
class AutofillEntry;
class AutofillProfile;
+class AutofillTableEncryptor;
class AutofillTableTest;
class CreditCard;
@@ -550,6 +547,8 @@ class AutofillTable : public WebDatabaseTable {
bool InitAutofillSyncMetadataTable();
bool InitModelTypeStateTable();
+ std::unique_ptr<AutofillTableEncryptor> autofill_table_encryptor_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillTable);
};
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor.h b/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor.h
new file mode 100644
index 00000000000..2391cd722a2
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor.h
@@ -0,0 +1,26 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_TABLE_ENCRYPTOR_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_TABLE_ENCRYPTOR_H_
+
+#include <string>
+
+#include "base/strings/string16.h"
+
+namespace autofill {
+// Encryptor used by Autofill table.
+class AutofillTableEncryptor {
+ public:
+ virtual ~AutofillTableEncryptor() = default;
+
+ virtual bool EncryptString16(const base::string16& plaintext,
+ std::string* ciphertext) const = 0;
+ virtual bool DecryptString16(const std::string& ciphertext,
+ base::string16* plaintext) const = 0;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_TABLE_ENCRYPTOR_H_
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.cc b/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.cc
new file mode 100644
index 00000000000..6ee6516d154
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/autofill_table_encryptor_factory.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/memory/singleton.h"
+#include "components/autofill/core/browser/webdata/system_encryptor.h"
+
+namespace autofill {
+
+AutofillTableEncryptorFactory::AutofillTableEncryptorFactory() = default;
+
+AutofillTableEncryptorFactory::~AutofillTableEncryptorFactory() = default;
+
+AutofillTableEncryptorFactory* AutofillTableEncryptorFactory::GetInstance() {
+ return base::Singleton<AutofillTableEncryptorFactory>::get();
+}
+
+std::unique_ptr<AutofillTableEncryptor>
+AutofillTableEncryptorFactory::Create() {
+ DCHECK(sequence_checker_.CalledOnValidSequence());
+ return delegate_ ? delegate_->Create() : base::MakeUnique<SystemEncryptor>();
+}
+
+void AutofillTableEncryptorFactory::SetDelegate(
+ std::unique_ptr<Delegate> delegate) {
+ DCHECK(sequence_checker_.CalledOnValidSequence());
+ delegate_ = std::move(delegate);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.h b/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.h
new file mode 100644
index 00000000000..aa0d52de601
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_encryptor_factory.h
@@ -0,0 +1,53 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_TABLE_ENCRYPTOR_FACTORY_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_TABLE_ENCRYPTOR_FACTORY_H_
+
+#include <memory>
+
+#include "base/sequence_checker.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+} // namespace base
+
+namespace autofill {
+
+class AutofillTableEncryptor;
+
+// Factory for creating Autofill table encryptor.
+// If |delegate_| is set, then |delegate_| is used to create encryptor,
+// else default encrytor (SystemEncryptor) is returned.
+class AutofillTableEncryptorFactory {
+ public:
+ // Embedders are recommended to use this delegate to inject
+ // their encryptor into Autofill table.
+ class Delegate {
+ public:
+ virtual ~Delegate() = default;
+
+ virtual std::unique_ptr<AutofillTableEncryptor> Create() = 0;
+ };
+
+ static AutofillTableEncryptorFactory* GetInstance();
+
+ std::unique_ptr<AutofillTableEncryptor> Create();
+
+ void SetDelegate(std::unique_ptr<Delegate> delegate);
+
+ private:
+ AutofillTableEncryptorFactory();
+ ~AutofillTableEncryptorFactory();
+
+ std::unique_ptr<Delegate> delegate_;
+ base::SequenceChecker sequence_checker_;
+
+ friend struct base::DefaultSingletonTraits<AutofillTableEncryptorFactory>;
+ DISALLOW_COPY_AND_ASSIGN(AutofillTableEncryptorFactory);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_TABLE_ENCRYPTOR_FACTORY_H_
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 e8da2b12843..235dd06230b 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -2,14 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <stddef.h>
+#include "components/autofill/core/browser/webdata/autofill_table.h"
#include <map>
#include <set>
-#include <string>
#include <tuple>
#include <utility>
-#include <vector>
#include "base/command_line.h"
#include "base/files/file_util.h"
@@ -29,7 +27,6 @@
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
-#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
@@ -44,6 +41,10 @@
using base::ASCIIToUTF16;
using base::Time;
using base::TimeDelta;
+using sync_pb::EntityMetadata;
+using sync_pb::ModelTypeState;
+using syncer::EntityMetadataMap;
+using syncer::MetadataBatch;
namespace autofill {
@@ -85,8 +86,8 @@ bool CompareAutofillEntries(const AutofillEntry& a, const AutofillEntry& b) {
b.date_created(), b.date_last_used());
}
-AutofillEntry MakeAutofillEntry(const char* name,
- const char* value,
+AutofillEntry MakeAutofillEntry(const std::string& name,
+ const std::string& value,
time_t date_created,
time_t date_last_used) {
if (date_last_used < 0)
@@ -463,6 +464,31 @@ TEST_F(AutofillTableTest, Autofill_UpdateTwo) {
db_.get()));
}
+TEST_F(AutofillTableTest, Autofill_UpdateNullTerminated) {
+ const char kName[] = "foo";
+ const char kValue[] = "bar";
+ // A value which contains terminating character.
+ std::string value(kValue, arraysize(kValue));
+
+ AutofillEntry entry0(MakeAutofillEntry(kName, kValue, 1, -1));
+ AutofillEntry entry1(MakeAutofillEntry(kName, value, 2, 3));
+ std::vector<AutofillEntry> entries;
+ entries.push_back(entry0);
+ entries.push_back(entry1);
+ ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
+
+ EXPECT_EQ(1, GetAutofillEntryCount(ASCIIToUTF16(kName), ASCIIToUTF16(kValue),
+ db_.get()));
+ EXPECT_EQ(2, GetAutofillEntryCount(ASCIIToUTF16(kName), ASCIIToUTF16(value),
+ db_.get()));
+
+ std::vector<AutofillEntry> all_entries;
+ ASSERT_TRUE(table_->GetAllAutofillEntries(&all_entries));
+ ASSERT_EQ(2U, all_entries.size());
+ EXPECT_EQ(entry0, all_entries[0]);
+ EXPECT_EQ(entry1, all_entries[1]);
+}
+
TEST_F(AutofillTableTest, Autofill_UpdateReplace) {
AutofillChangeList changes;
// Add a form field. This will be replaced.
@@ -1823,8 +1849,8 @@ TEST_F(AutofillTableTest, SetServerProfileUpdateUsageStats) {
table_->GetServerProfiles(&outputs);
ASSERT_EQ(1u, outputs.size());
EXPECT_EQ(one.server_id(), outputs[0]->server_id());
- EXPECT_EQ(0U, outputs[0]->use_count());
- EXPECT_EQ(base::Time(), outputs[0]->use_date());
+ EXPECT_EQ(1U, outputs[0]->use_count());
+ EXPECT_NE(base::Time(), outputs[0]->use_date());
// We don't track modification date for server profiles. It should always be
// base::Time().
EXPECT_EQ(base::Time(), outputs[0]->modification_date());
@@ -1851,18 +1877,6 @@ TEST_F(AutofillTableTest, SetServerProfileUpdateUsageStats) {
EXPECT_NE(base::Time(), outputs[0]->use_date());
EXPECT_EQ(base::Time(), outputs[0]->modification_date());
outputs.clear();
-
- // Set a null profile list --- this should clear metadata.
- table_->SetServerProfiles(std::vector<AutofillProfile>());
- // Reset the old profile list and see the metadata is reset.
- table_->SetServerProfiles(inputs);
- table_->GetServerProfiles(&outputs);
- ASSERT_EQ(1u, outputs.size());
- EXPECT_EQ(one.server_id(), outputs[0]->server_id());
- EXPECT_EQ(0U, outputs[0]->use_count());
- EXPECT_EQ(base::Time(), outputs[0]->use_date());
- EXPECT_EQ(base::Time(), outputs[0]->modification_date());
- outputs.clear();
}
// Tests that deleting time ranges re-masks server credit cards that were
@@ -1996,8 +2010,16 @@ TEST_F(AutofillTableTest, GetFormValuesForElementName_SubstringMatchEnabled) {
}
}
-TEST_F(AutofillTableTest, GetAllSyncMetadata) {
- sync_pb::EntityMetadata metadata;
+TEST_F(AutofillTableTest, AutofillNoMetadata) {
+ MetadataBatch metadata_batch;
+ EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+ EXPECT_EQ(0u, metadata_batch.TakeAllMetadata().size());
+ EXPECT_EQ(ModelTypeState().SerializeAsString(),
+ metadata_batch.GetModelTypeState().SerializeAsString());
+}
+
+TEST_F(AutofillTableTest, AutofillGetAllSyncMetadata) {
+ EntityMetadata metadata;
std::string storage_key = "storage_key";
std::string storage_key2 = "storage_key2";
metadata.set_sequence_number(1);
@@ -2005,7 +2027,7 @@ TEST_F(AutofillTableTest, GetAllSyncMetadata) {
EXPECT_TRUE(
table_->UpdateSyncMetadata(syncer::AUTOFILL, storage_key, metadata));
- sync_pb::ModelTypeState model_type_state;
+ ModelTypeState model_type_state;
model_type_state.set_initial_sync_done(true);
EXPECT_TRUE(table_->UpdateModelTypeState(syncer::AUTOFILL, model_type_state));
@@ -2014,12 +2036,12 @@ TEST_F(AutofillTableTest, GetAllSyncMetadata) {
EXPECT_TRUE(
table_->UpdateSyncMetadata(syncer::AUTOFILL, storage_key2, metadata));
- syncer::MetadataBatch metadata_batch;
+ MetadataBatch metadata_batch;
EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
EXPECT_TRUE(metadata_batch.GetModelTypeState().initial_sync_done());
- syncer::EntityMetadataMap metadata_records = metadata_batch.TakeAllMetadata();
+ EntityMetadataMap metadata_records = metadata_batch.TakeAllMetadata();
EXPECT_EQ(metadata_records.size(), 2u);
EXPECT_EQ(metadata_records[storage_key].sequence_number(), 1);
@@ -2033,11 +2055,11 @@ TEST_F(AutofillTableTest, GetAllSyncMetadata) {
EXPECT_FALSE(metadata_batch.GetModelTypeState().initial_sync_done());
}
-TEST_F(AutofillTableTest, WriteThenDeleteSyncMetadata) {
- sync_pb::EntityMetadata metadata;
- syncer::MetadataBatch metadata_batch;
+TEST_F(AutofillTableTest, AutofillWriteThenDeleteSyncMetadata) {
+ EntityMetadata metadata;
+ MetadataBatch metadata_batch;
std::string storage_key = "storage_key";
- sync_pb::ModelTypeState model_type_state;
+ ModelTypeState model_type_state;
model_type_state.set_initial_sync_done(true);
@@ -2052,32 +2074,35 @@ TEST_F(AutofillTableTest, WriteThenDeleteSyncMetadata) {
// It shouldn't be there any more.
EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
- syncer::EntityMetadataMap metadata_records = metadata_batch.TakeAllMetadata();
+ EntityMetadataMap metadata_records = metadata_batch.TakeAllMetadata();
EXPECT_EQ(metadata_records.size(), 0u);
// Now delete the model type state.
EXPECT_TRUE(table_->ClearModelTypeState(syncer::AUTOFILL));
- EXPECT_FALSE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+ EXPECT_TRUE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+ EXPECT_EQ(ModelTypeState().SerializeAsString(),
+ metadata_batch.GetModelTypeState().SerializeAsString());
}
-TEST_F(AutofillTableTest, CorruptSyncMetadata) {
- syncer::MetadataBatch metadata_batch;
- sync_pb::ModelTypeState state;
- std::string storage_key = "storage_key";
-
+TEST_F(AutofillTableTest, AutofillCorruptSyncMetadata) {
+ MetadataBatch metadata_batch;
sql::Statement s(db_->GetSQLConnection()->GetUniqueStatement(
"INSERT OR REPLACE INTO autofill_sync_metadata "
"(storage_key, value) VALUES(?, ?)"));
- s.BindString(0, storage_key);
+ s.BindString(0, "storage_key");
s.BindString(1, "unparseable");
+ EXPECT_TRUE(s.Run());
- sql::Statement s2(db_->GetSQLConnection()->GetUniqueStatement(
+ EXPECT_FALSE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
+}
+
+TEST_F(AutofillTableTest, AutofillCorruptModelTypeState) {
+ MetadataBatch metadata_batch;
+ sql::Statement s(db_->GetSQLConnection()->GetUniqueStatement(
"INSERT OR REPLACE INTO autofill_model_type_state "
"(rowid, value) VALUES(1, ?)"));
- s2.BindString(0, "unparseable");
-
+ s.BindString(0, "unparseable");
EXPECT_TRUE(s.Run());
- EXPECT_TRUE(s2.Run());
EXPECT_FALSE(table_->GetAllSyncMetadata(syncer::AUTOFILL, &metadata_batch));
}
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 326ddc4ee15..021b91abd50 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
@@ -33,6 +33,10 @@ namespace autofill {
namespace {
+// The length of the GUIDs used for local autofill data. It is different than
+// the length used for server autofill data.
+const int kLocalGuidSize = 36;
+
void* UserDataKey() {
// Use the address of a static so that COMDAT folding won't ever fold
// with something else.
@@ -163,20 +167,40 @@ void MergeCommonMetadata(
bool* is_local_modified) {
size_t remote_use_count =
base::checked_cast<size_t>(remote_metadata.use_count());
- if (local_model->use_count() < remote_use_count) {
- local_model->set_use_count(remote_use_count);
- *is_local_modified = true;
- } else if (local_model->use_count() > remote_use_count) {
- *is_remote_outdated = true;
- }
-
base::Time remote_use_date =
base::Time::FromInternalValue(remote_metadata.use_date());
- if (local_model->use_date() < remote_use_date) {
+
+ // If the two models have the same metadata, do nothing.
+ if (local_model->use_count() == remote_use_count &&
+ local_model->use_date() == remote_use_date) {
+ return;
+ }
+
+ // Special case for local models with a use_count of one. This means the local
+ // model was only created, never used. The remote model should always be
+ // preferred.
+ // This situation can happen for new Chromium instances where there is no data
+ // yet on disk, making the use_date artifically high. Once the metadata sync
+ // kicks in, we should use that value.
+ if (local_model->use_count() == 1) {
local_model->set_use_date(remote_use_date);
+ local_model->set_use_count(remote_use_count);
*is_local_modified = true;
- } else if (local_model->use_date() > remote_use_date) {
- *is_remote_outdated = true;
+ } else {
+ // Otherwise, just keep the most recent use date and biggest use count.
+ if (local_model->use_date() < remote_use_date) {
+ local_model->set_use_date(remote_use_date);
+ *is_local_modified = true;
+ } else if (local_model->use_date() > remote_use_date) {
+ *is_remote_outdated = true;
+ }
+
+ if (local_model->use_count() < remote_use_count) {
+ local_model->set_use_count(remote_use_count);
+ *is_local_modified = true;
+ } else if (local_model->use_count() > remote_use_count) {
+ *is_remote_outdated = true;
+ }
}
}
@@ -201,6 +225,20 @@ void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
is_local_modified);
}
+// Whether the |current_billing_address_id| is considered outdated compared to
+// the |proposed_billing_address_id|.
+bool IsBillingAddressOutdated(const std::string& current_billing_address_id,
+ const std::string& proposed_billing_address_id) {
+ DCHECK(current_billing_address_id != proposed_billing_address_id);
+
+ // If the current billing address is empty, or if the current one refers to a
+ // server address and the proposed one refers to a local address, the current
+ // billing address is considered outdated.
+ return current_billing_address_id.empty() ||
+ (current_billing_address_id.size() != kLocalGuidSize &&
+ proposed_billing_address_id.size() == kLocalGuidSize);
+}
+
// Merges the metadata of the remote and local versions of the credit card.
void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
CreditCard* local_card,
@@ -213,18 +251,21 @@ void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
&remote_billing_address_id);
if (local_card->billing_address_id() != remote_billing_address_id) {
- // If one of the values is empty, update it with the non empty value.
- if (local_card->billing_address_id().empty()) {
+ if (IsBillingAddressOutdated(local_card->billing_address_id(),
+ remote_billing_address_id)) {
local_card->set_billing_address_id(remote_billing_address_id);
*is_local_modified = true;
- } else if (remote_billing_address_id.empty()) {
+ } else if (IsBillingAddressOutdated(remote_billing_address_id,
+ local_card->billing_address_id())) {
*is_remote_outdated = true;
} else {
- // The cards have a different non-empty billing address id. Keep the
- // billing address id of the most recently used card.
+ // The cards have a different non-empty billing address id and both refer
+ // to the same type of address. Keep the billing address id of the most
+ // recently used card. If both have the same timestamp, the remote version
+ // should be kept in order to stabilize the values.
base::Time remote_use_date =
base::Time::FromInternalValue(remote_metadata.use_date());
- if (local_card->use_date() < remote_use_date) {
+ if (local_card->use_date() <= remote_use_date) {
local_card->set_billing_address_id(remote_billing_address_id);
*is_local_modified = true;
} else {
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
index 89439d7184c..b24fec6e158 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service_unittest.cc
@@ -59,6 +59,12 @@ const char kAddr2SyncTag[] = "address-YWRkcjLvv74=";
const char kCard1SyncTag[] = "card-Y2FyZDHvv74=";
const char kCard2SyncTag[] = "card-Y2FyZDLvv74=";
+// Local profile GUID in UTF8 and non-UTF8.
+const char kLocalAddr1[] = "e171e3ed-858a-4dd5-9bf3-8517f14ba5fc";
+const char kLocalAddr2[] = "fa232b9a-f248-4e5a-8d76-d46f821c0c5f";
+const char kLocalAddr1Utf8[] =
+ "ZTE3MWUzZWQtODU4YS00ZGQ1LTliZjMtODUxN2YxNGJhNWZj";
+
// Map values are owned by the caller to GetLocalData.
ACTION_P2(GetCopiesOf, profiles, cards) {
for (const auto& profile : *profiles) {
@@ -674,9 +680,9 @@ syncer::SyncChange BuildCardChange(
// server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreNewMetadataFromServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -698,9 +704,9 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// disk when processing on-going sync changes.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesFromServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -724,9 +730,9 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// processing on-going sync changes.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SendHigherValuesToServerOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -743,7 +749,7 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
SyncAddressChangeAndDataMatch(
syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2, true),
+ kAddr1Utf8, 2, 2, true),
SyncCardChangeAndDataMatch(
syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
sync_pb::WalletMetadataSpecifics::CARD,
@@ -755,9 +761,9 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// Verify that addition of known metadata is treated the same as an update.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
TreatAdditionOfKnownMetadataAsUpdateOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -774,7 +780,7 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
SyncAddressChangeAndDataMatch(
syncer::SyncChange::ACTION_UPDATE, kAddr1SyncTag,
sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2, true),
+ kAddr1Utf8, 2, 2, true),
SyncCardChangeAndDataMatch(
syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
sync_pb::WalletMetadataSpecifics::CARD,
@@ -787,9 +793,9 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// no disk writes and no messages sent to the server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreUpdateOfUnknownMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -811,9 +817,9 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// ignored. There should be no disk writes and no messages sent to the server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
IgnoreDeleteOfUnknownMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -835,9 +841,9 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// trigger an undelete message sent to the server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
UndeleteExistingMetadataOnSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -854,7 +860,7 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
SyncAddressChangeAndDataMatch(
syncer::SyncChange::ACTION_ADD, kAddr1SyncTag,
sync_pb::WalletMetadataSpecifics::ADDRESS,
- kAddr1Utf8, 1, 2, true),
+ kAddr1Utf8, 2, 2, true),
SyncCardChangeAndDataMatch(
syncer::SyncChange::ACTION_ADD, kCard1SyncTag,
sync_pb::WalletMetadataSpecifics::CARD,
@@ -867,11 +873,11 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// data, which is used to avoid calling the expensive GetAllSyncData() function.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
CacheIsUpToDateAfterSyncChange) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
local_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
local_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
local_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, true));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, true));
remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
remote_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr2));
@@ -903,7 +909,7 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// values to the sync server.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesLocallyOnLateDataArrival) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
MergeMetadata(&local_, &remote_);
syncer::SyncChangeList changes;
@@ -931,7 +937,7 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// once the data finally arrives.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
SaveHigherValuesLocallyOnLateDataArrivalAfterPartialUpdates) {
- remote_.UpdateAddressStats(BuildAddress(kAddr1, 1, 2, false));
+ remote_.UpdateAddressStats(BuildAddress(kAddr1, 2, 2, false));
remote_.UpdateAddressStats(BuildAddress(kAddr2, 3, 4, false));
remote_.UpdateCardStats(BuildCard(kCard1, 5, 6, kAddr1));
remote_.UpdateCardStats(BuildCard(kCard2, 7, 8, kAddr1));
@@ -974,7 +980,7 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
// Make sure that if the better data is split across the local and server
// version, both are updated with the merge results.
TEST_F(AutofillWalletMetadataSyncableServiceTest, SaveHigherValues_Mixed1) {
- local_.UpdateAddressStats(BuildAddress(kAddr1, 1, 20, true));
+ local_.UpdateAddressStats(BuildAddress(kAddr1, 2, 20, true));
local_.UpdateCardStats(BuildCard(kCard1, 30, 4, ""));
remote_.UpdateAddressStats(BuildAddress(kAddr1, 10, 2, false));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
@@ -1025,9 +1031,10 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest, SaveHigherValues_Mixed2) {
}
// Verify that if both local and server have a different non empty billing
-// address id, the one with the most recent (bigger) use date is kept.
+// address id refering to a Wallet address, the one with the most recent
+// (bigger) use date is kept.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValues_DifferentBillingAddressId_LocalMostRecent) {
+ DifferentServerBillingAddressId_LocalMostRecent) {
local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr1));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
@@ -1044,9 +1051,10 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
}
// Verify that if both local and server have a different non empty billing
-// address id, the one with the most recent (bigger) use date is kept.
+// address id refering to a Wallet address, the one with the most recent
+// (bigger) use date is kept.
TEST_F(AutofillWalletMetadataSyncableServiceTest,
- SaveHigherValues_DifferentBillingAddressId_RemoteMostRecent) {
+ DifferentServerBillingAddressId_RemoteMostRecent) {
local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kAddr2));
@@ -1059,5 +1067,169 @@ TEST_F(AutofillWalletMetadataSyncableServiceTest,
MergeMetadata(&local_, &remote_);
}
+// Verify that if both local and server have a different non empty billing
+// address id refering to a local profile, the one with the most recent (bigger)
+// use date is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ DifferentLocalBillingAddressId_LocalMostRecent) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 40, kLocalAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr2));
+
+ // The value from the local should be kept because it has a more recent use
+ // date.
+ EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local_, SendChangesToSyncServer(
+ UnorderedElementsAre(SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 40, kLocalAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id refering to a local profile, the one with the most recent (bigger)
+// use date is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ DifferentLocalBillingAddressId_RemoteMostRecent) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 40, kLocalAddr2));
+
+ // The value from the remote should be kept because it has a more recent use
+ // date.
+ EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+ kCard1, 3, 40, kLocalAddr2)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ DifferentBillingAddressId_KeepLocalId_Local) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+
+ // The billing address from the local version of the card should be kept since
+ // it refers to a local autofill profile.
+ EXPECT_CALL(local_, UpdateCardStats(_)).Times(0);
+ EXPECT_CALL(local_, SendChangesToSyncServer(
+ UnorderedElementsAre(SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 3, 4, kLocalAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept, even id the
+// other was used more recently.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ DifferentBillingAddressId_KeepLocalId_Remote) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+
+ // The billing address from the remote version of the card should be kept
+ // since it refers to a local autofill profile.
+ EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+ kCard1, 3, 4, kLocalAddr1)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept, even id the
+// other was used more recently. Also makes sure that for the rest of the fields
+// the highest values are kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ SaveHigherValues_DifferentBillingAddressId_KeepLocalId_Local) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr2));
+
+ // The billing address from the local version of the card should be kept since
+ // it refers to a local autofill profile. The highest use stats should
+ // be kept.
+ EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+ kCard1, 30, 40, kLocalAddr1)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(
+ UnorderedElementsAre(SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 30, 40, kLocalAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id, the one refering to a local profile is always kept. Also makes
+// sure that for the rest of the fields the highest values are kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ SaveHigherValues_DifferentBillingAddressId_KeepLocalId_Remote) {
+ local_.UpdateCardStats(BuildCard(kCard1, 30, 40, kAddr2));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+
+ // The billing address from the remote version of the card should be kept
+ // since it refers to a local autofill profile. The highest use stats should
+ // be kept.
+ EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+ kCard1, 30, 40, kLocalAddr1)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(
+ UnorderedElementsAre(SyncCardChangeAndDataMatch(
+ syncer::SyncChange::ACTION_UPDATE, kCard1SyncTag,
+ sync_pb::WalletMetadataSpecifics::CARD,
+ kCard1Utf8, 30, 40, kLocalAddr1Utf8))));
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id refering to a Wallet address with the same timestamp, the remote
+// one is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ DifferentServerBillingAddressId_BothSameTimestamp) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kAddr2));
+
+ // The value from the remote should be kept to promote a stable set of values.
+ EXPECT_CALL(local_, UpdateCardStats(
+ AutofillCardMetadataMatches(kCard1, 3, 4, kAddr2)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if both local and server have a different non empty billing
+// address id refering to a local profile with the same timestamp, the remote
+// one is kept.
+TEST_F(AutofillWalletMetadataSyncableServiceTest,
+ DifferentLocalBillingAddressId_BothSameTimestamp) {
+ local_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr2));
+
+ // The value from the remote should be kept to promote a stable set of values.
+ EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+ kCard1, 3, 4, kLocalAddr2)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local_, &remote_);
+}
+
+// Verify that if the local card has a use_count of one, its use_date is
+// replaced even if it is more recent (new cards are created with a use_date set
+// to the current time).
+TEST_F(AutofillWalletMetadataSyncableServiceTest, NewLocalCard) {
+ local_.UpdateCardStats(BuildCard(kCard1, 1, 5000, kLocalAddr1));
+ remote_.UpdateCardStats(BuildCard(kCard1, 3, 4, kLocalAddr1));
+
+ EXPECT_CALL(local_, UpdateCardStats(AutofillCardMetadataMatches(
+ kCard1, 3, 4, kLocalAddr1)));
+ EXPECT_CALL(local_, SendChangesToSyncServer(_)).Times(0);
+
+ MergeMetadata(&local_, &remote_);
+}
+
} // namespace
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index 8ad43337b41..b43f4fc3ed7 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
@@ -291,7 +291,7 @@ void AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
}
// static
-void AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
+void AutofillWalletSyncableService::CopyRelevantMetadataFromDisk(
const AutofillTable& table,
std::vector<CreditCard>* cards_from_server) {
std::vector<std::unique_ptr<CreditCard>> cards_on_disk;
@@ -301,6 +301,11 @@ void AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
for (const auto& saved_card : cards_on_disk) {
for (CreditCard& server_card : *cards_from_server) {
if (saved_card->server_id() == server_card.server_id()) {
+ // The wallet data doesn't have the use stats. Use the ones present on
+ // disk to not overwrite them with bad data.
+ server_card.set_use_count(saved_card->use_count());
+ server_card.set_use_date(saved_card->use_date());
+
// Keep the billing address id of the saved cards only if it points to
// a local address.
if (saved_card->billing_address_id().length() == kLocalGuidSize) {
@@ -320,11 +325,11 @@ syncer::SyncMergeResult AutofillWalletSyncableService::SetSyncData(
// Users can set billing address of the server credit card locally, but that
// information does not propagate to either Chrome Sync or Google Payments
- // server. To preserve user's preferred billing address, copy the billing
- // addresses from disk into |wallet_cards|.
+ // server. To preserve user's preferred billing address and most recent use
+ // stats, copy them from disk into |wallet_cards|.
AutofillTable* table =
AutofillTable::FromWebDatabase(webdata_backend_->GetDatabase());
- CopyRelevantBillingAddressesFromDisk(*table, &wallet_cards);
+ CopyRelevantMetadataFromDisk(*table, &wallet_cards);
// In the common case, the database won't have changed. Committing an update
// to the database will require at least one DB page write and will schedule
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 03f13116409..ae8bae82f66 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
@@ -61,15 +61,17 @@ class AutofillWalletSyncableService
const std::string& app_locale);
private:
+ FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
+ CopyRelevantMetadataFromDisk_KeepLocalAddresses);
FRIEND_TEST_ALL_PREFIXES(
AutofillWalletSyncableServiceTest,
- CopyRelevantBillingAddressesFromDisk_KeepLocalAddresses);
- FRIEND_TEST_ALL_PREFIXES(
- AutofillWalletSyncableServiceTest,
- CopyRelevantBillingAddressesFromDisk_OverwriteOtherAddresses);
+ CopyRelevantMetadataFromDisk_OverwriteOtherAddresses);
FRIEND_TEST_ALL_PREFIXES(
AutofillWalletSyncableServiceTest,
PopulateWalletCardsAndAddresses_BillingAddressIdTransfer);
+ FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest,
+ CopyRelevantMetadataFromDisk_KeepUseStats);
+ FRIEND_TEST_ALL_PREFIXES(AutofillWalletSyncableServiceTest, NewWalletCard);
syncer::SyncMergeResult SetSyncData(const syncer::SyncDataList& data_list);
@@ -81,10 +83,10 @@ class AutofillWalletSyncableService
std::vector<AutofillProfile>* wallet_addresses);
// Finds the copies of the same credit card from the server and on disk and
- // overwrites the server version with the billing id saved on disk if it
- // refers to a local autofill profile. The credit card's IDs do not change
- // over time.
- static void CopyRelevantBillingAddressesFromDisk(
+ // overwrites the server version with the use stats saved on disk, and the
+ // billing id if it refers to a local autofill profile. The credit card's IDs
+ // do not change over time.
+ static void CopyRelevantMetadataFromDisk(
const AutofillTable& table,
std::vector<CreditCard>* cards_from_server);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
index 9561a8b1c9b..41e33728dee 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_syncable_service_unittest.cc
@@ -9,6 +9,7 @@
#include "base/memory/ptr_util.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/sync/protocol/autofill_specifics.pb.h"
#include "components/sync/protocol/sync.pb.h"
@@ -99,7 +100,7 @@ TEST(AutofillWalletSyncableServiceTest,
// Verify that the billing address id from the card saved on disk is kept if it
// is a local profile guid.
TEST(AutofillWalletSyncableServiceTest,
- CopyRelevantBillingAddressesFromDisk_KeepLocalAddresses) {
+ CopyRelevantMetadataFromDisk_KeepLocalAddresses) {
std::vector<CreditCard> cards_on_disk;
std::vector<CreditCard> wallet_cards;
@@ -119,8 +120,8 @@ TEST(AutofillWalletSyncableServiceTest,
// Setup the TestAutofillTable with the cards_on_disk.
TestAutofillTable table(cards_on_disk);
- AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
- table, &wallet_cards);
+ AutofillWalletSyncableService::CopyRelevantMetadataFromDisk(table,
+ &wallet_cards);
ASSERT_EQ(1U, wallet_cards.size());
@@ -133,7 +134,7 @@ TEST(AutofillWalletSyncableServiceTest,
// Verify that the billing address id from the card saved on disk is overwritten
// if it does not refer to a local profile.
TEST(AutofillWalletSyncableServiceTest,
- CopyRelevantBillingAddressesFromDisk_OverwriteOtherAddresses) {
+ CopyRelevantMetadataFromDisk_OverwriteOtherAddresses) {
std::string old_billing_id = "1234";
std::string new_billing_id = "9876";
std::vector<CreditCard> cards_on_disk;
@@ -152,8 +153,8 @@ TEST(AutofillWalletSyncableServiceTest,
// Setup the TestAutofillTable with the cards_on_disk.
TestAutofillTable table(cards_on_disk);
- AutofillWalletSyncableService::CopyRelevantBillingAddressesFromDisk(
- table, &wallet_cards);
+ AutofillWalletSyncableService::CopyRelevantMetadataFromDisk(table,
+ &wallet_cards);
ASSERT_EQ(1U, wallet_cards.size());
@@ -162,4 +163,63 @@ TEST(AutofillWalletSyncableServiceTest,
EXPECT_EQ(new_billing_id, wallet_cards.back().billing_address_id());
}
+// Verify that the use stats on disk are kept when server cards are synced.
+TEST(AutofillWalletSyncableServiceTest,
+ CopyRelevantMetadataFromDisk_KeepUseStats) {
+ TestAutofillClock test_clock;
+ base::Time arbitrary_time = base::Time::FromDoubleT(25);
+ base::Time disk_time = base::Time::FromDoubleT(10);
+ test_clock.SetNow(arbitrary_time);
+
+ std::vector<CreditCard> cards_on_disk;
+ std::vector<CreditCard> wallet_cards;
+
+ // Create a card on disk with specific use stats.
+ cards_on_disk.push_back(CreditCard());
+ cards_on_disk.back().set_use_count(3U);
+ cards_on_disk.back().set_use_date(disk_time);
+
+ // Create a card pulled from wallet with the same id, but a different billing
+ // address id.
+ wallet_cards.push_back(CreditCard());
+ wallet_cards.back().set_use_count(10U);
+
+ // Setup the TestAutofillTable with the cards_on_disk.
+ TestAutofillTable table(cards_on_disk);
+
+ AutofillWalletSyncableService::CopyRelevantMetadataFromDisk(table,
+ &wallet_cards);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // Make sure the use stats from disk were kept
+ EXPECT_EQ(3U, wallet_cards.back().use_count());
+ EXPECT_EQ(disk_time, wallet_cards.back().use_date());
+}
+
+// Verify that the use stats of a new Wallet card are as expected.
+TEST(AutofillWalletSyncableServiceTest, NewWalletCard) {
+ TestAutofillClock test_clock;
+ base::Time arbitrary_time = base::Time::FromDoubleT(25);
+ test_clock.SetNow(arbitrary_time);
+
+ std::vector<AutofillProfile> wallet_addresses;
+ std::vector<CreditCard> wallet_cards;
+ syncer::SyncDataList data_list;
+
+ // Create a Sync data for a card and its billing address.
+ data_list.push_back(CreateSyncDataForWalletAddress("1" /* id */));
+ data_list.push_back(CreateSyncDataForWalletCreditCard(
+ "card1" /* id */, "1" /* billing_address_id */));
+
+ AutofillWalletSyncableService::PopulateWalletCardsAndAddresses(
+ data_list, &wallet_cards, &wallet_addresses);
+
+ ASSERT_EQ(1U, wallet_cards.size());
+
+ // The use_count should be 1 and the use_date should be the current time.
+ EXPECT_EQ(1U, wallet_cards.back().use_count());
+ EXPECT_EQ(arbitrary_time, wallet_cards.back().use_date());
+}
+
} // namespace autofill \ No newline at end of file
diff --git a/chromium/components/autofill/core/browser/webdata/system_encryptor.cc b/chromium/components/autofill/core/browser/webdata/system_encryptor.cc
new file mode 100644
index 00000000000..7b16c089529
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/system_encryptor.cc
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/system_encryptor.h"
+
+#include "components/os_crypt/os_crypt.h"
+
+namespace autofill {
+
+bool SystemEncryptor::EncryptString16(const base::string16& plaintext,
+ std::string* ciphertext) const {
+ return ::OSCrypt::EncryptString16(plaintext, ciphertext);
+}
+
+bool SystemEncryptor::DecryptString16(const std::string& ciphertext,
+ base::string16* plaintext) const {
+ return ::OSCrypt::DecryptString16(ciphertext, plaintext);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/system_encryptor.h b/chromium/components/autofill/core/browser/webdata/system_encryptor.h
new file mode 100644
index 00000000000..e6efb426c63
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/system_encryptor.h
@@ -0,0 +1,30 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_SYSTEM_ENCRYPTOR_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_SYSTEM_ENCRYPTOR_H_
+
+#include "base/macros.h"
+#include "components/autofill/core/browser/webdata/autofill_table_encryptor.h"
+
+namespace autofill {
+// Default encryptor used in Autofill table.
+class SystemEncryptor : public AutofillTableEncryptor {
+ public:
+ SystemEncryptor() = default;
+ ~SystemEncryptor() override = default;
+
+ bool EncryptString16(const base::string16& plaintext,
+ std::string* ciphertext) const override;
+
+ bool DecryptString16(const std::string& ciphertext,
+ base::string16* plaintext) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SystemEncryptor);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_SYSTEM_ENCRYPTOR_H_
diff --git a/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc b/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc
new file mode 100644
index 00000000000..aa2eb36397d
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.cc
@@ -0,0 +1,36 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/webdata/web_data_model_type_controller.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+
+using syncer::ModelType;
+using syncer::ModelTypeController;
+using syncer::SyncClient;
+
+namespace autofill {
+
+WebDataModelTypeController::WebDataModelTypeController(
+ ModelType type,
+ SyncClient* sync_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& model_thread,
+ const scoped_refptr<AutofillWebDataService>& web_data_service,
+ const BridgeFromWebData& bridge_from_web_data)
+ : ModelTypeController(type, sync_client, model_thread),
+ web_data_service_(web_data_service),
+ bridge_from_web_data_(bridge_from_web_data) {}
+
+WebDataModelTypeController::~WebDataModelTypeController() {}
+
+ModelTypeController::BridgeProvider
+WebDataModelTypeController::GetBridgeProvider() {
+ // As opposed to the default implementation, get the bridge on demand, the web
+ // data service requires us to be on the model thread.
+ return base::Bind(bridge_from_web_data_,
+ base::RetainedRef(web_data_service_));
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h b/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h
new file mode 100644
index 00000000000..b071d28c556
--- /dev/null
+++ b/chromium/components/autofill/core/browser/webdata/web_data_model_type_controller.h
@@ -0,0 +1,49 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_WEB_DATA_MODEL_TYPE_CONTROLLER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_WEB_DATA_MODEL_TYPE_CONTROLLER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/sync/driver/model_type_controller.h"
+
+namespace syncer {
+class ModelTypeSyncBridge;
+} // namespace syncer
+
+namespace autofill {
+
+class WebDataModelTypeController : public syncer::ModelTypeController {
+ public:
+ using BridgeFromWebData =
+ base::Callback<base::WeakPtr<syncer::ModelTypeSyncBridge>(
+ AutofillWebDataService*)>;
+
+ WebDataModelTypeController(
+ syncer::ModelType type,
+ syncer::SyncClient* sync_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& model_thread,
+ const scoped_refptr<AutofillWebDataService>& web_data_service,
+ const BridgeFromWebData& bridge_from_web_data);
+
+ ~WebDataModelTypeController() override;
+
+ private:
+ // syncer::ModelTypeController implementation.
+ syncer::ModelTypeController::BridgeProvider GetBridgeProvider() override;
+
+ // A reference to the AutofillWebDataService for this controller.
+ scoped_refptr<AutofillWebDataService> web_data_service_;
+
+ // How to grab the correct bridge from a web data.
+ BridgeFromWebData bridge_from_web_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebDataModelTypeController);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_WEB_DATA_MODEL_TYPE_CONTROLLER_H_
diff --git a/chromium/components/autofill/core/common/BUILD.gn b/chromium/components/autofill/core/common/BUILD.gn
index d01d18e3b28..f7a34bb28b6 100644
--- a/chromium/components/autofill/core/common/BUILD.gn
+++ b/chromium/components/autofill/core/common/BUILD.gn
@@ -4,6 +4,8 @@
static_library("common") {
sources = [
+ "autofill_clock.cc",
+ "autofill_clock.h",
"autofill_constants.cc",
"autofill_constants.h",
"autofill_data_validation.cc",
diff --git a/chromium/components/autofill/core/common/autofill_clock.cc b/chromium/components/autofill/core/common/autofill_clock.cc
new file mode 100644
index 00000000000..8702403d9e5
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_clock.cc
@@ -0,0 +1,43 @@
+// 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/common/autofill_clock.h"
+
+#include <utility>
+
+#include "base/time/clock.h"
+#include "base/time/default_clock.h"
+
+namespace autofill {
+
+namespace {
+
+static base::LazyInstance<AutofillClock> g_autofill_clock =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+// static
+base::Time AutofillClock::Now() {
+ if (!g_autofill_clock.Get().clock_)
+ SetClock();
+
+ return g_autofill_clock.Get().clock_->Now();
+}
+
+AutofillClock::AutofillClock(){};
+AutofillClock::~AutofillClock(){};
+
+// static
+void AutofillClock::SetClock() {
+ g_autofill_clock.Get().clock_.reset(new base::DefaultClock());
+}
+
+// static
+void AutofillClock::SetTestClock(std::unique_ptr<base::Clock> clock) {
+ DCHECK(clock);
+ g_autofill_clock.Get().clock_ = std::move(clock);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/common/autofill_clock.h b/chromium/components/autofill/core/common/autofill_clock.h
new file mode 100644
index 00000000000..45a991211ba
--- /dev/null
+++ b/chromium/components/autofill/core/common/autofill_clock.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CLOCK_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CLOCK_H_
+
+#include <memory>
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+
+namespace base {
+class Clock;
+class Time;
+} // namespace base
+
+namespace autofill {
+
+// Handles getting the current time for the Autofill feature. Can be injected
+// with a customizable clock to facilitate testing.
+class AutofillClock {
+ public:
+ // Returns the current time based on |clock_|.
+ static base::Time Now();
+
+ private:
+ friend class TestAutofillClock;
+ friend struct base::DefaultLazyInstanceTraits<AutofillClock>;
+
+ // Resets a normal clock.
+ static void SetClock();
+
+ // Sets the clock to be used for tests.
+ static void SetTestClock(std::unique_ptr<base::Clock> clock);
+
+ AutofillClock();
+ ~AutofillClock();
+
+ // The clock used to return the current time.
+ std::unique_ptr<base::Clock> clock_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillClock);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CLOCK_H_
diff --git a/chromium/components/autofill/core/common/autofill_switches.cc b/chromium/components/autofill/core/common/autofill_switches.cc
index 8aadec54c62..217408a99d8 100644
--- a/chromium/components/autofill/core/common/autofill_switches.cc
+++ b/chromium/components/autofill/core/common/autofill_switches.cc
@@ -56,6 +56,9 @@ const char kLocalHeuristicsOnlyForPasswordGeneration[] =
// Annotates forms with Autofill field type predictions.
const char kShowAutofillTypePredictions[] = "show-autofill-type-predictions";
+// Annotates forms and fields with Autofill signatures.
+const char kShowAutofillSignatures[] = "show-autofill-signatures";
+
// Use the sandbox Online Wallet service URL (for developer testing).
const char kWalletServiceUseSandbox[] = "wallet-service-use-sandbox";
diff --git a/chromium/components/autofill/core/common/autofill_switches.h b/chromium/components/autofill/core/common/autofill_switches.h
index e423cca352b..b1c7d909c2b 100644
--- a/chromium/components/autofill/core/common/autofill_switches.h
+++ b/chromium/components/autofill/core/common/autofill_switches.h
@@ -24,6 +24,7 @@ extern const char kEnableSuggestionsWithSubstringMatch[];
extern const char kIgnoreAutocompleteOffForAutofill[];
extern const char kLocalHeuristicsOnlyForPasswordGeneration[];
extern const char kShowAutofillTypePredictions[];
+extern const char kShowAutofillSignatures[];
extern const char kWalletServiceUseSandbox[];
#if defined(OS_ANDROID)
diff --git a/chromium/components/autofill/core/common/autofill_util.cc b/chromium/components/autofill/core/common/autofill_util.cc
index bc458a9609c..c20ac562e43 100644
--- a/chromium/components/autofill/core/common/autofill_util.cc
+++ b/chromium/components/autofill/core/common/autofill_util.cc
@@ -42,6 +42,11 @@ bool IsFeatureSubstringMatchEnabled() {
switches::kEnableSuggestionsWithSubstringMatch);
}
+bool IsShowAutofillSignaturesEnabled() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kShowAutofillSignatures);
+}
+
bool IsKeyboardAccessoryEnabled() {
#if defined(OS_ANDROID)
return base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/chromium/components/autofill/core/common/autofill_util.h b/chromium/components/autofill/core/common/autofill_util.h
index fccd473af20..a9738774580 100644
--- a/chromium/components/autofill/core/common/autofill_util.h
+++ b/chromium/components/autofill/core/common/autofill_util.h
@@ -19,6 +19,9 @@ namespace autofill {
// is on.
bool IsFeatureSubstringMatchEnabled();
+// Returns true if showing autofill signature as HTML attributes is enabled.
+bool IsShowAutofillSignaturesEnabled();
+
// Returns true when keyboard accessory is enabled.
bool IsKeyboardAccessoryEnabled();
diff --git a/chromium/components/autofill/core/common/form_field_data.cc b/chromium/components/autofill/core/common/form_field_data.cc
index 6e19116ad9a..48796627fa9 100644
--- a/chromium/components/autofill/core/common/form_field_data.cc
+++ b/chromium/components/autofill/core/common/form_field_data.cc
@@ -15,7 +15,7 @@ namespace {
// Increment this anytime pickle format is modified as well as provide
// deserialization routine from previous kPickleVersion format.
-const int kPickleVersion = 6;
+const int kPickleVersion = 7;
void AddVectorToPickle(std::vector<base::string16> strings,
base::Pickle* pickle) {
@@ -114,6 +114,11 @@ bool DeserializeSection9(base::PickleIterator* iter,
return iter->ReadUInt32(&field_data->properties_mask);
}
+bool DeserializeSection10(base::PickleIterator* iter,
+ FormFieldData* field_data) {
+ return iter->ReadString16(&field_data->id);
+}
+
} // namespace
FormFieldData::FormFieldData()
@@ -134,7 +139,7 @@ FormFieldData::~FormFieldData() {
bool FormFieldData::SameFieldAs(const FormFieldData& field) const {
// A FormFieldData stores a value, but the value is not part of the identity
// of the field, so we don't want to compare the values.
- return label == field.label && name == field.name &&
+ return label == field.label && name == field.name && id == field.id &&
form_control_type == field.form_control_type &&
autocomplete_attribute == field.autocomplete_attribute &&
placeholder == field.placeholder && max_length == field.max_length &&
@@ -177,6 +182,8 @@ bool FormFieldData::operator<(const FormFieldData& field) const {
if (label > field.label) return false;
if (name < field.name) return true;
if (name > field.name) return false;
+ if (id < field.id) return true;
+ if (id > field.id) return false;
if (form_control_type < field.form_control_type) return true;
if (form_control_type > field.form_control_type) return false;
if (autocomplete_attribute < field.autocomplete_attribute) return true;
@@ -222,6 +229,7 @@ void SerializeFormFieldData(const FormFieldData& field_data,
pickle->WriteString16(field_data.placeholder);
pickle->WriteString16(field_data.css_classes);
pickle->WriteUInt32(field_data.properties_mask);
+ pickle->WriteString16(field_data.id);
}
bool DeserializeFormFieldData(base::PickleIterator* iter,
@@ -306,6 +314,21 @@ bool DeserializeFormFieldData(base::PickleIterator* iter,
}
break;
}
+ case 7: {
+ if (!DeserializeSection1(iter, &temp_form_field_data) ||
+ !DeserializeSection6(iter, &temp_form_field_data) ||
+ !DeserializeSection7(iter, &temp_form_field_data) ||
+ !DeserializeSection2(iter, &temp_form_field_data) ||
+ !DeserializeSection3(iter, &temp_form_field_data) ||
+ !DeserializeSection4(iter, &temp_form_field_data) ||
+ !DeserializeSection8(iter, &temp_form_field_data) ||
+ !DeserializeSection9(iter, &temp_form_field_data) ||
+ !DeserializeSection10(iter, &temp_form_field_data)) {
+ LOG(ERROR) << "Could not deserialize FormFieldData from pickle";
+ return false;
+ }
+ break;
+ }
default: {
LOG(ERROR) << "Unknown FormFieldData pickle version " << version;
return false;
@@ -341,6 +364,7 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field) {
return os << base::UTF16ToUTF8(field.label) << " "
<< base::UTF16ToUTF8(field.name) << " "
+ << base::UTF16ToUTF8(field.id) << " "
<< base::UTF16ToUTF8(field.value) << " " << field.form_control_type
<< " " << field.autocomplete_attribute << " " << field.placeholder
<< " " << field.max_length << " " << field.css_classes << " "
diff --git a/chromium/components/autofill/core/common/form_field_data.h b/chromium/components/autofill/core/common/form_field_data.h
index dbcb3ea445e..a4de0a2236c 100644
--- a/chromium/components/autofill/core/common/form_field_data.h
+++ b/chromium/components/autofill/core/common/form_field_data.h
@@ -69,6 +69,7 @@ struct FormFieldData {
// serializing functions (in the .cc file) and the constructor.
base::string16 label;
base::string16 name;
+ base::string16 id;
base::string16 value;
std::string form_control_type;
std::string autocomplete_attribute;
@@ -118,6 +119,7 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field);
EXPECT_EQ(expected.is_autofilled, actual.is_autofilled); \
EXPECT_EQ(expected.check_status, actual.check_status); \
EXPECT_EQ(expected.properties_mask, actual.properties_mask); \
+ EXPECT_EQ(expected.id, actual.id); \
} while (0)
} // namespace autofill
diff --git a/chromium/components/autofill/core/common/form_field_data_unittest.cc b/chromium/components/autofill/core/common/form_field_data_unittest.cc
index cae49ecb4df..0c94126a202 100644
--- a/chromium/components/autofill/core/common/form_field_data_unittest.cc
+++ b/chromium/components/autofill/core/common/form_field_data_unittest.cc
@@ -49,6 +49,10 @@ void FillVersion6Fields(FormFieldData* data) {
FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::HAD_FOCUS;
}
+void FillVersion7Fields(FormFieldData* data) {
+ data->id = base::ASCIIToUTF16("id");
+}
+
void WriteSection1(const FormFieldData& data, base::Pickle* pickle) {
pickle->WriteString16(data.label);
pickle->WriteString16(data.name);
@@ -99,6 +103,10 @@ void WriteVersion6Specific(const FormFieldData& data, base::Pickle* pickle) {
pickle->WriteUInt32(data.properties_mask);
}
+void WriteVersion7Specific(const FormFieldData& data, base::Pickle* pickle) {
+ pickle->WriteString16(data.id);
+}
+
void SerializeInVersion1Format(const FormFieldData& data,
base::Pickle* pickle) {
WriteSection1(data, pickle);
@@ -159,6 +167,19 @@ void SerializeInVersion6Format(const FormFieldData& data,
WriteVersion6Specific(data, pickle);
}
+void SerializeInVersion7Format(const FormFieldData& data,
+ base::Pickle* pickle) {
+ WriteSection1(data, pickle);
+ WriteSection4(data, pickle);
+ WriteSection5(data, pickle);
+ WriteVersion2Specific(data, pickle);
+ WriteSection2(data, pickle);
+ WriteVersion3Specific(data, pickle);
+ WriteVersion5Specific(data, pickle);
+ WriteVersion6Specific(data, pickle);
+ WriteVersion7Specific(data, pickle);
+}
+
} // namespace
TEST(FormFieldDataTest, SerializeAndDeserialize) {
@@ -168,6 +189,7 @@ TEST(FormFieldDataTest, SerializeAndDeserialize) {
FillVersion3Fields(&data);
FillVersion5Fields(&data);
FillVersion6Fields(&data);
+ FillVersion7Fields(&data);
base::Pickle pickle;
SerializeFormFieldData(data, &pickle);
@@ -281,6 +303,26 @@ TEST(FormFieldDataTest, DeserializeVersion6) {
EXPECT_TRUE(actual.SameFieldAs(data));
}
+TEST(FormFieldDataTest, DeserializeVersion7) {
+ FormFieldData data;
+ FillCommonFields(&data);
+ FillVersion2Fields(&data);
+ FillVersion3Fields(&data);
+ FillVersion5Fields(&data);
+ FillVersion6Fields(&data);
+ FillVersion7Fields(&data);
+
+ base::Pickle pickle;
+ pickle.WriteInt(7);
+ SerializeInVersion7Format(data, &pickle);
+
+ base::PickleIterator iter(pickle);
+ FormFieldData actual;
+ EXPECT_TRUE(DeserializeFormFieldData(&iter, &actual));
+
+ EXPECT_TRUE(actual.SameFieldAs(data));
+}
+
// Verify that if the data isn't valid, the FormFieldData isn't populated
// during deserialization.
TEST(FormFieldDataTest, DeserializeBadData) {
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 93d1bc6c500..5fc676c20e9 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger.cc
@@ -18,7 +18,6 @@
using base::checked_cast;
using base::Value;
using base::DictionaryValue;
-using base::FundamentalValue;
using base::StringValue;
namespace autofill {
@@ -101,13 +100,13 @@ void SavePasswordProgressLogger::LogURL(
void SavePasswordProgressLogger::LogBoolean(
SavePasswordProgressLogger::StringID label,
bool truth_value) {
- LogValue(label, FundamentalValue(truth_value));
+ LogValue(label, Value(truth_value));
}
void SavePasswordProgressLogger::LogNumber(
SavePasswordProgressLogger::StringID label,
int signed_number) {
- LogValue(label, FundamentalValue(signed_number));
+ LogValue(label, Value(signed_number));
}
void SavePasswordProgressLogger::LogNumber(