summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/autofill/core/browser/autofill_profile.cc26
-rw-r--r--components/autofill/core/browser/autofill_profile.h11
-rw-r--r--components/autofill/core/browser/autofill_test_utils.cc2
-rw-r--r--components/autofill/core/browser/personal_data_manager.cc21
-rw-r--r--components/autofill/core/browser/personal_data_manager_unittest.cc29
-rw-r--r--components/autofill/core/browser/webdata/autofill_table.cc296
-rw-r--r--components/autofill/core/browser/webdata/autofill_table.h43
-rw-r--r--components/autofill/core/browser/webdata/autofill_table_unittest.cc111
-rw-r--r--components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc4
-rw-r--r--components/autofill/core/browser/webdata/autofill_webdata.h10
-rw-r--r--components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc19
-rw-r--r--components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h8
-rw-r--r--components/autofill/core/browser/webdata/autofill_webdata_service.cc16
-rw-r--r--components/autofill/core/browser/webdata/autofill_webdata_service.h5
-rw-r--r--components/test/data/web_database/version_64.sql26
-rw-r--r--components/webdata/common/web_database.cc2
-rw-r--r--components/webdata/common/web_database_migration_unittest.cc49
-rw-r--r--sync/protocol/autofill_specifics.proto2
18 files changed, 579 insertions, 101 deletions
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc
index 196910c..9ea27e6 100644
--- a/components/autofill/core/browser/autofill_profile.cc
+++ b/components/autofill/core/browser/autofill_profile.cc
@@ -15,6 +15,7 @@
#include "base/i18n/case_conversion.h"
#include "base/i18n/char_iterator.h"
#include "base/logging.h"
+#include "base/sha1.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "base/strings/utf_string_conversions.h"
@@ -267,7 +268,8 @@ AutofillProfile::AutofillProfile(RecordType type, const std::string& server_id)
record_type_(type),
name_(1),
email_(1),
- phone_number_(1, PhoneNumber(this)) {
+ phone_number_(1, PhoneNumber(this)),
+ server_id_(server_id) {
DCHECK(type == SERVER_PROFILE);
}
@@ -311,6 +313,8 @@ AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
address_ = profile.address_;
set_language_code(profile.language_code());
+ server_id_ = profile.server_id();
+
return *this;
}
@@ -824,6 +828,26 @@ void AutofillProfile::CreateInferredLabels(
}
}
+void AutofillProfile::GenerateServerProfileIdentifier() {
+ DCHECK_EQ(SERVER_PROFILE, record_type());
+ base::string16 contents = MultiString(*this, NAME_FIRST);
+ contents.append(MultiString(*this, NAME_MIDDLE));
+ contents.append(MultiString(*this, NAME_LAST));
+ contents.append(MultiString(*this, EMAIL_ADDRESS));
+ contents.append(GetRawInfo(COMPANY_NAME));
+ contents.append(GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ contents.append(GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
+ contents.append(GetRawInfo(ADDRESS_HOME_CITY));
+ contents.append(GetRawInfo(ADDRESS_HOME_STATE));
+ contents.append(GetRawInfo(ADDRESS_HOME_ZIP));
+ contents.append(GetRawInfo(ADDRESS_HOME_SORTING_CODE));
+ contents.append(GetRawInfo(ADDRESS_HOME_COUNTRY));
+ contents.append(MultiString(*this, PHONE_HOME_WHOLE_NUMBER));
+ std::string contents_utf8 = UTF16ToUTF8(contents);
+ contents_utf8.append(language_code());
+ server_id_ = base::SHA1HashString(contents_utf8);
+}
+
// static
base::string16 AutofillProfile::CanonicalizeProfileString(
const base::string16& str) {
diff --git a/components/autofill/core/browser/autofill_profile.h b/components/autofill/core/browser/autofill_profile.h
index 597ff041..5da60d5 100644
--- a/components/autofill/core/browser/autofill_profile.h
+++ b/components/autofill/core/browser/autofill_profile.h
@@ -42,7 +42,8 @@ class AutofillProfile : public AutofillDataModel {
AutofillProfile(const std::string& guid, const std::string& origin);
// Server profile constructor. The type must be SERVER_PROFILE (this serves
- // to differentiate this constructor).
+ // to differentiate this constructor). |server_id| can be empty. If empty,
+ // callers should invoke GenerateServerProfileIdentifier after setting data.
AutofillProfile(RecordType type, const std::string& server_id);
// For use in STL containers.
@@ -181,6 +182,11 @@ class AutofillProfile : public AutofillDataModel {
// Nonempty only when type() == SERVER_PROFILE.
const std::string& server_id() const { return server_id_; }
+ // Creates an identifier and saves it as |server_id_|. Only used for
+ // server credit cards. The server doesn't attach an identifier so Chrome
+ // creates its own. The ID is a hash of the data contained in the profile.
+ void GenerateServerProfileIdentifier();
+
// Returns a standardized representation of the given string for comparison
// purposes. The resulting string will be lower-cased with all punctuation
// substituted by spaces. Whitespace will be converted to ASCII space, and
@@ -257,7 +263,8 @@ class AutofillProfile : public AutofillDataModel {
// The BCP 47 language code that can be used to format |address_| for display.
std::string language_code_;
- // ID assigned by the server. This will be set only for WALLET_PROFILEs.
+ // ID used for identifying this profile. Only set for SERVER_PROFILEs. This is
+ // a hash of the contents.
std::string server_id_;
};
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index 8b94c99..922eff7 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -299,7 +299,7 @@ void SetServerCreditCards(AutofillTable* table,
if (card.record_type() != CreditCard::FULL_SERVER_CARD)
continue;
- table->UnmaskServerCreditCard(card.server_id(), card.number());
+ table->UnmaskServerCreditCard(card, card.number());
}
}
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 0e10852..b7a0a46 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -517,16 +517,10 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
if (credit_card) {
credit_card->RecordUse();
- if (credit_card->record_type() == CreditCard::LOCAL_CARD) {
+ if (credit_card->record_type() == CreditCard::LOCAL_CARD)
database_->UpdateCreditCard(*credit_card);
- } else if (credit_card->record_type() == CreditCard::FULL_SERVER_CARD) {
- database_->UpdateUnmaskedCardUsageStats(*credit_card);
- } else {
- // It's possible to get a masked server card here if the user decides not
- // to store a card while verifying it. We don't currently track usage
- // of masked cards, so no-op.
- return;
- }
+ else
+ database_->UpdateServerCardUsageStats(*credit_card);
Refresh();
return;
@@ -535,7 +529,12 @@ void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
AutofillProfile* profile = GetProfileByGUID(data_model.guid());
if (profile) {
profile->RecordUse();
- database_->UpdateAutofillProfile(*profile);
+
+ if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
+ database_->UpdateAutofillProfile(*profile);
+ else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
+ database_->UpdateServerAddressUsageStats(*profile);
+
Refresh();
}
}
@@ -673,7 +672,7 @@ void PersonalDataManager::UpdateServerCreditCard(
DCHECK_NE(existing_credit_card->record_type(), credit_card.record_type());
DCHECK_EQ(existing_credit_card->Label(), credit_card.Label());
if (existing_credit_card->record_type() == CreditCard::MASKED_SERVER_CARD) {
- database_->UnmaskServerCreditCard(credit_card.server_id(),
+ database_->UnmaskServerCreditCard(credit_card,
credit_card.number());
} else {
database_->MaskServerCreditCard(credit_card.server_id());
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 74f934d..ae63c86 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -3102,7 +3102,7 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
test::SetCreditCardInfo(&server_cards.back(), "Bonnie Parker",
- "2109" /* Mastercard */, "12", "2012");
+ "4444" /* Mastercard */, "12", "2012");
server_cards.back().SetTypeForMaskedCard(kMasterCard);
server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
@@ -3131,6 +3131,7 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
+ ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
for (size_t i = 0; i < 3; ++i)
EXPECT_EQ(0, server_cards[i].Compare(*personal_data_->GetCreditCards()[i]));
@@ -3152,6 +3153,7 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.WillOnce(QuitMainMessageLoop());
base::MessageLoop::current()->Run();
+ ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
EXPECT_EQ(1U, personal_data_->GetCreditCards()[0]->use_count());
EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[0]->use_date());
@@ -3163,6 +3165,31 @@ TEST_F(PersonalDataManagerTest, UpdateServerCreditCardUsageStats) {
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());
+
+ // Can record usage stats on masked cards.
+ server_cards[1].set_guid(personal_data_->GetCreditCards()[1]->guid());
+ personal_data_->RecordUseOf(server_cards[1]);
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::MessageLoop::current()->Run();
+ ASSERT_EQ(3U, personal_data_->GetCreditCards().size());
+ EXPECT_EQ(1U, personal_data_->GetCreditCards()[1]->use_count());
+ EXPECT_NE(base::Time(), personal_data_->GetCreditCards()[1]->use_date());
+
+ // Upgrading to unmasked retains the usage stats (and increments them).
+ CreditCard* unmasked_card2 = &server_cards[1];
+ unmasked_card2->set_record_type(CreditCard::FULL_SERVER_CARD);
+ unmasked_card2->SetNumber(ASCIIToUTF16("5555555555554444"));
+ personal_data_->UpdateServerCreditCard(*unmasked_card2);
+
+ server_cards[1].set_guid(personal_data_->GetCreditCards()[1]->guid());
+ personal_data_->RecordUseOf(server_cards[1]);
+ EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
+ .WillOnce(QuitMainMessageLoop());
+ base::MessageLoop::current()->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());
}
TEST_F(PersonalDataManagerTest, ClearAllServerData) {
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index 10ec246..3f5a4c2 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -437,7 +437,8 @@ bool AutofillTable::CreateTablesIfNecessary() {
InitProfileNamesTable() && InitProfileEmailsTable() &&
InitProfilePhonesTable() && InitProfileTrashTable() &&
InitMaskedCreditCardsTable() && InitUnmaskedCreditCardsTable() &&
- InitServerAddressesTable());
+ InitServerCardMetadataTable() && InitServerAddressesTable() &&
+ InitServerAddressMetadataTable());
}
bool AutofillTable::IsSyncable() {
@@ -475,6 +476,9 @@ bool AutofillTable::MigrateToVersion(int version,
case 64:
*update_compatible_version = false;
return MigrateToVersion64AddUnmaskDate();
+ case 65:
+ *update_compatible_version = false;
+ return MigrateToVersion65AddServerMetadataTables();
}
return true;
}
@@ -904,6 +908,8 @@ bool AutofillTable::GetServerProfiles(std::vector<AutofillProfile*>* profiles) {
sql::Statement s(db_->GetUniqueStatement(
"SELECT "
"id,"
+ "use_count,"
+ "use_date,"
"recipient_name,"
"company_name,"
"street_address,"
@@ -916,12 +922,16 @@ bool AutofillTable::GetServerProfiles(std::vector<AutofillProfile*>* profiles) {
"country_code," // ADDRESS_HOME_COUNTRY
"phone_number," // PHONE_HOME_WHOLE_NUMBER
"language_code "
- "FROM server_addresses"));
+ "FROM server_addresses addresses "
+ "LEFT OUTER JOIN server_address_metadata USING (id)"));
while (s.Step()) {
int index = 0;
scoped_ptr<AutofillProfile> profile(new AutofillProfile(
AutofillProfile::SERVER_PROFILE, s.ColumnString(index++)));
+ profile->set_use_count(s.ColumnInt64(index++));
+ profile->set_use_date(
+ base::Time::FromInternalValue(s.ColumnInt64(index++)));
base::string16 recipient_name = s.ColumnString16(index++);
profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
@@ -1001,6 +1011,12 @@ void AutofillTable::SetServerProfiles(
insert.Reset(true);
}
+ // Delete metadata that's no longer relevant.
+ sql::Statement metadata_delete(db_->GetUniqueStatement(
+ "DELETE FROM server_address_metadata WHERE id NOT IN "
+ "(SELECT id FROM server_addresses)"));
+ metadata_delete.Run();
+
transaction.Commit();
}
@@ -1155,16 +1171,16 @@ bool AutofillTable::GetServerCreditCards(
"card_number_encrypted, " // 0
"last_four," // 1
"masked.id," // 2
- "use_count," // 3
- "use_date," // 4
+ "metadata.use_count," // 3
+ "metadata.use_date," // 4
"type," // 5
"status," // 6
"name_on_card," // 7
"exp_month," // 8
"exp_year " // 9
"FROM masked_credit_cards masked "
- "LEFT OUTER JOIN unmasked_credit_cards unmasked "
- "ON masked.id = unmasked.id"));
+ "LEFT OUTER JOIN unmasked_credit_cards USING (id) "
+ "LEFT OUTER JOIN server_card_metadata metadata USING (id)"));
while (s.Step()) {
int index = 0;
@@ -1182,19 +1198,16 @@ bool AutofillTable::GetServerCreditCards(
CREDIT_CARD_NUMBER,
record_type == CreditCard::MASKED_SERVER_CARD ? last_four
: full_card_number);
- int64 use_count = s.ColumnInt64(index++);
- int64 use_date = s.ColumnInt64(index++);
+ card->set_use_count(s.ColumnInt64(index++));
+ card->set_use_date(base::Time::FromInternalValue(s.ColumnInt64(index++)));
+
std::string card_type = s.ColumnString(index++);
if (record_type == CreditCard::MASKED_SERVER_CARD) {
// The type must be set after setting the number to override the
// autodectected type.
card->SetTypeForMaskedCard(card_type.c_str());
- DCHECK_EQ(0, use_count);
- DCHECK_EQ(0, use_date);
} else {
DCHECK_EQ(CreditCard::GetCreditCardType(full_card_number), card_type);
- card->set_use_count(use_count);
- card->set_use_date(base::Time::FromInternalValue(use_date));
}
card->SetServerStatus(ServerStatusStringToEnum(s.ColumnString(index++)));
@@ -1218,31 +1231,6 @@ void AutofillTable::SetServerCreditCards(
"DELETE FROM masked_credit_cards"));
masked_delete.Run();
- // Delete all items in the unmasked table that aren't in the new set.
- sql::Statement get_unmasked(db_->GetUniqueStatement(
- "SELECT id FROM unmasked_credit_cards"));
- while (get_unmasked.Step()) {
- // We expect relatively few cards, just do brute-force.
- std::string server_id = get_unmasked.ColumnString(0);
- bool found_card = false;
- for (const CreditCard& cur_card : credit_cards) {
- if (cur_card.server_id() == server_id) {
- found_card = true;
- break;
- }
- }
- if (!found_card) {
- // This unmasked card in the DB isn't present in the input. The statement
- // is compiled every time because it's much more likely that this is never
- // executed than it runs more than once.
- sql::Statement unmasked_delete(db_->GetUniqueStatement(
- "DELETE FROM unmasked_credit_cards WHERE id = ?"));
- unmasked_delete.BindString(0, server_id);
- unmasked_delete.Run();
- DCHECK_EQ(1, db_->GetLastChangeCount());
- }
- }
-
sql::Statement masked_insert(db_->GetUniqueStatement(
"INSERT INTO masked_credit_cards("
"id," // 0
@@ -1270,36 +1258,46 @@ void AutofillTable::SetServerCreditCards(
masked_insert.Reset(true);
}
+ // Delete all items in the unmasked table that aren't in the new set.
+ sql::Statement unmasked_delete(db_->GetUniqueStatement(
+ "DELETE FROM unmasked_credit_cards WHERE id NOT IN "
+ "(SELECT id FROM masked_credit_cards)"));
+ unmasked_delete.Run();
+ // Do the same for metadata.
+ sql::Statement metadata_delete(db_->GetUniqueStatement(
+ "DELETE FROM server_card_metadata WHERE id NOT IN "
+ "(SELECT id FROM masked_credit_cards)"));
+ metadata_delete.Run();
+
transaction.Commit();
}
-bool AutofillTable::UnmaskServerCreditCard(const std::string& id,
+bool AutofillTable::UnmaskServerCreditCard(const CreditCard& masked,
const base::string16& full_number) {
// Make sure there aren't duplicates for this card.
- MaskServerCreditCard(id);
+ MaskServerCreditCard(masked.server_id());
sql::Statement s(db_->GetUniqueStatement(
"INSERT INTO unmasked_credit_cards("
"id,"
"card_number_encrypted,"
- "use_count,"
- "use_date,"
"unmask_date)"
- "VALUES (?,?,?,?,?)"));
- s.BindString(0, id);
+ "VALUES (?,?,?)"));
+ s.BindString(0, masked.server_id());
std::string encrypted_data;
OSCrypt::EncryptString16(full_number, &encrypted_data);
s.BindBlob(1, encrypted_data.data(),
static_cast<int>(encrypted_data.length()));
+ s.BindInt64(2, base::Time::Now().ToInternalValue()); // unmask_date
- // Unmasking counts as a usage, so set the stats accordingly.
- base::Time now = base::Time::Now();
- s.BindInt64(2, 1); // use_count
- s.BindInt64(3, now.ToInternalValue()); // use_date
+ s.Run();
- s.BindInt64(4, now.ToInternalValue()); // unmask_date
+ CreditCard unmasked = masked;
+ unmasked.set_record_type(CreditCard::FULL_SERVER_CARD);
+ unmasked.SetNumber(full_number);
+ unmasked.RecordUse();
+ UpdateServerCardUsageStats(unmasked);
- s.Run();
return db_->GetLastChangeCount() > 0;
}
@@ -1311,18 +1309,54 @@ bool AutofillTable::MaskServerCreditCard(const std::string& id) {
return db_->GetLastChangeCount() > 0;
}
-bool AutofillTable::UpdateUnmaskedCardUsageStats(
+bool AutofillTable::UpdateServerCardUsageStats(
const CreditCard& credit_card) {
- DCHECK_EQ(CreditCard::FULL_SERVER_CARD, credit_card.record_type());
+ DCHECK_NE(CreditCard::LOCAL_CARD, credit_card.record_type());
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement remove(db_->GetUniqueStatement(
+ "DELETE FROM server_card_metadata WHERE id = ?"));
+ remove.BindString(0, credit_card.server_id());
+ remove.Run();
sql::Statement s(db_->GetUniqueStatement(
- "UPDATE unmasked_credit_cards "
- "SET use_count=?, use_date=? "
- "WHERE id=?"));
+ "INSERT INTO server_card_metadata(use_count, use_date, id)"
+ "VALUES (?,?,?)"));
s.BindInt64(0, credit_card.use_count());
s.BindInt64(1, credit_card.use_date().ToInternalValue());
s.BindString(2, credit_card.server_id());
s.Run();
+
+ transaction.Commit();
+
+ return db_->GetLastChangeCount() > 0;
+}
+
+bool AutofillTable::UpdateServerAddressUsageStats(
+ const AutofillProfile& profile) {
+ DCHECK_EQ(AutofillProfile::SERVER_PROFILE, profile.record_type());
+
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement remove(db_->GetUniqueStatement(
+ "DELETE FROM server_address_metadata WHERE id = ?"));
+ remove.BindString(0, profile.server_id());
+ remove.Run();
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "INSERT INTO server_address_metadata(use_count, use_date, id)"
+ "VALUES (?,?,?)"));
+ s.BindInt64(0, profile.use_count());
+ s.BindInt64(1, profile.use_date().ToInternalValue());
+ s.BindString(2, profile.server_id());
+ s.Run();
+
+ transaction.Commit();
+
return db_->GetLastChangeCount() > 0;
}
@@ -1346,6 +1380,16 @@ bool AutofillTable::ClearAllServerData() {
addresses.Run();
changed |= db_->GetLastChangeCount() > 0;
+ sql::Statement card_metadata(db_->GetUniqueStatement(
+ "DELETE FROM server_card_metadata"));
+ card_metadata.Run();
+ changed |= db_->GetLastChangeCount() > 0;
+
+ sql::Statement address_metadata(db_->GetUniqueStatement(
+ "DELETE FROM server_address_metadata"));
+ address_metadata.Run();
+ changed |= db_->GetLastChangeCount() > 0;
+
transaction.Commit();
return changed;
}
@@ -1725,6 +1769,19 @@ bool AutofillTable::InitUnmaskedCreditCardsTable() {
return true;
}
+bool AutofillTable::InitServerCardMetadataTable() {
+ if (!db_->DoesTableExist("server_card_metadata")) {
+ if (!db_->Execute("CREATE TABLE server_card_metadata ("
+ "id VARCHAR NOT NULL,"
+ "use_count INTEGER NOT NULL DEFAULT 0, "
+ "use_date INTEGER NOT NULL DEFAULT 0)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
bool AutofillTable::InitServerAddressesTable() {
if (!db_->DoesTableExist("server_addresses")) {
// The space after language_code is necessary to match what sqlite does
@@ -1750,6 +1807,19 @@ bool AutofillTable::InitServerAddressesTable() {
return true;
}
+bool AutofillTable::InitServerAddressMetadataTable() {
+ if (!db_->DoesTableExist("server_address_metadata")) {
+ if (!db_->Execute("CREATE TABLE server_address_metadata ("
+ "id VARCHAR NOT NULL,"
+ "use_count INTEGER NOT NULL DEFAULT 0, "
+ "use_date INTEGER NOT NULL DEFAULT 0)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
bool AutofillTable::MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields() {
sql::Transaction transaction(db_);
if (!transaction.Begin())
@@ -2054,4 +2124,122 @@ bool AutofillTable::MigrateToVersion64AddUnmaskDate() {
return transaction.Commit();
}
+bool AutofillTable::MigrateToVersion65AddServerMetadataTables() {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ if (!db_->DoesTableExist("server_card_metadata") &&
+ !db_->Execute("CREATE TABLE server_card_metadata ("
+ "id VARCHAR NOT NULL,"
+ "use_count INTEGER NOT NULL DEFAULT 0, "
+ "use_date INTEGER NOT NULL DEFAULT 0)")) {
+ return false;
+ }
+
+ // This clobbers existing usage metadata, which is not synced and only
+ // applies to unmasked cards. Trying to migrate the usage metadata would be
+ // tricky as multiple devices for the same user get DB upgrades.
+ if (!db_->Execute("UPDATE unmasked_credit_cards "
+ "SET use_count=0, use_date=0")) {
+ return false;
+ }
+
+ if (!db_->DoesTableExist("server_address_metadata") &&
+ !db_->Execute("CREATE TABLE server_address_metadata ("
+ "id VARCHAR NOT NULL,"
+ "use_count INTEGER NOT NULL DEFAULT 0, "
+ "use_date INTEGER NOT NULL DEFAULT 0)")) {
+ return false;
+ }
+
+ // Get existing server addresses and generate IDs for them.
+ sql::Statement s(db_->GetUniqueStatement(
+ "SELECT "
+ "id,"
+ "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 "
+ "FROM server_addresses addresses"));
+ std::vector<AutofillProfile> profiles;
+ while (s.Step()) {
+ int index = 0;
+ AutofillProfile profile(
+ AutofillProfile::SERVER_PROFILE, s.ColumnString(index++));
+
+ base::string16 recipient_name = s.ColumnString16(index++);
+ profile.SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
+ profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, s.ColumnString16(index++));
+ profile.SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++));
+ profile.SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++));
+ profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
+ s.ColumnString16(index++));
+ index++; // Skip address_4 which we haven't added to AutofillProfile yet.
+ profile.SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++));
+ profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, s.ColumnString16(index++));
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++));
+ base::string16 phone_number = s.ColumnString16(index++);
+ profile.set_language_code(s.ColumnString(index++));
+ profile.SetInfo(AutofillType(NAME_FULL), recipient_name,
+ profile.language_code());
+ profile.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), phone_number,
+ profile.language_code());
+ profile.GenerateServerProfileIdentifier();
+ profiles.push_back(profile);
+ }
+
+ // Reinsert with the generated IDs.
+ sql::Statement delete_old(db_->GetUniqueStatement(
+ "DELETE FROM server_addresses"));
+ delete_old.Run();
+
+ sql::Statement insert(db_->GetUniqueStatement(
+ "INSERT INTO server_addresses("
+ "id,"
+ "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) "
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ for (const AutofillProfile& profile : profiles) {
+ int index = 0;
+ insert.BindString(index++, profile.server_id());
+ insert.BindString16(index++, profile.GetRawInfo(NAME_FULL));
+ insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME));
+ insert.BindString16(index++,
+ profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE));
+ insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY));
+ insert.BindString16(index++,
+ profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY));
+ index++; // SKip address_4 which we haven't added to AutofillProfile yet.
+ insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP));
+ insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE));
+ insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
+ insert.BindString16(index++, profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
+ insert.BindString(index++, profile.language_code());
+ insert.Run();
+ insert.Reset(true);
+ }
+
+ return transaction.Commit();
+}
+
} // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index cd97658..9ed5c8c 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -163,13 +163,22 @@ struct FormFieldData;
// masked_credit_cards table to get the rest of the data.
// card_number_encrypted
// Full card number, encrypted.
-// use_count The number of times this card has been used to fill
-// a form. Added in version 62.
-// use_date The date this card was last used to fill a form, in
-// internal time format (NOT time_t). Added in version 62.
+// use_count DEPRECATED in version 65. See server_card_metadata.
+// use_date DEPRECATED in version 65. See server_card_metadata.
// unmask_date The date this card was unmasked in units of
// Time::ToInternalValue. Added in version 64.
//
+// server_card_metadata
+// Metadata (currently, usage data) about server credit
+// cards. This will be synced.
+//
+// id The server ID, which matches an ID from the
+// masked_credit_cards table.
+// use_count The number of times this card has been used to fill
+// a form.
+// use_date The date this card was last used to fill a form,
+// in internal t.
+//
// server_addresses This table contains Autofill address data synced from
// the wallet server. It's basically the same as the
// autofill_profiles table but locally immutable.
@@ -198,6 +207,18 @@ struct FormFieldData;
// "ja-latn" language code starts with the recipient name.
// phone_number Phone number. This is a string and has no formatting
// constraints. Added in version 64.
+//
+// server_address_metadata
+// Metadata (currently, usage data) about server addresses.
+// This will be synced.
+//
+// id The server ID, which matches an ID from the
+// server_addresses table.
+// use_count The number of times this address has been used to fill
+// a form.
+// use_date The date this address was last used to fill a form,
+// in internal t.
+
class AutofillTable : public WebDatabaseTable {
public:
explicit AutofillTable(const std::string& app_locale);
@@ -316,12 +337,12 @@ class AutofillTable : public WebDatabaseTable {
// Cards synced from the server may be "masked" (only last 4 digits
// available) or "unmasked" (everything is available). These functions set
// that state.
- bool UnmaskServerCreditCard(const std::string& id,
+ bool UnmaskServerCreditCard(const CreditCard& masked,
const base::string16& full_number);
bool MaskServerCreditCard(const std::string& id);
- // Updates the use count and last use date for an unmasked server card.
- bool UpdateUnmaskedCardUsageStats(const CreditCard& credit_card);
+ bool UpdateServerCardUsageStats(const CreditCard& credit_card);
+ bool UpdateServerAddressUsageStats(const AutofillProfile& profile);
// Deletes all data from the server card and profile tables. Returns true if
// any data was deleted, false if not (so false means "commit not needed"
@@ -365,7 +386,10 @@ class AutofillTable : public WebDatabaseTable {
// Clear all profiles.
bool ClearAutofillProfiles();
- // Table migration functions.
+ // Table migration functions. NB: These do not and should not rely on other
+ // functions in this class. The implementation of a function such as
+ // GetCreditCard may change over time, but MigrateToVersionXX should never
+ // change.
bool MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields();
bool MigrateToVersion55MergeAutofillDatesTable();
bool MigrateToVersion56AddProfileLanguageCodeForFormatting();
@@ -375,6 +399,7 @@ class AutofillTable : public WebDatabaseTable {
bool MigrateToVersion62AddUsageStatsForUnmaskedCards();
bool MigrateToVersion63AddServerRecipientName();
bool MigrateToVersion64AddUnmaskDate();
+ bool MigrateToVersion65AddServerMetadataTables();
// Max data length saved in the table;
static const size_t kMaxDataLength;
@@ -444,7 +469,9 @@ class AutofillTable : public WebDatabaseTable {
bool InitProfileTrashTable();
bool InitMaskedCreditCardsTable();
bool InitUnmaskedCreditCardsTable();
+ bool InitServerCardMetadataTable();
bool InitServerAddressesTable();
+ bool InitServerAddressMetadataTable();
// The application locale. The locale is needed for the migration to version
// 35. Since it must be read on the UI thread, it is set when the table is
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index 061c63c..1f01515 100644
--- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -1665,7 +1665,7 @@ TEST_F(AutofillTableTest, MaskUnmaskServerCards) {
// Unmask the number. The full number should be available.
base::string16 full_number(ASCIIToUTF16("4111111111111111"));
- ASSERT_TRUE(table_->UnmaskServerCreditCard(inputs[0].server_id(),
+ ASSERT_TRUE(table_->UnmaskServerCreditCard(inputs[0],
full_number));
std::vector<CreditCard*> outputs;
@@ -1705,7 +1705,7 @@ TEST_F(AutofillTableTest, SetServerCardModify) {
// Now unmask it.
base::string16 full_number = ASCIIToUTF16("4111111111111111");
- table_->UnmaskServerCreditCard(masked_card.server_id(), full_number);
+ table_->UnmaskServerCreditCard(masked_card, full_number);
// The card should now be unmasked.
std::vector<CreditCard*> outputs;
@@ -1764,6 +1764,63 @@ TEST_F(AutofillTableTest, SetServerCardModify) {
outputs.clear();
}
+TEST_F(AutofillTableTest, SetServerCardUpdateUsageStats) {
+ // Add a masked card.
+ CreditCard masked_card(CreditCard::MASKED_SERVER_CARD, "a123");
+ masked_card.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("Paul F. Tompkins"));
+ masked_card.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("1"));
+ masked_card.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2020"));
+ masked_card.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("1111"));
+ masked_card.SetTypeForMaskedCard(kVisaCard);
+
+ std::vector<CreditCard> inputs;
+ inputs.push_back(masked_card);
+ test::SetServerCreditCards(table_.get(), inputs);
+
+ ScopedVector<CreditCard> outputs;
+ table_->GetServerCreditCards(&outputs.get());
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(masked_card.server_id(), outputs[0]->server_id());
+ EXPECT_EQ(0U, outputs[0]->use_count());
+ EXPECT_EQ(base::Time(), outputs[0]->use_date());
+ outputs.clear();
+
+ // Update the usage stats; make sure they're reflected in GetServerProfiles.
+ inputs.back().set_use_count(4U);
+ inputs.back().set_use_date(base::Time::Now());
+ table_->UpdateServerCardUsageStats(inputs.back());
+ table_->GetServerCreditCards(&outputs.get());
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(masked_card.server_id(), outputs[0]->server_id());
+ EXPECT_EQ(4U, outputs[0]->use_count());
+ EXPECT_NE(base::Time(), outputs[0]->use_date());
+ outputs.clear();
+
+ // Setting the cards again shouldn't delete the usage stats.
+ table_->SetServerCreditCards(inputs);
+ table_->GetServerCreditCards(&outputs.get());
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(masked_card.server_id(), outputs[0]->server_id());
+ EXPECT_EQ(4U, outputs[0]->use_count());
+ EXPECT_NE(base::Time(), outputs[0]->use_date());
+ outputs.clear();
+
+ // Set a card list where the card is missing --- this should clear metadata.
+ CreditCard masked_card2(CreditCard::MASKED_SERVER_CARD, "b456");
+ inputs.back() = masked_card2;
+ table_->SetServerCreditCards(inputs);
+
+ // Back to the original card list.
+ inputs.back() = masked_card;
+ table_->SetServerCreditCards(inputs);
+ table_->GetServerCreditCards(&outputs.get());
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(masked_card.server_id(), outputs[0]->server_id());
+ EXPECT_EQ(0U, outputs[0]->use_count());
+ EXPECT_EQ(base::Time(), outputs[0]->use_date());
+ outputs.clear();
+}
+
TEST_F(AutofillTableTest, SetServerProfile) {
AutofillProfile one(AutofillProfile::SERVER_PROFILE, "a123");
std::vector<AutofillProfile> inputs;
@@ -1792,6 +1849,52 @@ TEST_F(AutofillTableTest, SetServerProfile) {
outputs.clear();
}
+TEST_F(AutofillTableTest, SetServerProfileUpdateUsageStats) {
+ AutofillProfile one(AutofillProfile::SERVER_PROFILE, "a123");
+ std::vector<AutofillProfile> inputs;
+ inputs.push_back(one);
+ table_->SetServerProfiles(inputs);
+
+ ScopedVector<AutofillProfile> outputs;
+ table_->GetServerProfiles(&outputs.get());
+ 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());
+ outputs.clear();
+
+ // Update the usage stats; make sure they're reflected in GetServerProfiles.
+ inputs.back().set_use_count(4U);
+ inputs.back().set_use_date(base::Time::Now());
+ table_->UpdateServerAddressUsageStats(inputs.back());
+ table_->GetServerProfiles(&outputs.get());
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(one.server_id(), outputs[0]->server_id());
+ EXPECT_EQ(4U, outputs[0]->use_count());
+ EXPECT_NE(base::Time(), outputs[0]->use_date());
+ outputs.clear();
+
+ // Setting the profiles again shouldn't delete the usage stats.
+ table_->SetServerProfiles(inputs);
+ table_->GetServerProfiles(&outputs.get());
+ ASSERT_EQ(1u, outputs.size());
+ EXPECT_EQ(one.server_id(), outputs[0]->server_id());
+ EXPECT_EQ(4U, outputs[0]->use_count());
+ EXPECT_NE(base::Time(), outputs[0]->use_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.get());
+ 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());
+ outputs.clear();
+}
+
// Tests that deleting time ranges re-masks server credit cards that were
// unmasked in that time.
// TODO(brettw) fix flakiness and re-enable: crbug.com/465882
@@ -1815,7 +1918,7 @@ TEST_F(AutofillTableTest, DISABLED_DeleteUnmaskedCard) {
// Unmask it.
base::string16 full_number = ASCIIToUTF16("4111111111111111");
- table_->UnmaskServerCreditCard(masked_card.server_id(), full_number);
+ table_->UnmaskServerCreditCard(masked_card, full_number);
// Delete data in a range a year in the future.
std::vector<std::string> profile_guids;
@@ -1847,7 +1950,7 @@ TEST_F(AutofillTableTest, DISABLED_DeleteUnmaskedCard) {
outputs.clear();
// Unmask again, the card should be back.
- table_->UnmaskServerCreditCard(masked_card.server_id(), full_number);
+ table_->UnmaskServerCreditCard(masked_card, full_number);
ASSERT_TRUE(table_->GetServerCreditCards(&outputs.get()));
ASSERT_EQ(1u, outputs.size());
EXPECT_EQ(CreditCard::FULL_SERVER_CARD, outputs[0]->record_type());
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
index e4e0d05..e49fda7 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_syncable_service.cc
@@ -76,7 +76,7 @@ CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
AutofillProfile ProfileFromSpecifics(
const sync_pb::WalletPostalAddress& address) {
- AutofillProfile profile(AutofillProfile::SERVER_PROFILE, address.id());
+ AutofillProfile profile(AutofillProfile::SERVER_PROFILE, std::string());
// AutofillProfile stores multi-line addresses with newline separators.
std::vector<std::string> street_address(address.street_address().begin(),
@@ -109,6 +109,8 @@ AutofillProfile ProfileFromSpecifics(
base::UTF8ToUTF16(address.phone_number()),
profile.language_code());
+ profile.GenerateServerProfileIdentifier();
+
return profile;
}
diff --git a/components/autofill/core/browser/webdata/autofill_webdata.h b/components/autofill/core/browser/webdata/autofill_webdata.h
index 2cf04ef2..e2c121e 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata.h
@@ -103,12 +103,16 @@ class AutofillWebData {
// Toggles the record for a server credit card between masked (only last 4
// digits) and full (all digits).
- virtual void UnmaskServerCreditCard(const std::string& id,
+ virtual void UnmaskServerCreditCard(const CreditCard& credit_card,
const base::string16& full_number) = 0;
virtual void MaskServerCreditCard(const std::string& id) = 0;
- // Updates the use count and last use date for an unmasked server card.
- virtual void UpdateUnmaskedCardUsageStats(const CreditCard& credit_card) = 0;
+ // Updates the use count and last use date for a server card (masked or not).
+ virtual void UpdateServerCardUsageStats(const CreditCard& credit_card) = 0;
+
+ // Updates the use count and last use date for a server address.
+ virtual void UpdateServerAddressUsageStats(const AutofillProfile& profile)
+ = 0;
// Removes Autofill records from the database.
virtual void RemoveAutofillDataModifiedBetween(
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index 38bc3bc..2bdc505 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -336,12 +336,12 @@ scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetServerCreditCards(
}
WebDatabase::State AutofillWebDataBackendImpl::UnmaskServerCreditCard(
- const std::string& id,
+ const CreditCard& card,
const base::string16& full_number,
WebDatabase* db) {
DCHECK(db_thread_->BelongsToCurrentThread());
if (AutofillTable::FromWebDatabase(db)->UnmaskServerCreditCard(
- id, full_number))
+ card, full_number))
return WebDatabase::COMMIT_NEEDED;
return WebDatabase::COMMIT_NOT_NEEDED;
}
@@ -356,12 +356,23 @@ WebDatabase::State
return WebDatabase::COMMIT_NOT_NEEDED;
}
-WebDatabase::State AutofillWebDataBackendImpl::UpdateUnmaskedCardUsageStats(
+WebDatabase::State AutofillWebDataBackendImpl::UpdateServerCardUsageStats(
const CreditCard& card,
WebDatabase* db) {
DCHECK(db_thread_->BelongsToCurrentThread());
- if (AutofillTable::FromWebDatabase(db)->UpdateUnmaskedCardUsageStats(card))
+ if (AutofillTable::FromWebDatabase(db)->UpdateServerCardUsageStats(card))
+ return WebDatabase::COMMIT_NEEDED;
+ return WebDatabase::COMMIT_NOT_NEEDED;
+}
+
+WebDatabase::State AutofillWebDataBackendImpl::UpdateServerAddressUsageStats(
+ const AutofillProfile& profile,
+ WebDatabase* db) {
+ DCHECK(db_thread_->BelongsToCurrentThread());
+ if (AutofillTable::FromWebDatabase(db)->UpdateServerAddressUsageStats(
+ profile)) {
return WebDatabase::COMMIT_NEEDED;
+ }
return WebDatabase::COMMIT_NOT_NEEDED;
}
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 50f510a..18c54f7 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -137,16 +137,20 @@ class AutofillWebDataBackendImpl
// Server credit cards can be masked (only last 4 digits stored) or unmasked
// (all data stored). These toggle between the two states.
- WebDatabase::State UnmaskServerCreditCard(const std::string& id,
+ WebDatabase::State UnmaskServerCreditCard(const CreditCard& card,
const base::string16& full_number,
WebDatabase* db);
WebDatabase::State MaskServerCreditCard(const std::string& id,
WebDatabase* db);
- WebDatabase::State UpdateUnmaskedCardUsageStats(
+ WebDatabase::State UpdateServerCardUsageStats(
const CreditCard& credit_card,
WebDatabase* db);
+ WebDatabase::State UpdateServerAddressUsageStats(
+ const AutofillProfile& profile,
+ WebDatabase* db);
+
WebDatabase::State ClearAllServerData(WebDatabase* db);
// Removes Autofill records from the database. Valid only for local
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index 82da109..8f3be4d 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -183,12 +183,12 @@ WebDataServiceBase::Handle AutofillWebDataService::GetServerCreditCards(
}
void AutofillWebDataService::UnmaskServerCreditCard(
- const std::string& id,
+ const CreditCard& credit_card,
const base::string16& full_number) {
wdbs_->ScheduleDBTask(
FROM_HERE,
Bind(&AutofillWebDataBackendImpl::UnmaskServerCreditCard,
- autofill_backend_, id, full_number));
+ autofill_backend_, credit_card, full_number));
}
void AutofillWebDataService::MaskServerCreditCard(const std::string& id) {
@@ -205,14 +205,22 @@ void AutofillWebDataService::ClearAllServerData() {
autofill_backend_));
}
-void AutofillWebDataService::UpdateUnmaskedCardUsageStats(
+void AutofillWebDataService::UpdateServerCardUsageStats(
const CreditCard& credit_card) {
wdbs_->ScheduleDBTask(
FROM_HERE,
- Bind(&AutofillWebDataBackendImpl::UpdateUnmaskedCardUsageStats,
+ Bind(&AutofillWebDataBackendImpl::UpdateServerCardUsageStats,
autofill_backend_, credit_card));
}
+void AutofillWebDataService::UpdateServerAddressUsageStats(
+ const AutofillProfile& profile) {
+ wdbs_->ScheduleDBTask(
+ FROM_HERE,
+ Bind(&AutofillWebDataBackendImpl::UpdateServerAddressUsageStats,
+ autofill_backend_, profile));
+}
+
void AutofillWebDataService::RemoveAutofillDataModifiedBetween(
const Time& delete_begin,
const Time& delete_end) {
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.h b/components/autofill/core/browser/webdata/autofill_webdata_service.h
index acc23f3..221e49b 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -88,13 +88,14 @@ class AutofillWebDataService : public AutofillWebData,
// Server cards.
WebDataServiceBase::Handle GetServerCreditCards(
WebDataServiceConsumer* consumer) override;
- void UnmaskServerCreditCard(const std::string& id,
+ void UnmaskServerCreditCard(const CreditCard& card,
const base::string16& full_number) override;
void MaskServerCreditCard(const std::string& id) override;
void ClearAllServerData();
- void UpdateUnmaskedCardUsageStats(const CreditCard& credit_card) override;
+ void UpdateServerCardUsageStats(const CreditCard& credit_card) override;
+ void UpdateServerAddressUsageStats(const AutofillProfile& profile) override;
void RemoveAutofillDataModifiedBetween(const base::Time& delete_begin,
const base::Time& delete_end) override;
diff --git a/components/test/data/web_database/version_64.sql b/components/test/data/web_database/version_64.sql
new file mode 100644
index 0000000..620f52a
--- /dev/null
+++ b/components/test/data/web_database/version_64.sql
@@ -0,0 +1,26 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','64');
+INSERT INTO "meta" VALUES('last_compatible_version','61');
+INSERT INTO "meta" VALUES('Builtin Keyword Version','82');
+CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, date_created INTEGER DEFAULT 0, date_last_used INTEGER DEFAULT 0, count INTEGER DEFAULT 1, PRIMARY KEY (name, value));
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, street_address VARCHAR, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, sorting_code VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', language_code VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR, full_name VARCHAR);
+CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
+CREATE TABLE autofill_profile_phones ( guid VARCHAR, number VARCHAR);
+CREATE TABLE autofill_profiles_trash ( guid VARCHAR);
+CREATE TABLE masked_credit_cards (id VARCHAR,status VARCHAR,name_on_card VARCHAR,type VARCHAR,last_four VARCHAR,exp_month INTEGER DEFAULT 0,exp_year INTEGER DEFAULT 0);
+CREATE TABLE unmasked_credit_cards (id VARCHAR,card_number_encrypted VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, unmask_date INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE server_addresses (id VARCHAR,company_name VARCHAR,street_address VARCHAR,address_1 VARCHAR,address_2 VARCHAR,address_3 VARCHAR,address_4 VARCHAR,postal_code VARCHAR,sorting_code VARCHAR,country_code VARCHAR,language_code VARCHAR, recipient_name VARCHAR, phone_number VARCHAR);
+CREATE TABLE keywords (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,show_in_default_list INTEGER,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,instant_url VARCHAR,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR,alternate_urls VARCHAR,search_terms_replacement_key VARCHAR,image_url VARCHAR,search_url_post_params VARCHAR,suggest_url_post_params VARCHAR,instant_url_post_params VARCHAR,image_url_post_params VARCHAR,new_tab_url VARCHAR);
+INSERT INTO "keywords" VALUES(2,'Google','google.com','http://www.google.com/favicon.ico','{google:baseURL}search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:bookmarkBarPinned}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}{google:omniboxStartMarginParameter}{google:contextualSearchVersion}ie={inputEncoding}',1,'',0,0,'UTF-8',1,'{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&gs_ri={google:suggestRid}&xssi=t&q={searchTerms}&{google:inputType}{google:cursorPosition}{google:currentPageUrl}{google:pageClassification}{google:searchVersion}{google:sessionToken}{google:prefetchQuery}sugkey={google:suggestAPIKeyParameter}',1,0,'{google:baseURL}webhp?sourceid=chrome-instant&{google:RLZ}{google:forceInstantResults}{google:instantExtendedEnabledParameter}{google:ntpIsThemedParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}',0,'B0AD0C88-0B0F-4D2E-9412-7D600832785D','["{google:baseURL}#q={searchTerms}","{google:baseURL}search#q={searchTerms}","{google:baseURL}webhp#q={searchTerms}","{google:baseURL}s#q={searchTerms}","{google:baseURL}s?q={searchTerms}"]','espv','{google:baseURL}searchbyimage/upload','','','','encoded_image={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource},original_width={google:imageOriginalWidth},original_height={google:imageOriginalHeight}','{google:baseURL}_/chrome/newtab?{google:RLZ}{google:instantExtendedEnabledParameter}{google:ntpIsThemedParameter}ie={inputEncoding}');
+INSERT INTO "keywords" VALUES(3,'Bing','bing.com','https://www.bing.com/s/a/bing_p.ico','https://www.bing.com/search?q={searchTerms}&PC=U316&FORM=CHROMN',1,'',0,0,'UTF-8',1,'https://www.bing.com/osjson.aspx?query={searchTerms}&language={language}&PC=U316',3,0,'',0,'D42E29D2-75F7-4D8E-8ECA-3886F2B9E737','[]','','','','','','','https://www.bing.com/chrome/newtab');
+INSERT INTO "keywords" VALUES(4,'Yahoo!','yahoo.com','https://search.yahoo.com/favicon.ico','https://search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}',1,'',0,0,'UTF-8',1,'https://search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}',2,0,'',0,'832F796B-6C66-4B24-BB24-37A52E831685','[]','','','','','','','');
+INSERT INTO "keywords" VALUES(5,'AOL','aol.com','http://search.aol.com/favicon.ico','http://search.aol.com/aol/search?q={searchTerms}',1,'',0,0,'UTF-8',1,'http://autocomplete.search.aol.com/autocomplete/get?output=json&it=&q={searchTerms}',35,0,'',0,'8AF217B0-8D8B-431F-A4AC-471AABB85B4E','[]','','','','','','','');
+INSERT INTO "keywords" VALUES(6,'Ask','ask.com','http://sp.ask.com/sh/i/a16/favicon/favicon.ico','http://www.ask.com/web?q={searchTerms}',1,'',0,0,'UTF-8',1,'http://ss.ask.com/query?q={searchTerms}&li=ff',4,0,'',0,'3F7F86C1-1CA7-4080-8DD1-990348B92F31','[]','','','','','','','');
+CREATE INDEX autofill_name ON autofill (name);
+CREATE INDEX autofill_name_value_lower ON autofill (name, value_lower);
+COMMIT;
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc
index 04ff538..f091a2a 100644
--- a/components/webdata/common/web_database.cc
+++ b/components/webdata/common/web_database.cc
@@ -14,7 +14,7 @@
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
// static
-const int WebDatabase::kCurrentVersionNumber = 64;
+const int WebDatabase::kCurrentVersionNumber = 65;
const int WebDatabase::kDeprecatedVersionNumber = 51;
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index 1f36aad..9919098 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -132,7 +132,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 64;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 65;
void WebDatabaseMigrationTest::LoadDatabase(
const base::FilePath::StringType& file) {
@@ -934,3 +934,50 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion61ToCurrent) {
"use_date"));
}
}
+
+// Tests addition of server metadata tables.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion64ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_64.sql")));
+
+ // Verify pre-conditions.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(&connection, 64, 64));
+
+ EXPECT_FALSE(connection.DoesTableExist("server_card_metadata"));
+ EXPECT_FALSE(connection.DoesTableExist("server_address_metadata"));
+
+ // Add a server address --- make sure it gets an ID.
+ sql::Statement insert_profiles(
+ connection.GetUniqueStatement(
+ "INSERT INTO server_addresses(id, postal_code) "
+ "VALUES ('', 90210)"));
+ insert_profiles.Run();
+ }
+
+ DoMigration();
+
+ // Verify post-conditions.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ EXPECT_TRUE(connection.DoesTableExist("server_card_metadata"));
+ EXPECT_TRUE(connection.DoesTableExist("server_address_metadata"));
+
+ sql::Statement read_profiles(
+ connection.GetUniqueStatement(
+ "SELECT id, postal_code FROM server_addresses"));
+ ASSERT_TRUE(read_profiles.Step());
+ EXPECT_FALSE(read_profiles.ColumnString(0).empty());
+ EXPECT_EQ("90210", read_profiles.ColumnString(1));
+ }
+}
diff --git a/sync/protocol/autofill_specifics.proto b/sync/protocol/autofill_specifics.proto
index 85a868e..68547ae 100644
--- a/sync/protocol/autofill_specifics.proto
+++ b/sync/protocol/autofill_specifics.proto
@@ -116,7 +116,7 @@ message WalletMaskedCreditCard {
// Different than an AutofillProfile because this represents some known address
// on the server that is pulled down rather than synced between Chromes.
message WalletPostalAddress {
- // Server-generated unique ID string. This is opaque to the client.
+ // DEPRECATED
optional string id = 1;
optional string recipient_name = 12;