summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-23 03:53:09 +0000
committerdhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-23 03:53:09 +0000
commita6d8357a9702c6ce48e15914760708c1970a03e2 (patch)
tree196c9fe86d6d8b314815f5b7ad699024ec9dfee0 /chrome
parentdf0846a5f9527233de7b551dd426585f97b0f296 (diff)
downloadchromium_src-a6d8357a9702c6ce48e15914760708c1970a03e2.zip
chromium_src-a6d8357a9702c6ce48e15914760708c1970a03e2.tar.gz
chromium_src-a6d8357a9702c6ce48e15914760708c1970a03e2.tar.bz2
Autofill extend profiles to include multi-valued fields.
Changes to the underlying |autofill_profiles| schema. These changes split out name, email, and phone information into separate relationaly-tied tables so that we can support multi-valued fields. New tables are introduced: |autofill_profile_names|, |autofill_profile_emails|, and |autofill_profile_phones|. Also, the |label| fields have been removed from both |credit_cards| and |autofill_profiles|. BUG=65625 TEST=WebDatabaseMigrationTest.*:WebDatabaseTest.* Review URL: http://codereview.chromium.org/6546034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75710 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/webdata/web_database.cc745
-rw-r--r--chrome/browser/webdata/web_database.h3
-rw-r--r--chrome/browser/webdata/web_database_unittest.cc439
-rw-r--r--chrome/test/data/web_database/version_32.sql33
4 files changed, 1043 insertions, 177 deletions
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index d97698a..e3c5988 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -42,6 +42,12 @@
using webkit_glue::FormField;
using webkit_glue::PasswordForm;
+// Constants for the |autofill_profile_phones| |type| column.
+enum AutoFillPhoneType {
+ kAutoFillPhoneNumber = 0,
+ kAutoFillFaxNumber = 1
+};
+
////////////////////////////////////////////////////////////////////////////////
//
// Schema
@@ -111,12 +117,6 @@ using webkit_glue::PasswordForm;
//
// guid A guid string to uniquely identify the profile.
// Added in version 31.
-// label The label of the profile. Presented to the user when
-// selecting profiles.
-// first_name
-// middle_name
-// last_name
-// email
// company_name
// address_line_1
// address_line_2
@@ -124,19 +124,43 @@ using webkit_glue::PasswordForm;
// state
// zipcode
// country
-// phone
-// fax
// date_modified The date on which this profile was last modified.
// Added in version 30.
//
+// autofill_profile_names
+// This table contains the multi-valued name fields
+// associated with a profile.
+//
+// guid The guid string that identifies the profile to which
+// the name belongs.
+// first_name
+// middle_name
+// last_name
+//
+// autofill_profile_emails
+// This table contains the multi-valued email fields
+// associated with a profile.
+//
+// guid The guid string that identifies the profile to which
+// the email belongs.
+// email
+//
+// autofill_profile_phones
+// This table contains the multi-valued phone fields
+// associated with a profile.
+//
+// guid The guid string that identifies the profile to which
+// the phone or fax number belongs.
+// type An integer constant designating either phone or fax type
+// of the number.
+// number
+//
// credit_cards This table contains credit card data added by the user
// with the AutoFill dialog. Most of the columns are
// standard entries in a credit card form.
//
// guid A guid string to uniquely identify the profile.
// Added in version 31.
-// label The label of the credit card. Presented to the user
-// when selecting credit cards.
// name_on_card
// expiration_month
// expiration_year
@@ -165,8 +189,8 @@ typedef std::vector<Tuple3<int64, string16, string16> > AutofillElementList;
// Current version number. Note: when changing the current version number,
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
-const int kCurrentVersionNumber = 32;
-const int kCompatibleVersionNumber = 32;
+const int kCurrentVersionNumber = 33;
+const int kCompatibleVersionNumber = 33;
// ID of the url column in keywords.
const int kUrlIdPosition = 16;
@@ -257,93 +281,92 @@ void BindAutoFillProfileToStatement(const AutoFillProfile& profile,
sql::Statement* s) {
DCHECK(guid::IsValidGUID(profile.guid()));
s->BindString(0, profile.guid());
- s->BindString16(1, profile.Label());
- string16 text = profile.GetFieldText(AutoFillType(NAME_FIRST));
- s->BindString16(2, LimitDataSize(text));
- text = profile.GetFieldText(AutoFillType(NAME_MIDDLE));
- s->BindString16(3, LimitDataSize(text));
- text = profile.GetFieldText(AutoFillType(NAME_LAST));
- s->BindString16(4, LimitDataSize(text));
- text = profile.GetFieldText(AutoFillType(EMAIL_ADDRESS));
- s->BindString16(5, LimitDataSize(text));
- text = profile.GetFieldText(AutoFillType(COMPANY_NAME));
- s->BindString16(6, LimitDataSize(text));
+ string16 text = profile.GetFieldText(AutoFillType(COMPANY_NAME));
+ s->BindString16(1, LimitDataSize(text));
text = profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1));
- s->BindString16(7, LimitDataSize(text));
+ s->BindString16(2, LimitDataSize(text));
text = profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2));
- s->BindString16(8, LimitDataSize(text));
+ s->BindString16(3, LimitDataSize(text));
text = profile.GetFieldText(AutoFillType(ADDRESS_HOME_CITY));
- s->BindString16(9, LimitDataSize(text));
+ s->BindString16(4, LimitDataSize(text));
text = profile.GetFieldText(AutoFillType(ADDRESS_HOME_STATE));
- s->BindString16(10, LimitDataSize(text));
+ s->BindString16(5, LimitDataSize(text));
text = profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP));
- s->BindString16(11, LimitDataSize(text));
+ s->BindString16(6, LimitDataSize(text));
text = profile.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY));
- s->BindString16(12, LimitDataSize(text));
- text = profile.GetFieldText(AutoFillType(PHONE_HOME_WHOLE_NUMBER));
- s->BindString16(13, LimitDataSize(text));
- text = profile.GetFieldText(AutoFillType(PHONE_FAX_WHOLE_NUMBER));
- s->BindString16(14, LimitDataSize(text));
- s->BindInt64(15, Time::Now().ToTimeT());
+ s->BindString16(7, LimitDataSize(text));
+ s->BindInt64(8, Time::Now().ToTimeT());
}
AutoFillProfile* AutoFillProfileFromStatement(const sql::Statement& s) {
AutoFillProfile* profile = new AutoFillProfile;
profile->set_guid(s.ColumnString(0));
DCHECK(guid::IsValidGUID(profile->guid()));
- // TODO(dhollowa): remove label from |autofill_profiles| table.
- // Column 1 is label.
-
- profile->SetInfo(AutoFillType(NAME_FIRST),
- s.ColumnString16(2));
- profile->SetInfo(AutoFillType(NAME_MIDDLE),
- s.ColumnString16(3));
- profile->SetInfo(AutoFillType(NAME_LAST),
- s.ColumnString16(4));
- profile->SetInfo(AutoFillType(EMAIL_ADDRESS),
- s.ColumnString16(5));
- profile->SetInfo(AutoFillType(COMPANY_NAME),
- s.ColumnString16(6));
- profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE1),
- s.ColumnString16(7));
- profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE2),
- s.ColumnString16(8));
- profile->SetInfo(AutoFillType(ADDRESS_HOME_CITY),
- s.ColumnString16(9));
- profile->SetInfo(AutoFillType(ADDRESS_HOME_STATE),
- s.ColumnString16(10));
- profile->SetInfo(AutoFillType(ADDRESS_HOME_ZIP),
- s.ColumnString16(11));
- profile->SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY),
- s.ColumnString16(12));
- profile->SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER),
- s.ColumnString16(13));
- profile->SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER),
- s.ColumnString16(14));
- // Intentionally skip column 15, which stores the profile's modification date.
+
+ profile->SetInfo(AutoFillType(COMPANY_NAME), s.ColumnString16(1));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE1), s.ColumnString16(2));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE2), s.ColumnString16(3));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_CITY), s.ColumnString16(4));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_STATE), s.ColumnString16(5));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_ZIP), s.ColumnString16(6));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), s.ColumnString16(7));
+ // Intentionally skip column 8, which stores the profile's modification date.
return profile;
}
+void AddAutoFillProfileNameFromStatement(const sql::Statement& s,
+ AutoFillProfile* profile) {
+ DCHECK_EQ(profile->guid(), s.ColumnString(0));
+ DCHECK(guid::IsValidGUID(profile->guid()));
+
+ profile->SetInfo(AutoFillType(NAME_FIRST), s.ColumnString16(1));
+ profile->SetInfo(AutoFillType(NAME_MIDDLE), s.ColumnString16(2));
+ profile->SetInfo(AutoFillType(NAME_LAST), s.ColumnString16(3));
+}
+
+void AddAutoFillProfileEmailFromStatement(const sql::Statement& s,
+ AutoFillProfile* profile) {
+ DCHECK_EQ(profile->guid(), s.ColumnString(0));
+ DCHECK(guid::IsValidGUID(profile->guid()));
+
+ profile->SetInfo(AutoFillType(EMAIL_ADDRESS), s.ColumnString16(1));
+}
+
+void AddAutoFillProfilePhoneFromStatement(const sql::Statement& s,
+ AutoFillProfile* profile) {
+ DCHECK_EQ(profile->guid(), s.ColumnString(0));
+ DCHECK(guid::IsValidGUID(profile->guid()));
+ DCHECK_EQ(kAutoFillPhoneNumber, s.ColumnInt(1));
+ profile->SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER), s.ColumnString16(2));
+}
+
+void AddAutoFillProfileFaxFromStatement(const sql::Statement& s,
+ AutoFillProfile* profile) {
+ DCHECK_EQ(profile->guid(), s.ColumnString(0));
+ DCHECK(guid::IsValidGUID(profile->guid()));
+ DCHECK_EQ(kAutoFillFaxNumber, s.ColumnInt(1));
+ profile->SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER), s.ColumnString16(2));
+}
+
void BindCreditCardToStatement(const CreditCard& credit_card,
sql::Statement* s) {
DCHECK(guid::IsValidGUID(credit_card.guid()));
s->BindString(0, credit_card.guid());
- s->BindString16(1, credit_card.Label());
string16 text = credit_card.GetFieldText(AutoFillType(CREDIT_CARD_NAME));
- s->BindString16(2, LimitDataSize(text));
+ s->BindString16(1, LimitDataSize(text));
text = credit_card.GetFieldText(AutoFillType(CREDIT_CARD_EXP_MONTH));
- s->BindString16(3, LimitDataSize(text));
+ s->BindString16(2, LimitDataSize(text));
text = credit_card.GetFieldText(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR));
- s->BindString16(4, LimitDataSize(text));
+ s->BindString16(3, LimitDataSize(text));
text = credit_card.GetFieldText(AutoFillType(CREDIT_CARD_NUMBER));
std::string encrypted_data;
Encryptor::EncryptString16(text, &encrypted_data);
- s->BindBlob(5, encrypted_data.data(),
+ s->BindBlob(4, encrypted_data.data(),
static_cast<int>(encrypted_data.length()));
- s->BindInt64(6, Time::Now().ToTimeT());
+ s->BindInt64(5, Time::Now().ToTimeT());
}
CreditCard* CreditCardFromStatement(const sql::Statement& s) {
@@ -351,29 +374,218 @@ CreditCard* CreditCardFromStatement(const sql::Statement& s) {
credit_card->set_guid(s.ColumnString(0));
DCHECK(guid::IsValidGUID(credit_card->guid()));
- // TODO(dhollowa): remove label from |credit_cards| table.
- // Column 1 is label.
- credit_card->SetInfo(AutoFillType(CREDIT_CARD_NAME),
- s.ColumnString16(2));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_NAME), s.ColumnString16(1));
credit_card->SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
- s.ColumnString16(3));
+ s.ColumnString16(2));
credit_card->SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
- s.ColumnString16(4));
- int encrypted_number_len = s.ColumnByteLength(5);
+ s.ColumnString16(3));
+ int encrypted_number_len = s.ColumnByteLength(4);
string16 credit_card_number;
if (encrypted_number_len) {
std::string encrypted_number;
encrypted_number.resize(encrypted_number_len);
- memcpy(&encrypted_number[0], s.ColumnBlob(5), encrypted_number_len);
+ memcpy(&encrypted_number[0], s.ColumnBlob(4), encrypted_number_len);
Encryptor::DecryptString16(encrypted_number, &credit_card_number);
}
credit_card->SetInfo(AutoFillType(CREDIT_CARD_NUMBER), credit_card_number);
- // Intentionally skip column 6, which stores the modification date.
+ // Intentionally skip column 5, which stores the modification date.
return credit_card;
}
+bool AutoFillProfileHasName(const AutoFillProfile& profile) {
+ return !profile.GetFieldText(AutoFillType(NAME_FIRST)).empty() ||
+ !profile.GetFieldText(AutoFillType(NAME_MIDDLE)).empty() ||
+ !profile.GetFieldText(AutoFillType(NAME_MIDDLE)).empty();
+}
+
+bool AddAutoFillProfileName(const std::string& guid,
+ const AutoFillProfile& profile,
+ sql::Connection* db) {
+ if (!AutoFillProfileHasName(profile))
+ return true;
+
+ // Check for duplicate.
+ sql::Statement s_find(db->GetUniqueStatement(
+ "SELECT guid, first_name, middle_name, last_name "
+ "FROM autofill_profile_names "
+ "WHERE guid=? AND first_name=? AND middle_name=? AND last_name=?"));
+ if (!s_find) {
+ NOTREACHED();
+ return false;
+ }
+ s_find.BindString(0, guid);
+ s_find.BindString16(1, profile.GetFieldText(AutoFillType(NAME_FIRST)));
+ s_find.BindString16(2, profile.GetFieldText(AutoFillType(NAME_MIDDLE)));
+ s_find.BindString16(3, profile.GetFieldText(AutoFillType(NAME_LAST)));
+
+ if (!s_find.Step()) {
+ // Add the new name.
+ sql::Statement s(db->GetUniqueStatement(
+ "INSERT INTO autofill_profile_names"
+ " (guid, first_name, middle_name, last_name) "
+ "VALUES (?,?,?,?)"));
+ if (!s) {
+ NOTREACHED();
+ return false;
+ }
+ s.BindString(0, guid);
+ s.BindString16(1, profile.GetFieldText(AutoFillType(NAME_FIRST)));
+ s.BindString16(2, profile.GetFieldText(AutoFillType(NAME_MIDDLE)));
+ s.BindString16(3, profile.GetFieldText(AutoFillType(NAME_LAST)));
+
+ if (!s.Run()) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AddAutoFillProfileEmail(const std::string& guid,
+ const AutoFillProfile& profile,
+ sql::Connection* db) {
+ if (profile.GetFieldText(AutoFillType(EMAIL_ADDRESS)).empty())
+ return true;
+
+ // Check for duplicate.
+ sql::Statement s_find(db->GetUniqueStatement(
+ "SELECT guid, email "
+ "FROM autofill_profile_emails "
+ "WHERE guid=? AND email=?"));
+ if (!s_find) {
+ NOTREACHED();
+ return false;
+ }
+ s_find.BindString(0, guid);
+ s_find.BindString16(1, profile.GetFieldText(AutoFillType(EMAIL_ADDRESS)));
+
+ if (!s_find.Step()) {
+ sql::Statement s(db->GetUniqueStatement(
+ "INSERT INTO autofill_profile_emails"
+ " (guid, email) "
+ "VALUES (?,?)"));
+ if (!s) {
+ NOTREACHED();
+ return false;
+ }
+ s.BindString(0, guid);
+ s.BindString16(1, profile.GetFieldText(AutoFillType(EMAIL_ADDRESS)));
+
+ if (!s.Run()) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AddAutoFillProfilePhone(const std::string& guid,
+ const AutoFillProfile& profile,
+ AutoFillPhoneType phone_type,
+ sql::Connection* db) {
+ AutoFillFieldType field_type;
+ if (phone_type == kAutoFillPhoneNumber) {
+ field_type = PHONE_HOME_WHOLE_NUMBER;
+ } else if (phone_type == kAutoFillFaxNumber) {
+ field_type = PHONE_FAX_WHOLE_NUMBER;
+ } else {
+ NOTREACHED();
+ return false;
+ }
+
+ if (profile.GetFieldText(AutoFillType(field_type)).empty())
+ return true;
+
+ // Check for duplicate.
+ sql::Statement s_find(db->GetUniqueStatement(
+ "SELECT guid, type, number "
+ "FROM autofill_profile_phones "
+ "WHERE guid=? AND type=? AND number=?"));
+ if (!s_find) {
+ NOTREACHED();
+ return false;
+ }
+ s_find.BindString(0, guid);
+ s_find.BindInt(1, phone_type);
+ s_find.BindString16(
+ 2, profile.GetFieldText(AutoFillType(field_type)));
+
+ if (!s_find.Step()) {
+ sql::Statement s(db->GetUniqueStatement(
+ "INSERT INTO autofill_profile_phones"
+ " (guid, type, number) "
+ "VALUES (?,?,?)"));
+ if (!s) {
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+ s.BindString(0, guid);
+ s.BindInt(1, phone_type);
+ s.BindString16(
+ 2, profile.GetFieldText(AutoFillType(field_type)));
+
+ if (!s.Run()) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AddAutoFillProfilePieces(const std::string& guid,
+ const AutoFillProfile& profile,
+ sql::Connection* db) {
+ if (!AddAutoFillProfileName(guid, profile, db))
+ return false;
+
+ if (!AddAutoFillProfileEmail(guid, profile, db))
+ return false;
+
+ if (!AddAutoFillProfilePhone(guid, profile, kAutoFillPhoneNumber, db))
+ return false;
+
+ if (!AddAutoFillProfilePhone(guid, profile, kAutoFillFaxNumber, db))
+ return false;
+
+ return true;
+}
+
+bool RemoveAutoFillProfilePieces(const std::string& guid, sql::Connection* db) {
+ sql::Statement s1(db->GetUniqueStatement(
+ "DELETE FROM autofill_profile_names WHERE guid = ?"));
+ if (!s1) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ s1.BindString(0, guid);
+ if (!s1.Run())
+ return false;
+
+ sql::Statement s2(db->GetUniqueStatement(
+ "DELETE FROM autofill_profile_emails WHERE guid = ?"));
+ if (!s2) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ s2.BindString(0, guid);
+ if (!s2.Run())
+ return false;
+
+ sql::Statement s3(db->GetUniqueStatement(
+ "DELETE FROM autofill_profile_phones WHERE guid = ?"));
+ if (!s3) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+
+ s3.BindString(0, guid);
+ return s3.Run();
+}
+
} // namespace
WebDatabase::WebDatabase() {
@@ -432,7 +644,9 @@ sql::InitStatus WebDatabase::Init(const FilePath& db_name) {
if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() ||
!InitWebAppsTable() || !InitAutofillTable() ||
!InitAutofillDatesTable() || !InitAutoFillProfilesTable() ||
- !InitCreditCardsTable() || !InitTokenServiceTable()) {
+ !InitAutoFillProfileNamesTable() || !InitAutoFillProfileEmailsTable() ||
+ !InitAutoFillProfilePhonesTable() || !InitCreditCardsTable() ||
+ !InitTokenServiceTable()) {
LOG(WARNING) << "Unable to initialize the web database.";
return sql::INIT_FAILURE;
}
@@ -722,11 +936,6 @@ bool WebDatabase::InitAutoFillProfilesTable() {
if (!db_.DoesTableExist("autofill_profiles")) {
if (!db_.Execute("CREATE TABLE autofill_profiles ( "
"guid VARCHAR PRIMARY KEY, "
- "label VARCHAR, "
- "first_name VARCHAR, "
- "middle_name VARCHAR, "
- "last_name VARCHAR, "
- "email VARCHAR, "
"company_name VARCHAR, "
"address_line_1 VARCHAR, "
"address_line_2 VARCHAR, "
@@ -734,14 +943,46 @@ bool WebDatabase::InitAutoFillProfilesTable() {
"state VARCHAR, "
"zipcode VARCHAR, "
"country VARCHAR, "
- "phone VARCHAR, "
- "fax VARCHAR, "
"date_modified INTEGER NOT NULL DEFAULT 0)")) {
NOTREACHED();
return false;
}
- if (!db_.Execute("CREATE INDEX autofill_profiles_label_index "
- "ON autofill_profiles (label)")) {
+ }
+ return true;
+}
+
+bool WebDatabase::InitAutoFillProfileNamesTable() {
+ if (!db_.DoesTableExist("autofill_profile_names")) {
+ if (!db_.Execute("CREATE TABLE autofill_profile_names ( "
+ "guid VARCHAR, "
+ "first_name VARCHAR, "
+ "middle_name VARCHAR, "
+ "last_name VARCHAR)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WebDatabase::InitAutoFillProfileEmailsTable() {
+ if (!db_.DoesTableExist("autofill_profile_emails")) {
+ if (!db_.Execute("CREATE TABLE autofill_profile_emails ( "
+ "guid VARCHAR, "
+ "email VARCHAR)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WebDatabase::InitAutoFillProfilePhonesTable() {
+ if (!db_.DoesTableExist("autofill_profile_phones")) {
+ if (!db_.Execute("CREATE TABLE autofill_profile_phones ( "
+ "guid VARCHAR, "
+ "type INTEGER DEFAULT 0, "
+ "number VARCHAR)")) {
NOTREACHED();
return false;
}
@@ -753,7 +994,6 @@ bool WebDatabase::InitCreditCardsTable() {
if (!db_.DoesTableExist("credit_cards")) {
if (!db_.Execute("CREATE TABLE credit_cards ( "
"guid VARCHAR PRIMARY KEY, "
- "label VARCHAR, "
"name_on_card VARCHAR, "
"expiration_month INTEGER, "
"expiration_year INTEGER, "
@@ -762,11 +1002,6 @@ bool WebDatabase::InitCreditCardsTable() {
NOTREACHED();
return false;
}
- if (!db_.Execute("CREATE INDEX credit_cards_label_index "
- "ON credit_cards (label)")) {
- NOTREACHED();
- return false;
- }
}
return true;
@@ -1607,10 +1842,9 @@ bool WebDatabase::RemoveFormElement(const string16& name,
bool WebDatabase::AddAutoFillProfile(const AutoFillProfile& profile) {
sql::Statement s(db_.GetUniqueStatement(
"INSERT INTO autofill_profiles"
- "(guid, label, first_name, middle_name, last_name, email,"
- " company_name, address_line_1, address_line_2, city, state, zipcode,"
- " country, phone, fax, date_modified)"
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ "(guid, company_name, address_line_1, address_line_2, city, state,"
+ " zipcode, country, date_modified)"
+ "VALUES (?,?,?,?,?,?,?,?,?)"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -1623,7 +1857,10 @@ bool WebDatabase::AddAutoFillProfile(const AutoFillProfile& profile) {
return false;
}
- return s.Succeeded();
+ if (!s.Succeeded())
+ return false;
+
+ return AddAutoFillProfilePieces(profile.guid(), profile, &db_);
}
bool WebDatabase::GetAutoFillProfile(const std::string& guid,
@@ -1631,11 +1868,10 @@ bool WebDatabase::GetAutoFillProfile(const std::string& guid,
DCHECK(guid::IsValidGUID(guid));
DCHECK(profile);
sql::Statement s(db_.GetUniqueStatement(
- "SELECT guid, label, first_name, middle_name, last_name, email, "
- "company_name, address_line_1, address_line_2, city, state, zipcode, "
- "country, phone, fax, date_modified "
+ "SELECT guid, company_name, address_line_1, address_line_2, city, state,"
+ " zipcode, country, date_modified "
"FROM autofill_profiles "
- "WHERE guid = ?"));
+ "WHERE guid=?"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -1645,9 +1881,75 @@ bool WebDatabase::GetAutoFillProfile(const std::string& guid,
if (!s.Step())
return false;
- *profile = AutoFillProfileFromStatement(s);
+ if (!s.Succeeded())
+ return false;
- return s.Succeeded();
+ scoped_ptr<AutoFillProfile> p(AutoFillProfileFromStatement(s));
+
+ // Get associated name info.
+ sql::Statement s2(db_.GetUniqueStatement(
+ "SELECT guid, first_name, middle_name, last_name "
+ "FROM autofill_profile_names "
+ "WHERE guid=?"));
+ if (!s2) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+ s2.BindString(0, guid);
+
+ if (s2.Step()) {
+ AddAutoFillProfileNameFromStatement(s2, p.get());
+ }
+
+ // Get associated email info.
+ sql::Statement s3(db_.GetUniqueStatement(
+ "SELECT guid, email "
+ "FROM autofill_profile_emails "
+ "WHERE guid=?"));
+ if (!s3) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+ s3.BindString(0, guid);
+
+ if (s3.Step()) {
+ AddAutoFillProfileEmailFromStatement(s3, p.get());
+ }
+
+ // Get associated phone info.
+ sql::Statement s4(db_.GetUniqueStatement(
+ "SELECT guid, type, number "
+ "FROM autofill_profile_phones "
+ "WHERE guid=? AND type=?"));
+ if (!s4) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+ s4.BindString(0, guid);
+ s4.BindInt(1, kAutoFillPhoneNumber);
+
+ if (s4.Step()) {
+ AddAutoFillProfilePhoneFromStatement(s4, p.get());
+ }
+
+ // Get associated fax info.
+ sql::Statement s5(db_.GetUniqueStatement(
+ "SELECT guid, type, number "
+ "FROM autofill_profile_phones "
+ "WHERE guid=? AND type=?"));
+ if (!s5) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+ s5.BindString(0, guid);
+ s5.BindInt(1, kAutoFillFaxNumber);
+
+ if (s5.Step()) {
+ AddAutoFillProfileFaxFromStatement(s5, p.get());
+ }
+
+ *profile = p.release();
+ return true;
}
bool WebDatabase::GetAutoFillProfiles(
@@ -1656,17 +1958,20 @@ bool WebDatabase::GetAutoFillProfiles(
profiles->clear();
sql::Statement s(db_.GetUniqueStatement(
- "SELECT guid, label, first_name, middle_name, last_name, email, "
- "company_name, address_line_1, address_line_2, city, state, zipcode, "
- "country, phone, fax, date_modified "
+ "SELECT guid "
"FROM autofill_profiles"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
}
- while (s.Step())
- profiles->push_back(AutoFillProfileFromStatement(s));
+ while (s.Step()) {
+ std::string guid = s.ColumnString(0);
+ AutoFillProfile* profile = NULL;
+ if (!GetAutoFillProfile(guid, &profile))
+ return false;
+ profiles->push_back(profile);
+ }
return s.Succeeded();
}
@@ -1685,10 +1990,8 @@ bool WebDatabase::UpdateAutoFillProfile(const AutoFillProfile& profile) {
sql::Statement s(db_.GetUniqueStatement(
"UPDATE autofill_profiles "
- "SET guid=?, label=?, first_name=?, middle_name=?, last_name=?, "
- " email=?, company_name=?, address_line_1=?, address_line_2=?, "
- " city=?, state=?, zipcode=?, country=?, phone=?, fax=?, "
- " date_modified=? "
+ "SET guid=?, company_name=?, address_line_1=?, address_line_2=?, "
+ " city=?, state=?, zipcode=?, country=?, date_modified=? "
"WHERE guid=?"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
@@ -1696,10 +1999,17 @@ bool WebDatabase::UpdateAutoFillProfile(const AutoFillProfile& profile) {
}
BindAutoFillProfileToStatement(profile, &s);
- s.BindString(16, profile.guid());
+ s.BindString(9, profile.guid());
bool result = s.Run();
DCHECK_GT(db_.GetLastChangeCount(), 0);
- return result;
+ if (!result)
+ return result;
+
+ // Remove the old names, emails, and phone/fax numbers.
+ if (!RemoveAutoFillProfilePieces(profile.guid(), &db_))
+ return false;
+
+ return AddAutoFillProfilePieces(profile.guid(), profile, &db_);
}
bool WebDatabase::RemoveAutoFillProfile(const std::string& guid) {
@@ -1712,15 +2022,18 @@ bool WebDatabase::RemoveAutoFillProfile(const std::string& guid) {
}
s.BindString(0, guid);
- return s.Run();
+ if (!s.Run())
+ return false;
+
+ return RemoveAutoFillProfilePieces(guid, &db_);
}
bool WebDatabase::AddCreditCard(const CreditCard& credit_card) {
sql::Statement s(db_.GetUniqueStatement(
"INSERT INTO credit_cards"
- "(guid, label, name_on_card, expiration_month, expiration_year, "
+ "(guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified)"
- "VALUES (?,?,?,?,?,?,?)"));
+ "VALUES (?,?,?,?,?,?)"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
@@ -1738,10 +2051,10 @@ bool WebDatabase::AddCreditCard(const CreditCard& credit_card) {
}
bool WebDatabase::GetCreditCard(const std::string& guid,
- CreditCard** credit_card) {
+ CreditCard** credit_card) {
DCHECK(guid::IsValidGUID(guid));
sql::Statement s(db_.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
+ "SELECT guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified "
"FROM credit_cards "
"WHERE guid = ?"));
@@ -1765,16 +2078,20 @@ bool WebDatabase::GetCreditCards(
credit_cards->clear();
sql::Statement s(db_.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
- "card_number_encrypted, date_modified "
+ "SELECT guid "
"FROM credit_cards"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
}
- while (s.Step())
- credit_cards->push_back(CreditCardFromStatement(s));
+ while (s.Step()) {
+ std::string guid = s.ColumnString(0);
+ CreditCard* credit_card = NULL;
+ if (!GetCreditCard(guid, &credit_card))
+ return false;
+ credit_cards->push_back(credit_card);
+ }
return s.Succeeded();
}
@@ -1793,7 +2110,7 @@ bool WebDatabase::UpdateCreditCard(const CreditCard& credit_card) {
sql::Statement s(db_.GetUniqueStatement(
"UPDATE credit_cards "
- "SET guid=?, label=?, name_on_card=?, expiration_month=?, "
+ "SET guid=?, name_on_card=?, expiration_month=?, "
" expiration_year=?, card_number_encrypted=?, date_modified=? "
"WHERE guid=?"));
if (!s) {
@@ -1802,7 +2119,7 @@ bool WebDatabase::UpdateCreditCard(const CreditCard& credit_card) {
}
BindCreditCardToStatement(credit_card, &s);
- s.BindString(7, credit_card.guid());
+ s.BindString(6, credit_card.guid());
bool result = s.Run();
DCHECK_GT(db_.GetLastChangeCount(), 0);
return result;
@@ -2045,7 +2362,8 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){
db_.DoesColumnExist("credit_cards", "expiration_month") &&
db_.DoesColumnExist("credit_cards", "expiration_year") &&
db_.DoesColumnExist("credit_cards", "billing_address") &&
- db_.DoesColumnExist("credit_cards", "shipping_address")) {
+ db_.DoesColumnExist("credit_cards", "shipping_address") &&
+ db_.DoesColumnExist("autofill_profiles", "label")) {
query = "DELETE FROM credit_cards WHERE (" + credit_cards_is_too_big +
") OR label IN (SELECT label FROM autofill_profiles WHERE " +
autofill_profiles_is_too_big + ")";
@@ -2055,12 +2373,14 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){
return sql::INIT_FAILURE;
}
}
- query = "DELETE FROM autofill_profiles WHERE " +
- autofill_profiles_is_too_big;
- if (!db_.Execute(query.c_str())) {
- LOG(WARNING) << "Unable to update web database to version 24.";
- NOTREACHED();
- return sql::INIT_FAILURE;
+ if (db_.DoesColumnExist("autofill_profiles", "label")) {
+ query = "DELETE FROM autofill_profiles WHERE " +
+ autofill_profiles_is_too_big;
+ if (!db_.Execute(query.c_str())) {
+ LOG(WARNING) << "Unable to update web database to version 24.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
}
meta_table_.SetVersionNumber(24);
@@ -2533,6 +2853,161 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){
// FALL THROUGH
+ case 32:
+ // Test the existence of the |first_name| column as an indication that
+ // we need a migration. It is possible that the new |autofill_profiles|
+ // schema is in place because the table was newly created when migrating
+ // from a pre-version-22 database.
+ if (db_.DoesColumnExist("autofill_profiles", "first_name")) {
+ // Create autofill_profiles_temp table that will receive the data.
+ if (!db_.DoesTableExist("autofill_profiles_temp")) {
+ if (!db_.Execute("CREATE TABLE autofill_profiles_temp ( "
+ "guid VARCHAR PRIMARY KEY, "
+ "company_name VARCHAR, "
+ "address_line_1 VARCHAR, "
+ "address_line_2 VARCHAR, "
+ "city VARCHAR, "
+ "state VARCHAR, "
+ "zipcode VARCHAR, "
+ "country VARCHAR, "
+ "date_modified INTEGER NOT NULL DEFAULT 0)")) {
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+ }
+
+ {
+ sql::Statement s(db_.GetUniqueStatement(
+ "SELECT guid, first_name, middle_name, last_name, email, "
+ "company_name, address_line_1, address_line_2, city, state, "
+ "zipcode, country, phone, fax, date_modified "
+ "FROM autofill_profiles"));
+ while (s.Step()) {
+ AutoFillProfile profile;
+ profile.set_guid(s.ColumnString(0));
+ DCHECK(guid::IsValidGUID(profile.guid()));
+
+ profile.SetInfo(AutoFillType(NAME_FIRST), s.ColumnString16(1));
+ profile.SetInfo(AutoFillType(NAME_MIDDLE), s.ColumnString16(2));
+ profile.SetInfo(AutoFillType(NAME_LAST), s.ColumnString16(3));
+ profile.SetInfo(AutoFillType(EMAIL_ADDRESS), s.ColumnString16(4));
+ profile.SetInfo(AutoFillType(COMPANY_NAME), s.ColumnString16(5));
+ profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE1),
+ s.ColumnString16(6));
+ profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE2),
+ s.ColumnString16(7));
+ profile.SetInfo(AutoFillType(ADDRESS_HOME_CITY),
+ s.ColumnString16(8));
+ profile.SetInfo(AutoFillType(ADDRESS_HOME_STATE),
+ s.ColumnString16(9));
+ profile.SetInfo(AutoFillType(ADDRESS_HOME_ZIP),
+ s.ColumnString16(10));
+ profile.SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY),
+ s.ColumnString16(11));
+ profile.SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER),
+ s.ColumnString16(12));
+ profile.SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER),
+ s.ColumnString16(13));
+ int64 date_modified = s.ColumnInt64(14);
+
+ sql::Statement s_insert(db_.GetUniqueStatement(
+ "INSERT INTO autofill_profiles_temp"
+ "(guid, company_name, address_line_1, address_line_2, city,"
+ " state, zipcode, country, date_modified)"
+ "VALUES (?,?,?,?,?,?,?,?,?)"));
+ if (!s) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+ s_insert.BindString(0, profile.guid());
+ s_insert.BindString16(
+ 1, profile.GetFieldText(AutoFillType(COMPANY_NAME)));
+ s_insert.BindString16(
+ 2, profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)));
+ s_insert.BindString16(
+ 3, profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)));
+ s_insert.BindString16(
+ 4, profile.GetFieldText(AutoFillType(ADDRESS_HOME_CITY)));
+ s_insert.BindString16(
+ 5, profile.GetFieldText(AutoFillType(ADDRESS_HOME_STATE)));
+ s_insert.BindString16(
+ 6, profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)));
+ s_insert.BindString16(
+ 7, profile.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY)));
+ s_insert.BindInt64(8, date_modified);
+
+ if (!s_insert.Run()) {
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+
+ // Add the other bits: names, emails, and phone/fax.
+ if (!AddAutoFillProfilePieces(profile.guid(), profile, &db_)) {
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+ }
+ }
+
+ if (!db_.Execute("DROP TABLE autofill_profiles")) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+
+ if (!db_.Execute(
+ "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+ }
+
+ // Remove the labels column from the credit_cards table.
+ if (db_.DoesColumnExist("credit_cards", "label")) {
+ if (!db_.Execute("CREATE TABLE credit_cards_temp ( "
+ "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)")) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+
+ if (!db_.Execute(
+ "INSERT INTO credit_cards_temp "
+ "SELECT guid, name_on_card, expiration_month, "
+ "expiration_year, card_number_encrypted, date_modified "
+ "FROM credit_cards")) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+
+ if (!db_.Execute("DROP TABLE credit_cards")) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+
+ if (!db_.Execute(
+ "ALTER TABLE credit_cards_temp RENAME TO credit_cards")) {
+ LOG(WARNING) << "Unable to update web database to version 33.";
+ NOTREACHED();
+ return sql::INIT_FAILURE;
+ }
+ }
+
+ meta_table_.SetVersionNumber(33);
+ meta_table_.SetCompatibleVersionNumber(
+ std::min(33, kCompatibleVersionNumber));
+
+ // FALL THROUGH
+
// Add successive versions here. Each should set the version number and
// compatible version number as appropriate, then fall through to the next
// case.
diff --git a/chrome/browser/webdata/web_database.h b/chrome/browser/webdata/web_database.h
index 49d8677..7e315bc 100644
--- a/chrome/browser/webdata/web_database.h
+++ b/chrome/browser/webdata/web_database.h
@@ -338,6 +338,9 @@ class WebDatabase {
bool InitAutofillTable();
bool InitAutofillDatesTable();
bool InitAutoFillProfilesTable();
+ bool InitAutoFillProfileNamesTable();
+ bool InitAutoFillProfileEmailsTable();
+ bool InitAutoFillProfilePhonesTable();
bool InitCreditCardsTable();
bool InitTokenServiceTable();
bool InitWebAppIconsTable();
diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc
index 0c9b758..4c7baa9 100644
--- a/chrome/browser/webdata/web_database_unittest.cc
+++ b/chrome/browser/webdata/web_database_unittest.cc
@@ -149,6 +149,23 @@ void AutoFillProfile32FromStatement(const sql::Statement& s,
*date_modified = s.ColumnInt64(15);
}
+void AutoFillProfile33FromStatement(const sql::Statement& s,
+ AutoFillProfile* profile,
+ int64* date_modified) {
+ DCHECK(profile);
+ DCHECK(date_modified);
+ profile->set_guid(s.ColumnString(0));
+ EXPECT_TRUE(guid::IsValidGUID(profile->guid()));
+ profile->SetInfo(AutoFillType(COMPANY_NAME), s.ColumnString16(1));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE1), s.ColumnString16(2));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_LINE2), s.ColumnString16(3));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_CITY), s.ColumnString16(4));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_STATE), s.ColumnString16(5));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_ZIP), s.ColumnString16(6));
+ profile->SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), s.ColumnString16(7));
+ *date_modified = s.ColumnInt64(8);
+}
+
void CreditCard31FromStatement(const sql::Statement& s,
CreditCard* credit_card,
string16* label,
@@ -180,27 +197,24 @@ void CreditCard31FromStatement(const sql::Statement& s,
void CreditCard32FromStatement(const sql::Statement& s,
CreditCard* credit_card,
- string16* label,
std::string* encrypted_number,
int64* date_modified) {
DCHECK(credit_card);
- DCHECK(label);
DCHECK(encrypted_number);
DCHECK(date_modified);
credit_card->set_guid(s.ColumnString(0));
EXPECT_TRUE(guid::IsValidGUID(credit_card->guid()));
- *label = s.ColumnString16(1);
- credit_card->SetInfo(AutoFillType(CREDIT_CARD_NAME), s.ColumnString16(2));
+ credit_card->SetInfo(AutoFillType(CREDIT_CARD_NAME), s.ColumnString16(1));
credit_card->SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH),
- s.ColumnString16(3));
+ s.ColumnString16(2));
credit_card->SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR),
- s.ColumnString16(4));
- int encrypted_number_len = s.ColumnByteLength(5);
+ s.ColumnString16(3));
+ int encrypted_number_len = s.ColumnByteLength(4);
if (encrypted_number_len) {
encrypted_number->resize(encrypted_number_len);
- memcpy(&(*encrypted_number)[0], s.ColumnBlob(5), encrypted_number_len);
+ memcpy(&(*encrypted_number)[0], s.ColumnBlob(4), encrypted_number_len);
}
- *date_modified = s.ColumnInt64(6);
+ *date_modified = s.ColumnInt64(5);
}
} // namespace
@@ -1458,7 +1472,7 @@ TEST_F(WebDatabaseTest, AutoFillProfile) {
EXPECT_FALSE(s_billing.Step());
delete db_profile;
- // Update the 'Billing' profile.
+ // Update the 'Billing' profile, name only.
billing_profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Jane"));
Time pre_modification_time = Time::Now();
EXPECT_TRUE(db.UpdateAutoFillProfile(billing_profile));
@@ -1477,6 +1491,45 @@ TEST_F(WebDatabaseTest, AutoFillProfile) {
EXPECT_FALSE(s_billing_updated.Step());
delete db_profile;
+ // Update the 'Billing' profile.
+ billing_profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Janice"));
+ billing_profile.SetInfo(AutoFillType(NAME_MIDDLE), ASCIIToUTF16("C."));
+ billing_profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Joplin"));
+ billing_profile.SetInfo(AutoFillType(EMAIL_ADDRESS),
+ ASCIIToUTF16("jane@singer.com"));
+ billing_profile.SetInfo(AutoFillType(COMPANY_NAME), ASCIIToUTF16("Indy"));
+ billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE1),
+ ASCIIToUTF16("Open Road"));
+ billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE2),
+ ASCIIToUTF16("Route 66"));
+ billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_CITY),
+ ASCIIToUTF16("NFA"));
+ billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_STATE), ASCIIToUTF16("NY"));
+ billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_ZIP),
+ ASCIIToUTF16("10011"));
+ billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY),
+ ASCIIToUTF16("USA"));
+ billing_profile.SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER),
+ ASCIIToUTF16("18181230000"));
+ billing_profile.SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER),
+ ASCIIToUTF16("1915240000"));
+ Time pre_modification_time_2 = Time::Now();
+ EXPECT_TRUE(db.UpdateAutoFillProfile(billing_profile));
+ Time post_modification_time_2 = Time::Now();
+ ASSERT_TRUE(db.GetAutoFillProfile(billing_profile.guid(), &db_profile));
+ EXPECT_EQ(billing_profile, *db_profile);
+ sql::Statement s_billing_updated_2(db.db_.GetUniqueStatement(
+ "SELECT date_modified FROM autofill_profiles WHERE guid=?"));
+ s_billing_updated_2.BindString(0, billing_profile.guid());
+ ASSERT_TRUE(s_billing_updated_2);
+ ASSERT_TRUE(s_billing_updated_2.Step());
+ EXPECT_GE(s_billing_updated_2.ColumnInt64(0),
+ pre_modification_time_2.ToTimeT());
+ EXPECT_LE(s_billing_updated_2.ColumnInt64(0),
+ post_modification_time_2.ToTimeT());
+ EXPECT_FALSE(s_billing_updated_2.Step());
+ delete db_profile;
+
// Remove the 'Billing' profile.
EXPECT_TRUE(db.RemoveAutoFillProfile(billing_profile.guid()));
EXPECT_FALSE(db.GetAutoFillProfile(billing_profile.guid(), &db_profile));
@@ -1507,14 +1560,14 @@ TEST_F(WebDatabaseTest, CreditCard) {
ASSERT_TRUE(db.GetCreditCard(work_creditcard.guid(), &db_creditcard));
EXPECT_EQ(work_creditcard, *db_creditcard);
sql::Statement s_work(db.db_.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
+ "SELECT guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified "
"FROM credit_cards WHERE guid=?"));
s_work.BindString(0, work_creditcard.guid());
ASSERT_TRUE(s_work);
ASSERT_TRUE(s_work.Step());
- EXPECT_GE(s_work.ColumnInt64(6), pre_creation_time.ToTimeT());
- EXPECT_LE(s_work.ColumnInt64(6), post_creation_time.ToTimeT());
+ EXPECT_GE(s_work.ColumnInt64(5), pre_creation_time.ToTimeT());
+ EXPECT_LE(s_work.ColumnInt64(5), post_creation_time.ToTimeT());
EXPECT_FALSE(s_work.Step());
delete db_creditcard;
@@ -1535,14 +1588,14 @@ TEST_F(WebDatabaseTest, CreditCard) {
ASSERT_TRUE(db.GetCreditCard(target_creditcard.guid(), &db_creditcard));
EXPECT_EQ(target_creditcard, *db_creditcard);
sql::Statement s_target(db.db_.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
+ "SELECT guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified "
"FROM credit_cards WHERE guid=?"));
s_target.BindString(0, target_creditcard.guid());
ASSERT_TRUE(s_target);
ASSERT_TRUE(s_target.Step());
- EXPECT_GE(s_target.ColumnInt64(6), pre_creation_time.ToTimeT());
- EXPECT_LE(s_target.ColumnInt64(6), post_creation_time.ToTimeT());
+ EXPECT_GE(s_target.ColumnInt64(5), pre_creation_time.ToTimeT());
+ EXPECT_LE(s_target.ColumnInt64(5), post_creation_time.ToTimeT());
EXPECT_FALSE(s_target.Step());
delete db_creditcard;
@@ -1555,16 +1608,14 @@ TEST_F(WebDatabaseTest, CreditCard) {
ASSERT_TRUE(db.GetCreditCard(target_creditcard.guid(), &db_creditcard));
EXPECT_EQ(target_creditcard, *db_creditcard);
sql::Statement s_target_updated(db.db_.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
+ "SELECT guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified "
"FROM credit_cards WHERE guid=?"));
s_target_updated.BindString(0, target_creditcard.guid());
ASSERT_TRUE(s_target_updated);
ASSERT_TRUE(s_target_updated.Step());
- EXPECT_GE(s_target_updated.ColumnInt64(6),
- pre_modification_time.ToTimeT());
- EXPECT_LE(s_target_updated.ColumnInt64(6),
- post_modification_time.ToTimeT());
+ EXPECT_GE(s_target_updated.ColumnInt64(5), pre_modification_time.ToTimeT());
+ EXPECT_LE(s_target_updated.ColumnInt64(5), post_modification_time.ToTimeT());
EXPECT_FALSE(s_target_updated.Step());
delete db_creditcard;
@@ -2053,7 +2104,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 32;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 33;
void WebDatabaseMigrationTest::LoadDatabase(const FilePath& file) {
std::string contents;
@@ -2391,14 +2442,13 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringLabels) {
// Verify the credit card data is converted.
sql::Statement s(connection.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
+ "SELECT guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified "
"FROM credit_cards"));
ASSERT_TRUE(s.Step());
- EXPECT_EQ("label", s.ColumnString(1));
- EXPECT_EQ("Jack", s.ColumnString(2));
- EXPECT_EQ(2, s.ColumnInt(3));
- EXPECT_EQ(2012, s.ColumnInt(4));
+ EXPECT_EQ("Jack", s.ColumnString(1));
+ EXPECT_EQ(2, s.ColumnInt(2));
+ EXPECT_EQ(2012, s.ColumnInt(3));
// Column 5 is encrypted number blob.
// Column 6 is date_modified.
}
@@ -2467,14 +2517,13 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringIDs) {
// Verify the credit card data is converted.
sql::Statement s(connection.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, expiration_year, "
+ "SELECT guid, name_on_card, expiration_month, expiration_year, "
"card_number_encrypted, date_modified "
"FROM credit_cards"));
ASSERT_TRUE(s.Step());
- EXPECT_EQ("label", s.ColumnString(1));
- EXPECT_EQ("Jack", s.ColumnString(2));
- EXPECT_EQ(2, s.ColumnInt(3));
- EXPECT_EQ(2012, s.ColumnInt(4));
+ EXPECT_EQ("Jack", s.ColumnString(1));
+ EXPECT_EQ(2, s.ColumnInt(2));
+ EXPECT_EQ(2012, s.ColumnInt(3));
// Column 5 is encrypted credit card number blob.
// Column 6 is date_modified.
}
@@ -2739,24 +2788,35 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion31ToCurrent) {
// Verify data in the database after the migration.
sql::Statement s1(
connection.GetUniqueStatement(
- "SELECT guid, label, first_name, middle_name, last_name, "
- "email, company_name, address_line_1, address_line_2, city, state, "
- "zipcode, country, phone, fax, date_modified "
+ "SELECT guid, company_name, address_line_1, address_line_2, "
+ "city, state, zipcode, country, date_modified "
"FROM autofill_profiles"));
ASSERT_TRUE(s1.Step());
AutoFillProfile profile_a;
- string16 profile_label_a;
int64 profile_date_modified_a = 0;
- EXPECT_NO_FATAL_FAILURE(AutoFillProfile32FromStatement(
- s1, &profile_a, &profile_label_a, &profile_date_modified_a));
- EXPECT_EQ(profile, profile_a);
- EXPECT_EQ(profile_label, profile_label_a);
+ EXPECT_NO_FATAL_FAILURE(AutoFillProfile33FromStatement(
+ s1, &profile_a, &profile_date_modified_a));
+ EXPECT_EQ(profile.guid(), profile_a.guid());
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(COMPANY_NAME)),
+ profile_a.GetFieldText(AutoFillType(COMPANY_NAME)));
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)),
+ profile_a.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)));
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)),
+ profile_a.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)));
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(ADDRESS_HOME_CITY)),
+ profile_a.GetFieldText(AutoFillType(ADDRESS_HOME_CITY)));
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(ADDRESS_HOME_STATE)),
+ profile_a.GetFieldText(AutoFillType(ADDRESS_HOME_STATE)));
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)),
+ profile_a.GetFieldText(AutoFillType(ADDRESS_HOME_ZIP)));
+ EXPECT_EQ(profile.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY)),
+ profile_a.GetFieldText(AutoFillType(ADDRESS_HOME_COUNTRY)));
EXPECT_EQ(profile_date_modified, profile_date_modified_a);
sql::Statement s2(
connection.GetUniqueStatement(
- "SELECT guid, label, name_on_card, expiration_month, "
+ "SELECT guid, name_on_card, expiration_month, "
"expiration_year, card_number_encrypted, date_modified "
"FROM credit_cards"));
ASSERT_TRUE(s2.Step());
@@ -2767,7 +2827,6 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion31ToCurrent) {
int64 cc_date_modified_a = 0;
EXPECT_NO_FATAL_FAILURE(CreditCard32FromStatement(s2,
&credit_card_a,
- &cc_label_a,
&cc_number_encrypted_a,
&cc_date_modified_a));
EXPECT_EQ(credit_card, credit_card_a);
@@ -2776,3 +2835,299 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion31ToCurrent) {
EXPECT_EQ(cc_date_modified, cc_date_modified_a);
}
}
+
+// Factor |autofill_profiles| address information separately from name, email,
+// and phone.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) {
+ // Initialize the database.
+ ASSERT_NO_FATAL_FAILURE(
+ LoadDatabase(FilePath(FILE_PATH_LITERAL("version_32.sql"))));
+
+ // Verify pre-conditions. These are expectations for version 32 of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+ // Verify existence of columns we'll be changing.
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "label"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "first_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "middle_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "last_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "email"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "company_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "address_line_1"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "address_line_2"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "city"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "state"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "zipcode"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "country"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "phone"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "fax"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "date_modified"));
+
+ EXPECT_FALSE(connection.DoesTableExist("autofill_profile_names"));
+ EXPECT_FALSE(connection.DoesTableExist("autofill_profile_emails"));
+ EXPECT_FALSE(connection.DoesTableExist("autofill_profile_phones"));
+
+ EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "label"));
+ }
+
+ // Load the database via the WebDatabase class and migrate the database to
+ // the current version.
+ {
+ WebDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath()));
+ }
+
+ // Verify post-conditions. These are expectations for current version of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ // Verify changes to columns.
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "label"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "first_name"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles",
+ "middle_name"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "last_name"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "email"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "company_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "address_line_1"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "address_line_2"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "city"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "state"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "zipcode"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "country"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "phone"));
+ EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "fax"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles",
+ "date_modified"));
+
+ // New "names" table.
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names", "guid"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names",
+ "first_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names",
+ "middle_name"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_names",
+ "last_name"));
+
+ // New "emails" table.
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_emails", "guid"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_emails", "email"));
+
+ // New "phones" table.
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones", "guid"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones", "type"));
+ EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones",
+ "number"));
+
+ EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "label"));
+
+ // Verify data in the database after the migration.
+ sql::Statement s1(
+ connection.GetUniqueStatement(
+ "SELECT guid, company_name, address_line_1, address_line_2, "
+ "city, state, zipcode, country, date_modified "
+ "FROM autofill_profiles"));
+
+ // John Doe.
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("Doe Enterprises"), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("1 Main St"), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Apt 1"), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6));
+ EXPECT_EQ(ASCIIToUTF16("USA"), s1.ColumnString16(7));
+ EXPECT_EQ(1297882100UL, s1.ColumnInt64(8));
+
+ // John P. Doe.
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("589636FD-9037-3053-200C-80ABC97D7344", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("Doe Enterprises"), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("1 Main St"), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Apt 1"), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6));
+ EXPECT_EQ(ASCIIToUTF16("USA"), s1.ColumnString16(7));
+ EXPECT_EQ(1297882100UL, s1.ColumnInt64(8));
+
+ // Dave Smith.
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("2 Main Street"), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6));
+ EXPECT_EQ(ASCIIToUTF16("USA"), s1.ColumnString16(7));
+ EXPECT_EQ(1297882100UL, s1.ColumnInt64(8));
+
+ // Dave Smith (Part 2).
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("2 Main St"), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6));
+ EXPECT_EQ(ASCIIToUTF16("USA"), s1.ColumnString16(7));
+ EXPECT_EQ(1297882100UL, s1.ColumnInt64(8));
+
+ // Alfred E Newman.
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("584282AC-5D21-8D73-A2DB-4F892EF61F3F", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(6));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(7));
+ EXPECT_EQ(1297882100UL, s1.ColumnInt64(8));
+
+ // 3 Main St.
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("3 Main St"), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(6));
+ EXPECT_EQ(ASCIIToUTF16("USA"), s1.ColumnString16(7));
+ EXPECT_EQ(1297882100UL, s1.ColumnInt64(8));
+
+ // That should be all.
+ EXPECT_FALSE(s1.Step());
+
+ sql::Statement s2(
+ connection.GetUniqueStatement(
+ "SELECT guid, first_name, middle_name, last_name "
+ "FROM autofill_profile_names"));
+
+ // John Doe.
+ ASSERT_TRUE(s2.Step());
+ EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s2.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("John"), s2.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Doe"), s2.ColumnString16(3));
+
+ // John P. Doe.
+ ASSERT_TRUE(s2.Step());
+ EXPECT_EQ("589636FD-9037-3053-200C-80ABC97D7344", s2.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("John"), s2.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("P."), s2.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Doe"), s2.ColumnString16(3));
+
+ // Dave Smith.
+ ASSERT_TRUE(s2.Step());
+ EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s2.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("Dave"), s2.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Smith"), s2.ColumnString16(3));
+
+ // Dave Smith (Part 2).
+ ASSERT_TRUE(s2.Step());
+ EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s2.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("Dave"), s2.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Smith"), s2.ColumnString16(3));
+
+ // Alfred E Newman.
+ ASSERT_TRUE(s2.Step());
+ EXPECT_EQ("584282AC-5D21-8D73-A2DB-4F892EF61F3F", s2.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("Alfred"), s2.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("E"), s2.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Newman"), s2.ColumnString16(3));
+
+ // Note no name for 3 Main St.
+
+ // Should be all.
+ EXPECT_FALSE(s2.Step());
+
+ sql::Statement s3(
+ connection.GetUniqueStatement(
+ "SELECT guid, email "
+ "FROM autofill_profile_emails"));
+
+ // John Doe.
+ ASSERT_TRUE(s3.Step());
+ EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s3.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("john@doe.com"), s3.ColumnString16(1));
+
+ // John P. Doe.
+ ASSERT_TRUE(s3.Step());
+ EXPECT_EQ("589636FD-9037-3053-200C-80ABC97D7344", s3.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("john@doe.com"), s3.ColumnString16(1));
+
+ // Note no email for 2 Main Street.
+ // Note no email for 2 Main St.
+
+ // Alfred E Newman.
+ ASSERT_TRUE(s3.Step());
+ EXPECT_EQ("584282AC-5D21-8D73-A2DB-4F892EF61F3F", s3.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("a@e.com"), s3.ColumnString16(1));
+
+ // Note no email for 3 Main St.
+
+ // Should be all.
+ EXPECT_FALSE(s3.Step());
+
+ sql::Statement s4(
+ connection.GetUniqueStatement(
+ "SELECT guid, type, number "
+ "FROM autofill_profile_phones"));
+
+ // John Doe phone.
+ ASSERT_TRUE(s4.Step());
+ EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s4.ColumnString(0));
+ EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
+ EXPECT_EQ(ASCIIToUTF16("4151112222"), s4.ColumnString16(2));
+
+ // John Doe fax.
+ ASSERT_TRUE(s4.Step());
+ EXPECT_EQ("00580526-FF81-EE2A-0546-1AC593A32E2F", s4.ColumnString(0));
+ EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means phone.
+ EXPECT_EQ(ASCIIToUTF16("4153334444"), s4.ColumnString16(2));
+
+ // John P. Doe phone.
+ ASSERT_TRUE(s4.Step());
+ EXPECT_EQ("589636FD-9037-3053-200C-80ABC97D7344", s4.ColumnString(0));
+ EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone.
+ EXPECT_EQ(ASCIIToUTF16("4151112222"), s4.ColumnString16(2));
+
+ // John P. Doe fax.
+ ASSERT_TRUE(s4.Step());
+ EXPECT_EQ("589636FD-9037-3053-200C-80ABC97D7344", s4.ColumnString(0));
+ EXPECT_EQ(1, s4.ColumnInt(1)); // 1 means fax.
+ EXPECT_EQ(ASCIIToUTF16("4153334444"), s4.ColumnString16(2));
+
+ // Note no phone or fax for 2 Main Street.
+ // Note no phone or fax for 2 Main St.
+ // Note no phone or fax for Alfred E Newman.
+ // Note no phone or fax for 3 Main St.
+
+ // Should be all.
+ EXPECT_FALSE(s4.Step());
+ }
+}
diff --git a/chrome/test/data/web_database/version_32.sql b/chrome/test/data/web_database/version_32.sql
new file mode 100644
index 0000000..7030608
--- /dev/null
+++ b/chrome/test/data/web_database/version_32.sql
@@ -0,0 +1,33 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','32');
+INSERT INTO "meta" VALUES('last_compatible_version','32');
+INSERT INTO "meta" VALUES('Default Search Provider ID','2');
+INSERT INTO "meta" VALUES('Builtin Keyword Version','33');
+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,show_in_default_list INTEGER,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,autogenerate_keyword INTEGER DEFAULT 0,logo_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,instant_url VARCHAR);
+INSERT INTO "keywords" VALUES(2,'Google','google.com','http://www.google.com/favicon.ico','{google:baseURL}search?{google:RLZ}{google:acceptedSuggestion}{google:originalQueryForSuggestion}sourceid=chrome&ie={inputEncoding}&q={searchTerms}',1,1,'',0,0,'UTF-8','{google:baseSuggestURL}search?client=chrome&hl={language}&q={searchTerms}',1,1,6256,0,'{google:baseURL}webhp?{google:RLZ}sourceid=chrome-instant&ie={inputEncoding}&ion=1{searchTerms}&nord=1');
+INSERT INTO "keywords" VALUES(3,'Yahoo!','yahoo.com','http://search.yahoo.com/favicon.ico','http://search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}',1,1,'',0,0,'UTF-8','http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}',2,0,6273,0,'');
+INSERT INTO "keywords" VALUES(4,'Bing','bing.com','http://www.bing.com/s/wlflag.ico','http://www.bing.com/search?setmkt=en-US&q={searchTerms}',1,1,'',0,0,'UTF-8','http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}',3,0,6250,0,'');
+CREATE TABLE logins (origin_url VARCHAR NOT NULL, action_url VARCHAR, username_element VARCHAR, username_value VARCHAR, password_element VARCHAR, password_value BLOB, submit_element VARCHAR, signon_realm VARCHAR NOT NULL,ssl_valid INTEGER NOT NULL,preferred INTEGER NOT NULL,date_created INTEGER NOT NULL,blacklisted_by_user INTEGER NOT NULL,scheme INTEGER NOT NULL,UNIQUE (origin_url, username_element, username_value, password_element, submit_element, signon_realm));
+CREATE TABLE web_app_icons (url LONGVARCHAR,width int,height int,image BLOB, UNIQUE (url, width, height));
+CREATE TABLE web_apps (url LONGVARCHAR UNIQUE,has_all_images INTEGER NOT NULL);
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, pair_id INTEGER PRIMARY KEY, count INTEGER DEFAULT 1);
+CREATE TABLE autofill_dates ( pair_id INTEGER DEFAULT 0, date_created INTEGER DEFAULT 0);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, label VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR, email VARCHAR, company_name VARCHAR, address_line_1 VARCHAR, address_line_2 VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, country VARCHAR, phone VARCHAR, fax VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0);
+INSERT INTO "autofill_profiles" VALUES('00580526-FF81-EE2A-0546-1AC593A32E2F','John Doe, 1 Main St','John','','Doe','john@doe.com','Doe Enterprises','1 Main St','Apt 1','Los Altos','CA','94022','USA','4151112222','4153334444',1297882100);
+INSERT INTO "autofill_profiles" VALUES('589636FD-9037-3053-200C-80ABC97D7344','John P. Doe, 1 Main St','John','P.','Doe','john@doe.com','Doe Enterprises','1 Main St','Apt 1','Los Altos','CA','94022','USA','4151112222','4153334444',1297882100);
+INSERT INTO "autofill_profiles" VALUES('4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396','Dave Smith, 2 Main Street','Dave','','Smith','','','2 Main Street','','Los Altos','CA','94022','USA','','',1297882100);
+INSERT INTO "autofill_profiles" VALUES('722DF5C4-F74A-294A-46F0-31FFDED0D635','Dave Smith, 2 Main St','Dave','','Smith','','','2 Main St','','Los Altos','CA','94022','USA','','',1297882100);
+INSERT INTO "autofill_profiles" VALUES('584282AC-5D21-8D73-A2DB-4F892EF61F3F','Alfred E Newman, a@e.com','Alfred','E','Newman','a@e.com','','','','','','','','','',1297882100);
+INSERT INTO "autofill_profiles" VALUES('9E5FE298-62C7-83DF-6293-381BC589183F','3 Main St, Los Altos','','','','','','3 Main St','','Los Altos','CA','94022','USA','','',1297882100);
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, label VARCHAR, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE INDEX logins_signon ON logins (signon_realm);
+CREATE INDEX web_apps_url_index ON web_apps (url);
+CREATE INDEX autofill_name ON autofill (name);
+CREATE INDEX autofill_name_value_lower ON autofill (name, value_lower);
+CREATE INDEX autofill_dates_pair_id ON autofill_dates (pair_id);
+CREATE INDEX autofill_profiles_label_index ON autofill_profiles (label);
+CREATE INDEX credit_cards_label_index ON credit_cards (label);
+COMMIT;