diff options
13 files changed, 685 insertions, 250 deletions
diff --git a/components/autofill/core/browser/address.cc b/components/autofill/core/browser/address.cc index 2d326ce..c0bb1b5 100644 --- a/components/autofill/core/browser/address.cc +++ b/components/autofill/core/browser/address.cc @@ -31,10 +31,12 @@ Address& Address::operator=(const Address& address) { line1_ = address.line1_; line2_ = address.line2_; + dependent_locality_ = address.dependent_locality_; city_ = address.city_; state_ = address.state_; country_code_ = address.country_code_; zip_code_ = address.zip_code_; + sorting_code_ = address.sorting_code_; return *this; } @@ -47,6 +49,9 @@ base::string16 Address::GetRawInfo(ServerFieldType type) const { case ADDRESS_HOME_LINE2: return line2_; + case ADDRESS_HOME_DEPENDENT_LOCALITY: + return dependent_locality_; + case ADDRESS_HOME_CITY: return city_; @@ -56,6 +61,9 @@ base::string16 Address::GetRawInfo(ServerFieldType type) const { case ADDRESS_HOME_ZIP: return zip_code_; + case ADDRESS_HOME_SORTING_CODE: + return sorting_code_; + case ADDRESS_HOME_COUNTRY: return ASCIIToUTF16(country_code_); @@ -66,11 +74,6 @@ base::string16 Address::GetRawInfo(ServerFieldType type) const { return address; } - // TODO(isherman): Add support for these field types in support of i18n. - case ADDRESS_HOME_SORTING_CODE: - case ADDRESS_HOME_DEPENDENT_LOCALITY: - return base::string16(); - default: NOTREACHED(); return base::string16(); @@ -88,6 +91,10 @@ void Address::SetRawInfo(ServerFieldType type, const base::string16& value) { line2_ = value; break; + case ADDRESS_HOME_DEPENDENT_LOCALITY: + dependent_locality_ = value; + break; + case ADDRESS_HOME_CITY: city_ = value; break; @@ -106,6 +113,10 @@ void Address::SetRawInfo(ServerFieldType type, const base::string16& value) { zip_code_ = value; break; + case ADDRESS_HOME_SORTING_CODE: + sorting_code_ = value; + break; + case ADDRESS_HOME_STREET_ADDRESS: { // Clear any stale values, which might or might not get overwritten below. line1_.clear(); @@ -122,11 +133,6 @@ void Address::SetRawInfo(ServerFieldType type, const base::string16& value) { break; } - // TODO(isherman): Add support for these field types in support of i18n. - case ADDRESS_HOME_SORTING_CODE: - case ADDRESS_HOME_DEPENDENT_LOCALITY: - break; - default: NOTREACHED(); } @@ -191,9 +197,12 @@ void Address::GetMatchingTypes(const base::string16& text, void Address::GetSupportedTypes(ServerFieldTypeSet* supported_types) const { supported_types->insert(ADDRESS_HOME_LINE1); supported_types->insert(ADDRESS_HOME_LINE2); + supported_types->insert(ADDRESS_HOME_STREET_ADDRESS); + supported_types->insert(ADDRESS_HOME_DEPENDENT_LOCALITY); supported_types->insert(ADDRESS_HOME_CITY); supported_types->insert(ADDRESS_HOME_STATE); supported_types->insert(ADDRESS_HOME_ZIP); + supported_types->insert(ADDRESS_HOME_SORTING_CODE); supported_types->insert(ADDRESS_HOME_COUNTRY); } diff --git a/components/autofill/core/browser/address.h b/components/autofill/core/browser/address.h index f62c32e..8ad2751 100644 --- a/components/autofill/core/browser/address.h +++ b/components/autofill/core/browser/address.h @@ -45,9 +45,14 @@ class Address : public FormGroup { // The address, sans country info. base::string16 line1_; base::string16 line2_; + // A subdivision of city, e.g. inner-city district or suburb. + base::string16 dependent_locality_; base::string16 city_; base::string16 state_; base::string16 zip_code_; + // Similar to a ZIP code, but used by entities that might not be + // geographically contiguous. The canonical example is CEDEX in France. + base::string16 sorting_code_; // The ISO 3166 2-letter country code, or an empty string if there is no // country data specified for this address. diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index e7b5547..22ec8be 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc @@ -145,7 +145,8 @@ void DeterminePossibleFieldTypesForUpload( if (field->form_control_type == "password") { matching_types.insert(autofill::PASSWORD); } else { - base::string16 value = CollapseWhitespace(field->value, false); + base::string16 value; + TrimWhitespace(field->value, TRIM_ALL, &value); for (std::vector<AutofillProfile>::const_iterator it = profiles.begin(); it != profiles.end(); ++it) { it->GetMatchingTypes(value, app_locale, &matching_types); diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc index 29f85772..520eff9 100644 --- a/components/autofill/core/browser/autofill_profile.cc +++ b/components/autofill/core/browser/autofill_profile.cc @@ -135,8 +135,7 @@ void CopyValuesToItems(ServerFieldType type, const T& prototype) { form_group_items->resize(values.size(), prototype); for (size_t i = 0; i < form_group_items->size(); ++i) { - (*form_group_items)[i].SetRawInfo(type, - CollapseWhitespace(values[i], false)); + (*form_group_items)[i].SetRawInfo(type, values[i]); } // Must have at least one (possibly empty) element. if (form_group_items->empty()) @@ -285,7 +284,7 @@ void AutofillProfile::SetRawInfo(ServerFieldType type, const base::string16& value) { FormGroup* form_group = MutableFormGroupForType(AutofillType(type)); if (form_group) - form_group->SetRawInfo(type, CollapseWhitespace(value, false)); + form_group->SetRawInfo(type, value); } base::string16 AutofillProfile::GetInfo(const AutofillType& type, @@ -304,8 +303,9 @@ bool AutofillProfile::SetInfo(const AutofillType& type, if (!form_group) return false; - return - form_group->SetInfo(type, CollapseWhitespace(value, false), app_locale); + base::string16 trimmed_value; + TrimWhitespace(value, TRIM_ALL, &trimmed_value); + return form_group->SetInfo(type, trimmed_value, app_locale); } base::string16 AutofillProfile::GetInfoForVariant( @@ -400,13 +400,17 @@ bool AutofillProfile::IsPresentButInvalid(ServerFieldType type) const { int AutofillProfile::Compare(const AutofillProfile& profile) const { - const ServerFieldType single_value_types[] = { COMPANY_NAME, - ADDRESS_HOME_LINE1, - ADDRESS_HOME_LINE2, - ADDRESS_HOME_CITY, - ADDRESS_HOME_STATE, - ADDRESS_HOME_ZIP, - ADDRESS_HOME_COUNTRY }; + const ServerFieldType single_value_types[] = { + COMPANY_NAME, + ADDRESS_HOME_LINE1, + ADDRESS_HOME_LINE2, + ADDRESS_HOME_DEPENDENT_LOCALITY, + ADDRESS_HOME_CITY, + ADDRESS_HOME_STATE, + ADDRESS_HOME_ZIP, + ADDRESS_HOME_SORTING_CODE, + ADDRESS_HOME_COUNTRY, + }; for (size_t i = 0; i < arraysize(single_value_types); ++i) { int comparison = GetRawInfo(single_value_types[i]).compare( @@ -461,11 +465,12 @@ bool AutofillProfile::IsSubsetOf(const AutofillProfile& profile, for (ServerFieldTypeSet::const_iterator it = types.begin(); it != types.end(); ++it) { - if (*it == NAME_FULL) { + if (*it == NAME_FULL || *it == ADDRESS_HOME_STREET_ADDRESS) { // Ignore the compound "full name" field type. We are only interested in // comparing the constituent parts. For example, if |this| has a middle // name saved, but |profile| lacks one, |profile| could still be a subset - // of |this|. + // of |this|. Likewise, ignore the compound "street address" type, as we + // are only interested in matching line-by-line. continue; } else if (AutofillType(*it).group() == PHONE_HOME) { // Phone numbers should be canonicalized prior to being compared. @@ -500,6 +505,12 @@ void AutofillProfile::OverwriteWithOrAddTo(const AutofillProfile& profile, // first name, last name). CollapseCompoundFieldTypes(&field_types); + // TODO(isherman): Revisit this decision in the context of i18n and storing + // full addresses rather than storing 1-to-2 lines of an address. + // For addresses, do the opposite: transfer individual address lines, rather + // than full addresses. + field_types.erase(ADDRESS_HOME_STREET_ADDRESS); + for (ServerFieldTypeSet::const_iterator iter = field_types.begin(); iter != field_types.end(); ++iter) { if (AutofillProfile::SupportsMultiValue(*iter)) { @@ -818,12 +829,16 @@ std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) { << " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_LINE2)) << " " + << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)) + << " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_CITY)) << " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_STATE)) << " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_ZIP)) << " " + << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)) + << " " << UTF16ToUTF8(profile.GetRawInfo(ADDRESS_HOME_COUNTRY)) << " " << UTF16ToUTF8(MultiString(profile, PHONE_HOME_WHOLE_NUMBER)); diff --git a/components/autofill/core/browser/autofill_profile_unittest.cc b/components/autofill/core/browser/autofill_profile_unittest.cc index 6ae267d..194dc3a 100644 --- a/components/autofill/core/browser/autofill_profile_unittest.cc +++ b/components/autofill/core/browser/autofill_profile_unittest.cc @@ -807,4 +807,45 @@ TEST(AutofillProfileTest, IsPresentButInvalid) { EXPECT_FALSE(profile.IsPresentButInvalid(PHONE_HOME_WHOLE_NUMBER)); } +TEST(AutofillProfileTest, SetRawInfoPreservesLineBreaks) { + AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/"); + + profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, + ASCIIToUTF16("123 Super St.\n" + "Apt. #42")); + EXPECT_EQ(ASCIIToUTF16("123 Super St.\n" + "Apt. #42"), + profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); +} + +TEST(AutofillProfileTest, SetInfoPreservesLineBreaks) { + AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/"); + + profile.SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), + ASCIIToUTF16("123 Super St.\n" + "Apt. #42"), + "en-US"); + EXPECT_EQ(ASCIIToUTF16("123 Super St.\n" + "Apt. #42"), + profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); +} + +TEST(AutofillProfileTest, SetRawInfoDoesntTrimWhitespace) { + AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/"); + + profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("\tuser@example.com ")); + EXPECT_EQ(ASCIIToUTF16("\tuser@example.com "), + profile.GetRawInfo(EMAIL_ADDRESS)); +} + +TEST(AutofillProfileTest, SetInfoTrimsWhitespace) { + AutofillProfile profile(base::GenerateGUID(), "https://www.example.com/"); + + profile.SetInfo(AutofillType(EMAIL_ADDRESS), + ASCIIToUTF16("\tuser@example.com "), + "en-US"); + EXPECT_EQ(ASCIIToUTF16("user@example.com"), + profile.GetRawInfo(EMAIL_ADDRESS)); +} + } // namespace autofill diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 284a09f..28d92d4 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc @@ -248,7 +248,8 @@ bool PersonalDataManager::ImportFormData( for (size_t i = 0; i < form.field_count(); ++i) { const AutofillField* field = form.field(i); - base::string16 value = CollapseWhitespace(field->value, false); + base::string16 value; + TrimWhitespace(field->value, TRIM_ALL, &value); // If we don't know the type of the field, or the user hasn't entered any // information into the field, then skip it. diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index d45cfd8..4223b60c 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc @@ -879,6 +879,53 @@ TEST_F(PersonalDataManagerTest, ImportPhoneNumberSplitAcrossMultipleFields) { EXPECT_EQ(0, expected.Compare(*results[0])); } +TEST_F(PersonalDataManagerTest, ImportFormDataMultilineAddress) { + FormData form; + FormFieldData field; + test::CreateTestFormField( + "First name:", "first_name", "George", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField( + "Last name:", "last_name", "Washington", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField( + "Email:", "email", "theprez@gmail.com", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField( + "Address:", + "street_address", + "21 Laussat St\n" + "Apt. #42", + "textarea", + &field); + form.fields.push_back(field); + test::CreateTestFormField("City:", "city", "San Francisco", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("State:", "state", "California", "text", &field); + form.fields.push_back(field); + test::CreateTestFormField("Zip:", "zip", "94102", "text", &field); + form.fields.push_back(field); + FormStructure form_structure(form); + form_structure.DetermineHeuristicTypes(TestAutofillMetrics()); + scoped_ptr<CreditCard> imported_credit_card; + EXPECT_TRUE(personal_data_->ImportFormData(form_structure, + &imported_credit_card)); + ASSERT_FALSE(imported_credit_card); + + // Verify that the web database has been updated and the notification sent. + EXPECT_CALL(personal_data_observer_, + OnPersonalDataChanged()).WillOnce(QuitUIMessageLoop()); + base::MessageLoop::current()->Run(); + + AutofillProfile expected(base::GenerateGUID(), "https://www.example.com"); + test::SetProfileInfo(&expected, "George", NULL, + "Washington", "theprez@gmail.com", NULL, "21 Laussat St", "Apt. #42", + "San Francisco", "California", "94102", NULL, NULL); + const std::vector<AutofillProfile*>& results = personal_data_->GetProfiles(); + ASSERT_EQ(1U, results.size()); + EXPECT_EQ(0, expected.Compare(*results[0])); +} + TEST_F(PersonalDataManagerTest, SetUniqueCreditCardLabels) { CreditCard credit_card0(base::GenerateGUID(), "https://www.example.com"); credit_card0.SetRawInfo(CREDIT_CARD_NAME, ASCIIToUTF16("John")); @@ -2164,12 +2211,13 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { base::MessageLoop::current()->Run(); personal_data_->GetNonEmptyTypes(&non_empty_types); - EXPECT_EQ(14U, non_empty_types.size()); + EXPECT_EQ(15U, non_empty_types.size()); EXPECT_TRUE(non_empty_types.count(NAME_FIRST)); EXPECT_TRUE(non_empty_types.count(NAME_LAST)); EXPECT_TRUE(non_empty_types.count(NAME_FULL)); EXPECT_TRUE(non_empty_types.count(EMAIL_ADDRESS)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1)); + EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP)); @@ -2202,7 +2250,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { base::MessageLoop::current()->Run(); personal_data_->GetNonEmptyTypes(&non_empty_types); - EXPECT_EQ(18U, non_empty_types.size()); + EXPECT_EQ(19U, non_empty_types.size()); EXPECT_TRUE(non_empty_types.count(NAME_FIRST)); EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE)); EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE_INITIAL)); @@ -2212,6 +2260,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { EXPECT_TRUE(non_empty_types.count(COMPANY_NAME)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE2)); + EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP)); @@ -2235,7 +2284,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { base::MessageLoop::current()->Run(); personal_data_->GetNonEmptyTypes(&non_empty_types); - EXPECT_EQ(26U, non_empty_types.size()); + EXPECT_EQ(27U, non_empty_types.size()); EXPECT_TRUE(non_empty_types.count(NAME_FIRST)); EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE)); EXPECT_TRUE(non_empty_types.count(NAME_MIDDLE_INITIAL)); @@ -2245,6 +2294,7 @@ TEST_F(PersonalDataManagerTest, GetNonEmptyTypes) { EXPECT_TRUE(non_empty_types.count(COMPANY_NAME)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE1)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_LINE2)); + EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STREET_ADDRESS)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_CITY)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_STATE)); EXPECT_TRUE(non_empty_types.count(ADDRESS_HOME_ZIP)); diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index 1f61bb3..a57ac0d 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc @@ -15,6 +15,7 @@ #include "base/i18n/case_conversion.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/tuple.h" #include "components/autofill/core/browser/autofill_country.h" @@ -40,14 +41,16 @@ namespace { typedef std::vector<Tuple3<int64, base::string16, base::string16> > AutofillElementList; -// TODO(dhollowa): Find a common place for this. It is duplicated in -// personal_data_manager.cc. template<typename T> T* address_of(T& v) { return &v; } -base::string16 LimitDataSize(const base::string16& data) { +// Returns the |data_model|'s value corresponding to the |type|, trimmed to the +// maximum length that can be stored in a column of the Autofill database. +base::string16 GetInfo(const AutofillDataModel& data_model, + ServerFieldType type) { + base::string16 data = data_model.GetRawInfo(type); if (data.size() > AutofillTable::kMaxDataLength) return data.substr(0, AutofillTable::kMaxDataLength); @@ -55,93 +58,93 @@ base::string16 LimitDataSize(const base::string16& data) { } void BindAutofillProfileToStatement(const AutofillProfile& profile, - sql::Statement* s, - const std::string& app_locale) { + sql::Statement* s) { DCHECK(base::IsValidGUID(profile.guid())); - s->BindString(0, profile.guid()); - - base::string16 text = profile.GetRawInfo(COMPANY_NAME); - s->BindString16(1, LimitDataSize(text)); - text = profile.GetRawInfo(ADDRESS_HOME_LINE1); - s->BindString16(2, LimitDataSize(text)); - text = profile.GetRawInfo(ADDRESS_HOME_LINE2); - s->BindString16(3, LimitDataSize(text)); - text = profile.GetRawInfo(ADDRESS_HOME_CITY); - s->BindString16(4, LimitDataSize(text)); - text = profile.GetRawInfo(ADDRESS_HOME_STATE); - s->BindString16(5, LimitDataSize(text)); - text = profile.GetRawInfo(ADDRESS_HOME_ZIP); - s->BindString16(6, LimitDataSize(text)); - text = profile.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), app_locale); - s->BindString16(7, LimitDataSize(text)); - text = profile.GetRawInfo(ADDRESS_HOME_COUNTRY); - s->BindString16(8, LimitDataSize(text)); - s->BindInt64(9, Time::Now().ToTimeT()); - s->BindString(10, profile.origin()); -} - -AutofillProfile* AutofillProfileFromStatement(const sql::Statement& s, - const std::string& app_locale) { - AutofillProfile* profile = new AutofillProfile; - profile->set_guid(s.ColumnString(0)); + int index = 0; + s->BindString(index++, profile.guid()); + + s->BindString16(index++, GetInfo(profile, COMPANY_NAME)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_STREET_ADDRESS)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_DEPENDENT_LOCALITY)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_CITY)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_STATE)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_ZIP)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_SORTING_CODE)); + s->BindString16(index++, GetInfo(profile, ADDRESS_HOME_COUNTRY)); + s->BindInt64(index++, Time::Now().ToTimeT()); + s->BindString(index++, profile.origin()); +} + +scoped_ptr<AutofillProfile> AutofillProfileFromStatement( + const sql::Statement& s) { + scoped_ptr<AutofillProfile> profile(new AutofillProfile); + int index = 0; + profile->set_guid(s.ColumnString(index++)); DCHECK(base::IsValidGUID(profile->guid())); - profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(1)); - profile->SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); - profile->SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); - profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); - profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); - profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); - // Intentionally skip column 7, which stores the localized country name. - profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(8)); + profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++)); + 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++)); // Intentionally skip column 9, which stores the profile's modification date. - profile->set_origin(s.ColumnString(10)); + index++; + profile->set_origin(s.ColumnString(index++)); - return profile; + return profile.Pass(); } void BindCreditCardToStatement(const CreditCard& credit_card, sql::Statement* s) { DCHECK(base::IsValidGUID(credit_card.guid())); - s->BindString(0, credit_card.guid()); - - base::string16 text = credit_card.GetRawInfo(CREDIT_CARD_NAME); - s->BindString16(1, LimitDataSize(text)); - text = credit_card.GetRawInfo(CREDIT_CARD_EXP_MONTH); - s->BindString16(2, LimitDataSize(text)); - text = credit_card.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR); - s->BindString16(3, LimitDataSize(text)); - text = credit_card.GetRawInfo(CREDIT_CARD_NUMBER); + int index = 0; + s->BindString(index++, credit_card.guid()); + + s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_NAME)); + s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_MONTH)); + s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_4_DIGIT_YEAR)); + std::string encrypted_data; - Encryptor::EncryptString16(text, &encrypted_data); - s->BindBlob(4, encrypted_data.data(), + Encryptor::EncryptString16(credit_card.GetRawInfo(CREDIT_CARD_NUMBER), + &encrypted_data); + s->BindBlob(index++, encrypted_data.data(), static_cast<int>(encrypted_data.length())); - s->BindInt64(5, Time::Now().ToTimeT()); - s->BindString(6, credit_card.origin()); + + s->BindInt64(index++, Time::Now().ToTimeT()); + s->BindString(index++, credit_card.origin()); } -CreditCard* CreditCardFromStatement(const sql::Statement& s) { - CreditCard* credit_card = new CreditCard; +scoped_ptr<CreditCard> CreditCardFromStatement(const sql::Statement& s) { + scoped_ptr<CreditCard> credit_card(new CreditCard); - credit_card->set_guid(s.ColumnString(0)); + int index = 0; + credit_card->set_guid(s.ColumnString(index++)); DCHECK(base::IsValidGUID(credit_card->guid())); - credit_card->SetRawInfo(CREDIT_CARD_NAME, s.ColumnString16(1)); - credit_card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(2)); - credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, s.ColumnString16(3)); - int encrypted_number_len = s.ColumnByteLength(4); + credit_card->SetRawInfo(CREDIT_CARD_NAME, s.ColumnString16(index++)); + credit_card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(index++)); + credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, + s.ColumnString16(index++)); + int encrypted_number_len = s.ColumnByteLength(index); base::string16 credit_card_number; if (encrypted_number_len) { std::string encrypted_number; encrypted_number.resize(encrypted_number_len); - memcpy(&encrypted_number[0], s.ColumnBlob(4), encrypted_number_len); + memcpy(&encrypted_number[0], s.ColumnBlob(index++), encrypted_number_len); Encryptor::DecryptString16(encrypted_number, &credit_card_number); + } else { + index++; } credit_card->SetRawInfo(CREDIT_CARD_NUMBER, credit_card_number); // Intentionally skip column 5, which stores the modification date. - credit_card->set_origin(s.ColumnString(6)); + index++; + credit_card->set_origin(s.ColumnString(index++)); - return credit_card; + return credit_card.Pass(); } bool AddAutofillProfileNamesToProfile(sql::Connection* db, @@ -199,13 +202,10 @@ bool AddAutofillProfileEmailsToProfile(sql::Connection* db, bool AddAutofillProfilePhonesToProfile(sql::Connection* db, AutofillProfile* profile) { sql::Statement s(db->GetUniqueStatement( - "SELECT guid, type, number " + "SELECT guid, number " "FROM autofill_profile_phones " - "WHERE guid=? AND type=?")); - - // Value used to be either [(0, phone), (1, fax)] but fax has been removed. + "WHERE guid=?")); s.BindString(0, profile->guid()); - s.BindInt(1, 0); if (!s.is_valid()) return false; @@ -213,7 +213,7 @@ bool AddAutofillProfilePhonesToProfile(sql::Connection* db, std::vector<base::string16> numbers; while (s.Step()) { DCHECK_EQ(profile->guid(), s.ColumnString(0)); - numbers.push_back(s.ColumnString16(2)); + numbers.push_back(s.ColumnString16(1)); } if (!s.Succeeded()) return false; @@ -280,12 +280,10 @@ bool AddAutofillProfilePhones(const AutofillProfile& profile, // Add the new number. sql::Statement s(db->GetUniqueStatement( "INSERT INTO autofill_profile_phones" - " (guid, type, number) " - "VALUES (?,?,?)")); + " (guid, number) " + "VALUES (?,?)")); s.BindString(0, profile.guid()); - // Value used to be either [(0, phone), (1, fax)] but fax has been removed. - s.BindInt(1, 0); - s.BindString16(2, numbers[i]); + s.BindString16(1, numbers[i]); if (!s.Run()) return false; @@ -422,6 +420,9 @@ bool AutofillTable::MigrateToVersion(int version, // worked correctly for users with existing 'origin' columns, but failed // to create these columns for new users. return MigrateToVersion51AddOriginColumn(); + case 54: + *update_compatible_version = true; + return MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields(); } return true; } @@ -964,10 +965,10 @@ bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) { sql::Statement s(db_->GetUniqueStatement( "INSERT INTO autofill_profiles" - "(guid, company_name, address_line_1, address_line_2, city, state," - " zipcode, country, country_code, date_modified, origin)" + "(guid, company_name, street_address, dependent_locality, city, state," + " zipcode, sorting_code, country_code, date_modified, origin)" "VALUES (?,?,?,?,?,?,?,?,?,?,?)")); - BindAutofillProfileToStatement(profile, &s, app_locale_); + BindAutofillProfileToStatement(profile, &s); if (!s.Run()) return false; @@ -980,8 +981,8 @@ bool AutofillTable::GetAutofillProfile(const std::string& guid, DCHECK(base::IsValidGUID(guid)); DCHECK(profile); sql::Statement s(db_->GetUniqueStatement( - "SELECT guid, company_name, address_line_1, address_line_2, city, state," - " zipcode, country, country_code, date_modified, origin " + "SELECT guid, company_name, street_address, dependent_locality, city," + " state, zipcode, sorting_code, country_code, date_modified, origin " "FROM autofill_profiles " "WHERE guid=?")); s.BindString(0, guid); @@ -989,7 +990,7 @@ bool AutofillTable::GetAutofillProfile(const std::string& guid, if (!s.Step()) return false; - scoped_ptr<AutofillProfile> p(AutofillProfileFromStatement(s, app_locale_)); + scoped_ptr<AutofillProfile> p = AutofillProfileFromStatement(s); // Get associated name info. AddAutofillProfileNamesToProfile(db_, p.get()); @@ -1044,11 +1045,11 @@ bool AutofillTable::UpdateAutofillProfile(const AutofillProfile& profile) { sql::Statement s(db_->GetUniqueStatement( "UPDATE autofill_profiles " - "SET guid=?, company_name=?, address_line_1=?, address_line_2=?, " - " city=?, state=?, zipcode=?, country=?, country_code=?, " + "SET guid=?, company_name=?, street_address=?, dependent_locality=?, " + " city=?, state=?, zipcode=?, sorting_code=?, country_code=?, " " date_modified=?, origin=? " "WHERE guid=?")); - BindAutofillProfileToStatement(profile, &s, app_locale_); + BindAutofillProfileToStatement(profile, &s); s.BindString(11, profile.guid()); bool result = s.Run(); @@ -1139,7 +1140,7 @@ bool AutofillTable::GetCreditCard(const std::string& guid, if (!s.Step()) return false; - *credit_card = CreditCardFromStatement(s); + *credit_card = CreditCardFromStatement(s).release(); return true; } @@ -1457,12 +1458,12 @@ bool AutofillTable::InitProfilesTable() { if (!db_->Execute("CREATE TABLE autofill_profiles ( " "guid VARCHAR PRIMARY KEY, " "company_name VARCHAR, " - "address_line_1 VARCHAR, " - "address_line_2 VARCHAR, " + "street_address VARCHAR, " + "dependent_locality VARCHAR, " "city VARCHAR, " "state VARCHAR, " "zipcode VARCHAR, " - "country VARCHAR, " + "sorting_code VARCHAR, " "country_code VARCHAR, " "date_modified INTEGER NOT NULL DEFAULT 0, " "origin VARCHAR DEFAULT '')")) { @@ -1503,7 +1504,6 @@ bool AutofillTable::InitProfilePhonesTable() { 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; @@ -1915,38 +1915,40 @@ bool AutofillTable::MigrateToVersion33ProfilesBasedOnFirstName() { while (s.Step()) { AutofillProfile profile; - profile.set_guid(s.ColumnString(0)); + int index = 0; + profile.set_guid(s.ColumnString(index++)); DCHECK(base::IsValidGUID(profile.guid())); - profile.SetRawInfo(NAME_FIRST, s.ColumnString16(1)); - profile.SetRawInfo(NAME_MIDDLE, s.ColumnString16(2)); - profile.SetRawInfo(NAME_LAST, s.ColumnString16(3)); - profile.SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(4)); - profile.SetRawInfo(COMPANY_NAME, s.ColumnString16(5)); - profile.SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(6)); - profile.SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(7)); - profile.SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(8)); - profile.SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(9)); - profile.SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(10)); - profile.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), s.ColumnString16(11), - app_locale_); - profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(12)); - int64 date_modified = s.ColumnInt64(13); + profile.SetRawInfo(NAME_FIRST, s.ColumnString16(index++)); + profile.SetRawInfo(NAME_MIDDLE, s.ColumnString16(index++)); + profile.SetRawInfo(NAME_LAST, s.ColumnString16(index++)); + profile.SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(index++)); + profile.SetRawInfo(COMPANY_NAME, s.ColumnString16(index++)); + profile.SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(index++)); + profile.SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(index++)); + profile.SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++)); + profile.SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++)); + profile.SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++)); + profile.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), + s.ColumnString16(index++), app_locale_); + profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(index++)); + int64 date_modified = s.ColumnInt64(index++); 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 (?,?,?,?,?,?,?,?,?)")); - s_insert.BindString(0, profile.guid()); - s_insert.BindString16(1, profile.GetRawInfo(COMPANY_NAME)); - s_insert.BindString16(2, profile.GetRawInfo(ADDRESS_HOME_LINE1)); - s_insert.BindString16(3, profile.GetRawInfo(ADDRESS_HOME_LINE2)); - s_insert.BindString16(4, profile.GetRawInfo(ADDRESS_HOME_CITY)); - s_insert.BindString16(5, profile.GetRawInfo(ADDRESS_HOME_STATE)); - s_insert.BindString16(6, profile.GetRawInfo(ADDRESS_HOME_ZIP)); - s_insert.BindString16(7, profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); - s_insert.BindInt64(8, date_modified); + index = 0; + s_insert.BindString(index++, profile.guid()); + s_insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME)); + s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_LINE1)); + s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_LINE2)); + s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY)); + s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE)); + s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP)); + s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY)); + s_insert.BindInt64(index++, date_modified); if (!s_insert.Run()) return false; @@ -2069,20 +2071,23 @@ bool AutofillTable::MigrateToVersion37MergeAndCullOlderProfiles() { return false; scoped_ptr<AutofillProfile> profile(new AutofillProfile); - profile->set_guid(s.ColumnString(0)); + int index = 0; + profile->set_guid(s.ColumnString(index++)); DCHECK(base::IsValidGUID(profile->guid())); - profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(1)); - profile->SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(2)); - profile->SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(3)); - profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(4)); - profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(5)); - profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(6)); + profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++)); + profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++)); // Intentionally skip column 7, which stores the localized country name. - profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(8)); + index++; + profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++)); // Intentionally skip column 9, which stores the profile's modification // date. - profile->set_origin(s.ColumnString(10)); + index++; + profile->set_origin(s.ColumnString(index++)); // Get associated name info. AddAutofillProfileNamesToProfile(db_, profile.get()); @@ -2138,24 +2143,17 @@ bool AutofillTable::MigrateToVersion37MergeAndCullOlderProfiles() { "(guid, company_name, address_line_1, address_line_2, city, state," " zipcode, country, country_code, date_modified)" "VALUES (?,?,?,?,?,?,?,?,?,?)")); - s.BindString(0, iter->guid()); - base::string16 text = iter->GetRawInfo(COMPANY_NAME); - s.BindString16(1, LimitDataSize(text)); - text = iter->GetRawInfo(ADDRESS_HOME_LINE1); - s.BindString16(2, LimitDataSize(text)); - text = iter->GetRawInfo(ADDRESS_HOME_LINE2); - s.BindString16(3, LimitDataSize(text)); - text = iter->GetRawInfo(ADDRESS_HOME_CITY); - s.BindString16(4, LimitDataSize(text)); - text = iter->GetRawInfo(ADDRESS_HOME_STATE); - s.BindString16(5, LimitDataSize(text)); - text = iter->GetRawInfo(ADDRESS_HOME_ZIP); - s.BindString16(6, LimitDataSize(text)); - text = iter->GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), app_locale_); - s.BindString16(7, LimitDataSize(text)); - text = iter->GetRawInfo(ADDRESS_HOME_COUNTRY); - s.BindString16(8, LimitDataSize(text)); - s.BindInt64(9, date_item->second); + int index = 0; + s.BindString(index++, iter->guid()); + s.BindString16(index++, GetInfo(*iter, COMPANY_NAME)); + s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_LINE1)); + s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_LINE2)); + s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_CITY)); + s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_STATE)); + s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_ZIP)); + s.BindString16(index++, base::string16()); // This column is deprecated. + s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_COUNTRY)); + s.BindInt64(index++, date_item->second); if (!s.Run()) return false; @@ -2189,4 +2187,108 @@ bool AutofillTable::MigrateToVersion51AddOriginColumn() { return transaction.Commit(); } +bool AutofillTable::MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields() { + sql::Transaction transaction(db_); + if (!transaction.Begin()) + return false; + + // Test the existence of the |address_line_1| column as an indication that a + // migration is needed. It is possible that the new |autofill_profile_phones| + // schema is in place because the table was newly created when migrating from + // a pre-version-23 database. + if (db_->DoesColumnExist("autofill_profiles", "address_line_1")) { + // Create a temporary copy of the autofill_profiles table in the (newer) + // version 54 format. This table + // (a) adds columns for street_address, dependent_locality, and + // sorting_code, + // (b) removes the address_line_1 and address_line_2 columns, which are + // replaced by the street_address column, and + // (c) removes the country column, which was long deprecated. + if (db_->DoesTableExist("autofill_profiles_temp") || + !db_->Execute("CREATE TABLE autofill_profiles_temp ( " + "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 '')")) { + return false; + } + + // Copy over the data from the autofill_profiles table, taking care to merge + // the address lines 1 and 2 into the new street_address column. + if (!db_->Execute("INSERT INTO autofill_profiles_temp " + "SELECT guid, company_name, '', '', city, state, zipcode," + " '', country_code, date_modified, origin " + "FROM autofill_profiles")) { + return false; + } + sql::Statement s(db_->GetUniqueStatement( + "SELECT guid, address_line_1, address_line_2 FROM autofill_profiles")); + while (s.Step()) { + std::string guid = s.ColumnString(0); + base::string16 line1 = s.ColumnString16(1); + base::string16 line2 = s.ColumnString16(2); + base::string16 street_address = line1; + if (!line2.empty()) + street_address += ASCIIToUTF16("\n") + line2; + + sql::Statement s_update(db_->GetUniqueStatement( + "UPDATE autofill_profiles_temp SET street_address=? WHERE guid=?")); + s_update.BindString16(0, street_address); + s_update.BindString(1, guid); + if (!s_update.Run()) + return false; + } + if (!s.Succeeded()) + return false; + + // Delete the existing (version 53) table and replace it with the contents + // of the temporary table. + if (!db_->Execute("DROP TABLE autofill_profiles") || + !db_->Execute("ALTER TABLE autofill_profiles_temp " + "RENAME TO autofill_profiles")) { + return false; + } + } + + // Test the existence of the |type| column as an indication that a migration + // is needed. It is possible that the new |autofill_profile_phones| schema is + // in place because the table was newly created when migrating from a + // pre-version-23 database. + if (db_->DoesColumnExist("autofill_profile_phones", "type")) { + // Create a temporary copy of the autofill_profile_phones table in the + // (newer) version 54 format. This table removes the deprecated |type| + // column. + if (db_->DoesTableExist("autofill_profile_phones_temp") || + !db_->Execute("CREATE TABLE autofill_profile_phones_temp ( " + "guid VARCHAR, " + "number VARCHAR)")) { + return false; + } + + // Copy over the data from the autofill_profile_phones table. + if (!db_->Execute("INSERT INTO autofill_profile_phones_temp " + "SELECT guid, number FROM autofill_profile_phones")) { + return false; + } + + // Delete the existing (version 53) table and replace it with the contents + // of the temporary table. + if (!db_->Execute("DROP TABLE autofill_profile_phones")) + return false; + if (!db_->Execute("ALTER TABLE autofill_profile_phones_temp " + "RENAME TO autofill_profile_phones")) { + return false; + } + } + + 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 52012e2..bcacdcd 100644 --- a/components/autofill/core/browser/webdata/autofill_table.h +++ b/components/autofill/core/browser/webdata/autofill_table.h @@ -35,17 +35,17 @@ struct FormFieldData; // Note: The database stores time in seconds, UTC. // // autofill -// name The name of the input as specified in the html. -// value The literal contents of the text field. -// value_lower The contents of the text field made lower_case. -// pair_id An ID number unique to the row in the table. -// count How many times the user has entered the string |value| -// in a field of name |name|. +// name The name of the input as specified in the html. +// value The literal contents of the text field. +// value_lower The contents of the text field made lower_case. +// pair_id An ID number unique to the row in the table. +// count How many times the user has entered the string |value| +// in a field of name |name|. // -// autofill_dates This table associates a row to each separate time the -// user submits a form containing a certain name/value -// pair. The |pair_id| should match the |pair_id| field -// in the appropriate row of the autofill table. +// autofill_dates This table associates a row to each separate time the +// user submits a form containing a certain name/value +// pair. The |pair_id| should match the |pair_id| field +// in the appropriate row of the autofill table. // pair_id // date_created // @@ -56,13 +56,18 @@ struct FormFieldData; // guid A guid string to uniquely identify the profile. // Added in version 31. // company_name -// address_line_1 -// address_line_2 +// street_address The combined lines of the street address. +// Added in version 54. +// dependent_locality +// A sub-classification beneath the city, e.g. an +// inner-city district or suburb. Added in version 54. // city // state // zipcode -// country The country name. Deprecated, should be removed once -// the stable channel reaches version 11. +// sorting_code Similar to the zipcode column, but used for businesses +// or organizations that might not be geographically +// contiguous. The canonical example is CEDEX in France. +// Added in version 54. // country_code // date_modified The date on which this profile was last modified. // Added in version 30. @@ -91,12 +96,8 @@ struct FormFieldData; // This table contains the multi-valued phone fields // associated with a profile. // -// guid The guid string that identifies the profile to which -// the phone number belongs. -// type An integer constant designating either phone type of the -// number. -// TODO(jhawkins): Remove the type column and migrate the -// database. +// guid The guid string that identifies the profile to which the +// phone number belongs. // number // // autofill_profiles_trash @@ -115,7 +116,8 @@ struct FormFieldData; // name_on_card // expiration_month // expiration_year -// card_number_encrypted Stores encrypted credit card number. +// card_number_encrypted +// Stores encrypted credit card number. // date_modified The date on which this entry was last modified. // Added in version 30. // origin The domain of origin for this profile. @@ -320,6 +322,7 @@ class AutofillTable : public WebDatabaseTable { bool MigrateToVersion35GreatBritainCountryCodes(); bool MigrateToVersion37MergeAndCullOlderProfiles(); bool MigrateToVersion51AddOriginColumn(); + bool MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields(); // Max data length saved in the table; static const size_t kMaxDataLength; diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc index 982c325..241d393 100644 --- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc @@ -524,9 +524,12 @@ TEST_F(AutofillTableTest, AutofillProfile) { home_profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Google")); home_profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 Apple Way")); home_profile.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("unit 5")); + home_profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + ASCIIToUTF16("Beverly Hills")); home_profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Los Angeles")); home_profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA")); home_profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("90025")); + home_profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("MAGIC ###")); home_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US")); home_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("18181234567")); @@ -602,9 +605,12 @@ TEST_F(AutofillTableTest, AutofillProfile) { billing_profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Indy")); billing_profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("Open Road")); billing_profile.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Route 66")); + billing_profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, + ASCIIToUTF16("District 9")); billing_profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("NFA")); billing_profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("NY")); billing_profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("10011")); + billing_profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("123456")); billing_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US")); billing_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("18181230000")); diff --git a/components/test/data/web_database/version_53.sql b/components/test/data/web_database/version_53.sql new file mode 100644 index 0000000..751aeed --- /dev/null +++ b/components/test/data/web_database/version_53.sql @@ -0,0 +1,50 @@ +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); +INSERT INTO "meta" VALUES('version','53'); +INSERT INTO "meta" VALUES('last_compatible_version','48'); +INSERT INTO "meta" VALUES('Builtin Keyword Version','67'); +INSERT INTO "meta" VALUES('Default Search Provider ID','2'); +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}ie={inputEncoding}',1,'',0,0,'UTF-8',1,'{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&xssi=t&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}{google:pageClassification}sugkey={google:suggestAPIKeyParameter}',1,0,'{google:baseURL}webhp?sourceid=chrome-instant&{google:RLZ}{google:forceInstantResults}{google:instantExtendedEnabledParameter}{google:ntpIsThemedParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}',0,'1D955A9B-6F30-D3FF-5F5C-002E40BDF482','["{google:baseURL}#q={searchTerms}","{google:baseURL}search#q={searchTerms}","{google:baseURL}webhp#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','http://www.bing.com/s/wlflag.ico','http://www.bing.com/search?setmkt=en-US&q={searchTerms}',1,'',0,0,'UTF-8',1,'http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}',3,0,'',0,'E88DEF4C-20E0-5DD7-6A71-20058C05BF09','[]','','','','','','',''); +INSERT INTO "keywords" VALUES(4,'Yahoo!','yahoo.com','http://search.yahoo.com/favicon.ico','http://search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}',1,'',0,0,'UTF-8',1,'http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}',2,0,'',0,'F2F457FC-8B48-47A4-7D7C-8001AB91D1BD','[]','','','','','','',''); +INSERT INTO "keywords" VALUES(5,'AOL','aol.com','http://search.aol.com/favicon.ico','http://search.aol.com/aol/search?query={searchTerms}',1,'',0,0,'UTF-8',1,'http://autocomplete.search.aol.com/autocomplete/get?output=json&it=&q={searchTerms}',35,0,'',0,'F858668C-43E0-5CF3-7D05-EDE8DBF40106','[]','','','','','','',''); +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,'00268D17-EC55-D173-84F3-48D9B862E8E1','[]','','','','','','',''); +CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB); +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 web_intents ( service_url LONGVARCHAR, action VARCHAR, type VARCHAR, title LONGVARCHAR, disposition VARCHAR, scheme VARCHAR, UNIQUE (service_url, action, scheme, type)); +CREATE TABLE web_intents_defaults ( action VARCHAR, type VARCHAR, url_pattern LONGVARCHAR, user_date INTEGER, suppression INTEGER, service_url LONGVARCHAR, scheme VARCHAR, UNIQUE (action, scheme, type, url_pattern)); +CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, pair_id INTEGER PRIMARY KEY, count INTEGER DEFAULT 1); +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 ''); +CREATE TABLE autofill_dates ( pair_id INTEGER DEFAULT 0, date_created INTEGER DEFAULT 0); +CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, address_line_1 VARCHAR, address_line_2 VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, country VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT ''); +INSERT INTO "autofill_profiles" VALUES('00000000-0000-0000-0000-000000000001','Google, Inc.','1950 Charleston Rd.','(2nd floor)','Mountain View','CA','94043','United States','US',1386046731,'Chrome settings'); +INSERT INTO "autofill_profiles" VALUES('00000000-0000-0000-0000-000000000002','Google!','1600 Amphitheatre Pkwy.','','Mtn. View','California','94043-1234','United States','US',1386046800,'Chrome settings'); +INSERT INTO "autofill_profiles" VALUES('00000000-0000-0000-0000-000000000003','','','Only line 2???','','','','','',1386046834,'Chrome settings'); +INSERT INTO "autofill_profiles" VALUES('00000000-0000-0000-0000-000000000004','','','','','Texas','','','',1386046847,'Chrome settings'); +CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR); +INSERT INTO "autofill_profile_names" VALUES('00000000-0000-0000-0000-000000000001','','',''); +INSERT INTO "autofill_profile_names" VALUES('00000000-0000-0000-0000-000000000002','','',''); +INSERT INTO "autofill_profile_names" VALUES('00000000-0000-0000-0000-000000000003','','',''); +INSERT INTO "autofill_profile_names" VALUES('00000000-0000-0000-0000-000000000004','','',''); +CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR); +INSERT INTO "autofill_profile_emails" VALUES('00000000-0000-0000-0000-000000000001',''); +INSERT INTO "autofill_profile_emails" VALUES('00000000-0000-0000-0000-000000000002',''); +INSERT INTO "autofill_profile_emails" VALUES('00000000-0000-0000-0000-000000000003',''); +INSERT INTO "autofill_profile_emails" VALUES('00000000-0000-0000-0000-000000000004',''); +CREATE TABLE autofill_profile_phones ( guid VARCHAR, type INTEGER DEFAULT 0, number VARCHAR); +INSERT INTO "autofill_profile_phones" VALUES('00000000-0000-0000-0000-000000000001',0,'1.800.555.1234'); +INSERT INTO "autofill_profile_phones" VALUES('00000000-0000-0000-0000-000000000001',0,'+1 (800) 555-4321'); +INSERT INTO "autofill_profile_phones" VALUES('00000000-0000-0000-0000-000000000002',0,''); +INSERT INTO "autofill_profile_phones" VALUES('00000000-0000-0000-0000-000000000003',0,'6505557890'); +INSERT INTO "autofill_profile_phones" VALUES('00000000-0000-0000-0000-000000000004',0,''); +CREATE TABLE autofill_profiles_trash ( guid VARCHAR); +CREATE INDEX web_apps_url_index ON web_apps (url); +CREATE INDEX web_intents_index ON web_intents (action); +CREATE INDEX web_intents_default_index ON web_intents_defaults (action); +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); +COMMIT; diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc index 161fb80..44b6790 100644 --- a/components/webdata/common/web_database.cc +++ b/components/webdata/common/web_database.cc @@ -14,11 +14,11 @@ // corresponding changes must happen in the unit tests, and new migration test // added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|. // static -const int WebDatabase::kCurrentVersionNumber = 53; +const int WebDatabase::kCurrentVersionNumber = 54; namespace { -const int kCompatibleVersionNumber = 48; +const int kCompatibleVersionNumber = 54; // Change the version number and possibly the compatibility version of // |meta_table_|. diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc index 57ef02d..9b12fac 100644 --- a/components/webdata/common/web_database_migration_unittest.cc +++ b/components/webdata/common/web_database_migration_unittest.cc @@ -76,15 +76,15 @@ void AutofillProfile33FromStatement(const sql::Statement& s, profile->set_guid(s.ColumnString(0)); EXPECT_TRUE(base::IsValidGUID(profile->guid())); profile->SetRawInfo(autofill::COMPANY_NAME, s.ColumnString16(1)); - profile->SetRawInfo(autofill::ADDRESS_HOME_LINE1, s.ColumnString16(2)); - profile->SetRawInfo(autofill::ADDRESS_HOME_LINE2, s.ColumnString16(3)); - profile->SetRawInfo(autofill::ADDRESS_HOME_CITY, s.ColumnString16(4)); - profile->SetRawInfo(autofill::ADDRESS_HOME_STATE, s.ColumnString16(5)); - profile->SetRawInfo(autofill::ADDRESS_HOME_ZIP, s.ColumnString16(6)); + profile->SetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS, + s.ColumnString16(2)); + profile->SetRawInfo(autofill::ADDRESS_HOME_CITY, s.ColumnString16(3)); + profile->SetRawInfo(autofill::ADDRESS_HOME_STATE, s.ColumnString16(4)); + profile->SetRawInfo(autofill::ADDRESS_HOME_ZIP, s.ColumnString16(5)); profile->SetInfo( autofill::AutofillType(autofill::ADDRESS_HOME_COUNTRY), - s.ColumnString16(7), "en-US"); - *date_modified = s.ColumnInt64(8); + s.ColumnString16(6), "en-US"); + *date_modified = s.ColumnInt64(7); } void CreditCard31FromStatement(const sql::Statement& s, @@ -247,7 +247,7 @@ class WebDatabaseMigrationTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest); }; -const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 53; +const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 54; void WebDatabaseMigrationTest::LoadDatabase( const base::FilePath::StringType& file) { @@ -805,8 +805,8 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion31ToCurrent) { // 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 " + "SELECT guid, company_name, street_address, city, state, zipcode," + " country_code, date_modified " "FROM autofill_profiles")); ASSERT_TRUE(s1.Step()); @@ -916,13 +916,12 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { 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")); + "street_address")); 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", + "country_code")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "phone")); EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "fax")); EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", @@ -943,7 +942,6 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { // 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")); @@ -952,21 +950,22 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { // 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 " + "SELECT guid, company_name, street_address, city, state, zipcode, " + " country_code, 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("United States"), s1.ColumnString16(7)); - EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); + EXPECT_EQ(ASCIIToUTF16("1 Main St\n" + "Apt 1"), + s1.ColumnString16(2)); + EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("US"), s1.ColumnString16(6)); + EXPECT_EQ(1297882100L, s1.ColumnInt64(7)); // John P. Doe. // Gets merged during migration from 35 to 37 due to multi-valued fields. @@ -976,24 +975,22 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s1.ColumnString(0)); EXPECT_EQ(base::string16(), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("2 Main Street"), s1.ColumnString16(2)); - EXPECT_EQ(base::string16(), 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("United States"), s1.ColumnString16(7)); - EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); + EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("US"), s1.ColumnString16(6)); + EXPECT_EQ(1297882100L, s1.ColumnInt64(7)); // Dave Smith (Part 2). ASSERT_TRUE(s1.Step()); EXPECT_EQ("722DF5C4-F74A-294A-46F0-31FFDED0D635", s1.ColumnString(0)); EXPECT_EQ(base::string16(), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("2 Main St"), s1.ColumnString16(2)); - EXPECT_EQ(base::string16(), 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("United States"), s1.ColumnString16(7)); - EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); + EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("US"), s1.ColumnString16(6)); + EXPECT_EQ(1297882100L, s1.ColumnInt64(7)); // Alfred E Newman. // Gets culled during migration from 35 to 36 due to incomplete address. @@ -1003,12 +1000,11 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s1.ColumnString(0)); EXPECT_EQ(base::string16(), s1.ColumnString16(1)); EXPECT_EQ(ASCIIToUTF16("3 Main St"), s1.ColumnString16(2)); - EXPECT_EQ(base::string16(), 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("United States"), s1.ColumnString16(7)); - EXPECT_EQ(1297882100L, s1.ColumnInt64(8)); + EXPECT_EQ(ASCIIToUTF16("Los Altos"), s1.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("94022"), s1.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("US"), s1.ColumnString16(6)); + EXPECT_EQ(1297882100L, s1.ColumnInt64(7)); // That should be all. EXPECT_FALSE(s1.Step()); @@ -1097,14 +1093,13 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { sql::Statement s4( connection.GetUniqueStatement( - "SELECT guid, type, number " + "SELECT guid, 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)); + EXPECT_EQ(ASCIIToUTF16("4151112222"), s4.ColumnString16(1)); // John Doe fax. // Gets culled after fax type removed. @@ -1120,8 +1115,7 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { // 2 Main Street phone. ASSERT_TRUE(s4.Step()); EXPECT_EQ("4C74A9D8-7EEE-423E-F9C2-E7FA70ED1396", s4.ColumnString(0)); - EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone. - EXPECT_EQ(base::string16(), s4.ColumnString16(2)); + EXPECT_EQ(base::string16(), s4.ColumnString16(1)); // 2 Main Street fax. // Gets culled after fax type removed. @@ -1140,8 +1134,7 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion32ToCurrent) { // 3 Main St phone. ASSERT_TRUE(s4.Step()); EXPECT_EQ("9E5FE298-62C7-83DF-6293-381BC589183F", s4.ColumnString(0)); - EXPECT_EQ(0, s4.ColumnInt(1)); // 0 means phone. - EXPECT_EQ(base::string16(), s4.ColumnString16(2)); + EXPECT_EQ(base::string16(), s4.ColumnString16(1)); // 2 Main St fax. // Gets culled after fax type removed. @@ -1295,21 +1288,22 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion35ToCurrent) { // 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 " + "SELECT guid, company_name, street_address, city, state, zipcode," + " country_code, date_modified " "FROM autofill_profiles")); // John Doe. ASSERT_TRUE(s1.Step()); EXPECT_EQ("00000000-0000-0000-0000-000000000001", s1.ColumnString(0)); EXPECT_EQ(ASCIIToUTF16("Acme Inc."), s1.ColumnString16(1)); - EXPECT_EQ(ASCIIToUTF16("1 Main Street"), s1.ColumnString16(2)); - EXPECT_EQ(ASCIIToUTF16("Apt 2"), s1.ColumnString16(3)); - EXPECT_EQ(ASCIIToUTF16("San Francisco"), s1.ColumnString16(4)); - EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(5)); - EXPECT_EQ(ASCIIToUTF16("94102"), s1.ColumnString16(6)); - EXPECT_EQ(ASCIIToUTF16("United States"), s1.ColumnString16(7)); - EXPECT_EQ(1300131704, s1.ColumnInt64(8)); + EXPECT_EQ(ASCIIToUTF16("1 Main Street\n" + "Apt 2"), + s1.ColumnString16(2)); + EXPECT_EQ(ASCIIToUTF16("San Francisco"), s1.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("CA"), s1.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("94102"), s1.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("US"), s1.ColumnString16(6)); + EXPECT_EQ(1300131704, s1.ColumnInt64(7)); // That should be it. ASSERT_FALSE(s1.Step()); @@ -2117,3 +2111,161 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion52ToCurrent) { EXPECT_TRUE(connection.DoesColumnExist("keywords", "new_tab_url")); } } + +// Tests that for a version 54 database, +// (a) The street_address, dependent_locality, and sorting_code columns are +// added to the autofill_profiles table schema. +// (b) The address_line1, address_line2, and country columns are dropped from +// the autofill_profiles table schema. +// (c) The type column is dropped from the autofill_profile_phones schema. +TEST_F(WebDatabaseMigrationTest, MigrateVersion53ToCurrent) { + ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_53.sql"))); + + // Verify pre-conditions. These are expectations for version 53 of the + // database. + { + sql::Connection connection; + ASSERT_TRUE(connection.Open(GetDatabasePath())); + + EXPECT_TRUE( + connection.DoesColumnExist("autofill_profiles", "address_line_1")); + EXPECT_TRUE( + connection.DoesColumnExist("autofill_profiles", "address_line_2")); + EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", "country")); + EXPECT_FALSE( + connection.DoesColumnExist("autofill_profiles", "street_address")); + EXPECT_FALSE( + connection.DoesColumnExist("autofill_profiles", "dependent_locality")); + EXPECT_FALSE( + connection.DoesColumnExist("autofill_profiles", "sorting_code")); + EXPECT_TRUE(connection.DoesColumnExist("autofill_profile_phones", "type")); + } + + DoMigration(); + + // Verify post-conditions. These are expectations for current version of the + // database. + { + sql::Connection connection; + ASSERT_TRUE(connection.Open(GetDatabasePath())); + ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection)); + + // Check version. + EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection)); + + // Columns should have been added and removed appropriately. + EXPECT_FALSE( + connection.DoesColumnExist("autofill_profiles", "address_line1")); + EXPECT_FALSE( + connection.DoesColumnExist("autofill_profiles", "address_line2")); + EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "country")); + EXPECT_TRUE( + connection.DoesColumnExist("autofill_profiles", "street_address")); + EXPECT_TRUE( + connection.DoesColumnExist("autofill_profiles", "dependent_locality")); + EXPECT_TRUE( + connection.DoesColumnExist("autofill_profiles", "sorting_code")); + EXPECT_FALSE(connection.DoesColumnExist("autofill_profile_phones", "type")); + + // Data should have been preserved. + sql::Statement s_profiles( + connection.GetUniqueStatement( + "SELECT guid, company_name, street_address, dependent_locality," + " city, state, zipcode, sorting_code, country_code, date_modified," + " origin " + "FROM autofill_profiles")); + + // Address lines 1 and 2. + ASSERT_TRUE(s_profiles.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000001", + s_profiles.ColumnString(0)); + EXPECT_EQ(ASCIIToUTF16("Google, Inc."), s_profiles.ColumnString16(1)); + EXPECT_EQ(ASCIIToUTF16("1950 Charleston Rd.\n" + "(2nd floor)"), + s_profiles.ColumnString16(2)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("Mountain View"), s_profiles.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("CA"), s_profiles.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("94043"), s_profiles.ColumnString16(6)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(7)); + EXPECT_EQ(ASCIIToUTF16("US"), s_profiles.ColumnString16(8)); + EXPECT_EQ(1386046731, s_profiles.ColumnInt(9)); + EXPECT_EQ(ASCIIToUTF16("Chrome settings"), s_profiles.ColumnString16(10)); + + // Only address line 1. + ASSERT_TRUE(s_profiles.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000002", + s_profiles.ColumnString(0)); + EXPECT_EQ(ASCIIToUTF16("Google!"), s_profiles.ColumnString16(1)); + EXPECT_EQ(ASCIIToUTF16("1600 Amphitheatre Pkwy."), + s_profiles.ColumnString16(2)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(3)); + EXPECT_EQ(ASCIIToUTF16("Mtn. View"), s_profiles.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("California"), s_profiles.ColumnString16(5)); + EXPECT_EQ(ASCIIToUTF16("94043-1234"), s_profiles.ColumnString16(6)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(7)); + EXPECT_EQ(ASCIIToUTF16("US"), s_profiles.ColumnString16(8)); + EXPECT_EQ(1386046800, s_profiles.ColumnInt(9)); + EXPECT_EQ(ASCIIToUTF16("Chrome settings"), s_profiles.ColumnString16(10)); + + // Only address line 2. + ASSERT_TRUE(s_profiles.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000003", + s_profiles.ColumnString(0)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(1)); + EXPECT_EQ(ASCIIToUTF16("\nOnly line 2???"), s_profiles.ColumnString16(2)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(3)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(4)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(5)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(6)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(7)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(8)); + EXPECT_EQ(1386046834, s_profiles.ColumnInt(9)); + EXPECT_EQ(ASCIIToUTF16("Chrome settings"), s_profiles.ColumnString16(10)); + + // No address lines. + ASSERT_TRUE(s_profiles.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000004", + s_profiles.ColumnString(0)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(1)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(2)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(3)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(4)); + EXPECT_EQ(ASCIIToUTF16("Texas"), s_profiles.ColumnString16(5)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(6)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(7)); + EXPECT_EQ(base::string16(), s_profiles.ColumnString16(8)); + EXPECT_EQ(1386046847, s_profiles.ColumnInt(9)); + EXPECT_EQ(ASCIIToUTF16("Chrome settings"), s_profiles.ColumnString16(10)); + + // That should be it. + EXPECT_FALSE(s_profiles.Step()); + + // Verify the phone number data as well. + sql::Statement s_phones( + connection.GetUniqueStatement( + "SELECT guid, number FROM autofill_profile_phones")); + + ASSERT_TRUE(s_phones.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000001", s_phones.ColumnString(0)); + EXPECT_EQ(ASCIIToUTF16("1.800.555.1234"), s_phones.ColumnString16(1)); + + ASSERT_TRUE(s_phones.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000001", s_phones.ColumnString(0)); + EXPECT_EQ(ASCIIToUTF16("+1 (800) 555-4321"), s_phones.ColumnString16(1)); + + ASSERT_TRUE(s_phones.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000002", s_phones.ColumnString(0)); + EXPECT_EQ(base::string16(), s_phones.ColumnString16(1)); + + ASSERT_TRUE(s_phones.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000003", s_phones.ColumnString(0)); + EXPECT_EQ(ASCIIToUTF16("6505557890"), s_phones.ColumnString16(1)); + + ASSERT_TRUE(s_phones.Step()); + EXPECT_EQ("00000000-0000-0000-0000-000000000004", s_phones.ColumnString(0)); + EXPECT_EQ(base::string16(), s_phones.ColumnString16(1)); + + EXPECT_FALSE(s_phones.Step()); + } +} |