diff options
author | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-20 03:24:55 +0000 |
---|---|---|
committer | dhollowa@chromium.org <dhollowa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-20 03:24:55 +0000 |
commit | d3d728e9b36811fb77d8176297d607c84e6a2d18 (patch) | |
tree | 200690d244f5ab82d30283dd0ec16052225d3281 /chrome/browser | |
parent | e3322f4b2588371b962b0a7da5fbede0ace0cdd8 (diff) | |
download | chromium_src-d3d728e9b36811fb77d8176297d607c84e6a2d18.zip chromium_src-d3d728e9b36811fb77d8176297d607c84e6a2d18.tar.gz chromium_src-d3d728e9b36811fb77d8176297d607c84e6a2d18.tar.bz2 |
This is stage 1 of transition to GUIDs as primary identifier for AutoFill profiles and credit cards.
The transition will look like this in terms of table migration:
Current:
CREATE TABLE autofill_profiles (
label VARCHAR,
unique_id INTEGER PRIMARY KEY,
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);
Transitional (adds guid column):
CREATE TABLE autofill_profiles (
label VARCHAR,
unique_id INTEGER PRIMARY KEY,
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,
guid VARCHAR NOT NULL); // <- add guid
End goal (in follow up CL):
CREATE TABLE autofill_profiles (
// remove label
// remove unique_id
guid VARCHAR NOT NULL PRIMARY KEY // <- reorder guid, make primary
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);
And similarly for the credit_cards table.
BUG=58813
TEST=AutoFillProfileTest.Compare, GUIDTest.GUIDCorrectlyFormatted, WebDataServiceAutofillTest.ProfileRemoveGUID, WebDataServiceAutofillTest.CreditCardRemoveGUID, WebDatabaseTest.AutoFillProfile, WebDatabaseTest.CreditCard, WebDatabaseMigrationTest.MigrateVersion30ToCurrent
Review URL: http://codereview.chromium.org/3760009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63173 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/autofill/autofill_dialog_controller_mac.mm | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_profile.cc | 41 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_profile.h | 25 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_profile_unittest.cc | 21 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card.cc | 25 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card.h | 18 | ||||
-rw-r--r-- | chrome/browser/guid.cc | 32 | ||||
-rw-r--r-- | chrome/browser/guid.h | 3 | ||||
-rw-r--r-- | chrome/browser/guid_unittest.cc | 13 | ||||
-rw-r--r-- | chrome/browser/sync/glue/autofill_model_associator.cc | 2 | ||||
-rw-r--r-- | chrome/browser/sync/profile_sync_service_autofill_unittest.cc | 10 | ||||
-rw-r--r-- | chrome/browser/webdata/autofill_change.h | 2 | ||||
-rw-r--r-- | chrome/browser/webdata/web_data_service.cc | 90 | ||||
-rw-r--r-- | chrome/browser/webdata/web_data_service.h | 18 | ||||
-rw-r--r-- | chrome/browser/webdata/web_data_service_unittest.cc | 81 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.cc | 262 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.h | 30 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database_unittest.cc | 256 |
18 files changed, 856 insertions, 77 deletions
diff --git a/chrome/browser/autofill/autofill_dialog_controller_mac.mm b/chrome/browser/autofill/autofill_dialog_controller_mac.mm index 26bd111..35451ec 100644 --- a/chrome/browser/autofill/autofill_dialog_controller_mac.mm +++ b/chrome/browser/autofill/autofill_dialog_controller_mac.mm @@ -8,13 +8,13 @@ #include "base/mac_util.h" #include "base/singleton.h" #include "base/sys_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" #import "chrome/browser/autofill/autofill_address_model_mac.h" #import "chrome/browser/autofill/autofill_address_sheet_controller_mac.h" #import "chrome/browser/autofill/autofill_credit_card_model_mac.h" #import "chrome/browser/autofill/autofill_credit_card_sheet_controller_mac.h" #import "chrome/browser/autofill/personal_data_manager.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #import "chrome/browser/cocoa/window_size_autosaver.h" #include "chrome/browser/prefs/pref_service.h" diff --git a/chrome/browser/autofill/autofill_profile.cc b/chrome/browser/autofill/autofill_profile.cc index 4ef273f..bb45b75 100644 --- a/chrome/browser/autofill/autofill_profile.cc +++ b/chrome/browser/autofill/autofill_profile.cc @@ -19,6 +19,7 @@ #include "chrome/browser/autofill/fax_number.h" #include "chrome/browser/autofill/home_address.h" #include "chrome/browser/autofill/home_phone_number.h" +#include "chrome/browser/guid.h" #include "grit/generated_resources.h" namespace { @@ -34,7 +35,14 @@ void InitPersonalInfo(FormGroupMap* personal_info) { AutoFillProfile::AutoFillProfile(const string16& label, int unique_id) : label_(label), - unique_id_(unique_id) { + unique_id_(unique_id), + guid_(guid::GenerateGUID()) { + InitPersonalInfo(&personal_info_); +} + +AutoFillProfile::AutoFillProfile(const std::string& guid) + : unique_id_(0), + guid_(guid) { InitPersonalInfo(&personal_info_); } @@ -150,6 +158,7 @@ FormGroup* AutoFillProfile::Clone() const { AutoFillProfile* profile = new AutoFillProfile(); profile->label_ = label_; profile->unique_id_ = unique_id(); + profile->guid_ = guid(); FormGroupMap::const_iterator iter; for (iter = personal_info_.begin(); iter != personal_info_.end(); ++iter) { @@ -390,6 +399,7 @@ bool AutoFillProfile::IsEmpty() const { void AutoFillProfile::operator=(const AutoFillProfile& source) { label_ = source.label_; unique_id_ = source.unique_id_; + guid_ = source.guid_; STLDeleteContainerPairSecondPointers(personal_info_.begin(), personal_info_.end()); @@ -403,6 +413,33 @@ void AutoFillProfile::operator=(const AutoFillProfile& source) { } } +int AutoFillProfile::Compare(const AutoFillProfile& profile) const { + // The following AutoFill field types are the only types we store in the WebDB + // so far, so we're only concerned with matching these types in the profile. + const AutoFillFieldType types[] = { NAME_FIRST, + NAME_MIDDLE, + NAME_LAST, + EMAIL_ADDRESS, + COMPANY_NAME, + ADDRESS_HOME_LINE1, + ADDRESS_HOME_LINE2, + ADDRESS_HOME_CITY, + ADDRESS_HOME_STATE, + ADDRESS_HOME_ZIP, + ADDRESS_HOME_COUNTRY, + PHONE_HOME_NUMBER, + PHONE_FAX_NUMBER }; + + for (size_t index = 0; index < arraysize(types); ++index) { + int comparison = GetFieldText(AutoFillType(types[index])).compare( + profile.GetFieldText(AutoFillType(types[index]))); + if (comparison != 0) + return comparison; + } + + return 0; +} + bool AutoFillProfile::operator==(const AutoFillProfile& profile) const { // The following AutoFill field types are the only types we store in the WebDB // so far, so we're only concerned with matching these types in the profile. @@ -473,6 +510,8 @@ std::ostream& operator<<(std::ostream& os, const AutoFillProfile& profile) { << " " << profile.unique_id() << " " + << profile.guid() + << " " << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_FIRST))) << " " << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_MIDDLE))) diff --git a/chrome/browser/autofill/autofill_profile.h b/chrome/browser/autofill/autofill_profile.h index 1da4f27..4336139b 100644 --- a/chrome/browser/autofill/autofill_profile.h +++ b/chrome/browser/autofill/autofill_profile.h @@ -21,7 +21,11 @@ typedef std::map<FieldTypeGroup, FormGroup*> FormGroupMap; // to the requested form group type. class AutoFillProfile : public FormGroup { public: + // DEPRECATED + // TODO(dhollowa): Remove unique ID and label. http://crbug.com/58813 AutoFillProfile(const string16& label, int unique_id); + explicit AutoFillProfile(const std::string& guid); + // For use in STL containers. AutoFillProfile(); AutoFillProfile(const AutoFillProfile&); @@ -44,8 +48,12 @@ class AutoFillProfile : public FormGroup { virtual FormGroup* Clone() const; virtual const string16& Label() const; - void set_unique_id(int id) { unique_id_ = id; } int unique_id() const { return unique_id_; } + void set_unique_id(int id) { unique_id_ = id; } + + // This guid is the primary identifier for |AutoFillProfile| objects. + const std::string guid() const { return guid_; } + void set_guid(const std::string& guid) { guid_ = guid; } // Profile summary string for UI. // Constructs a summary string based on NAME_FIRST, NAME_LAST, and @@ -88,7 +96,17 @@ class AutoFillProfile : public FormGroup { // For use in STL containers. void operator=(const AutoFillProfile&); - // For WebData and Sync. + // Comparison for Sync. Returns 0 if the profile is the same as |this|, + // or < 0, or > 0 if it is different. The implied ordering can be used for + // culling duplicates. + // GUIDs, labels, and unique IDs are not compared, only the values of the + // profiles themselves. + int Compare(const AutoFillProfile& profile) const; + + // TODO(dhollowa): These operators need to be made private and then the unit + // tests that use them made friends. The public |Compare| method should be + // used by external clients (such as Sync). + // http://crbug.com/58813 bool operator==(const AutoFillProfile& profile) const; virtual bool operator!=(const AutoFillProfile& profile) const; void set_label(const string16& label) { label_ = label; } @@ -109,6 +127,9 @@ class AutoFillProfile : public FormGroup { // The unique ID of this profile. int unique_id_; + // The guid of this profile. + std::string guid_; + // Personal information for this profile. FormGroupMap personal_info_; }; diff --git a/chrome/browser/autofill/autofill_profile_unittest.cc b/chrome/browser/autofill/autofill_profile_unittest.cc index d217355..5a1f27b 100644 --- a/chrome/browser/autofill/autofill_profile_unittest.cc +++ b/chrome/browser/autofill/autofill_profile_unittest.cc @@ -9,6 +9,7 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_common_test.h" #include "chrome/browser/autofill/autofill_profile.h" +#include "chrome/browser/guid.h" #include "grit/generated_resources.h" #include "testing/gtest/include/gtest/gtest.h" @@ -362,4 +363,24 @@ TEST(AutoFillProfileTest, MergeWith) { EXPECT_EQ(expected_b, *b); } +TEST(AutoFillProfileTest, Compare) { + AutoFillProfile a, b; + + // Empty profiles are the same. + EXPECT_EQ(0, a.Compare(b)); + + // GUIDs don't count. + a.set_guid(guid::GenerateGUID()); + b.set_guid(guid::GenerateGUID()); + EXPECT_EQ(0, a.Compare(b)); + + // Different values produce non-zero results. + autofill_test::SetProfileInfo(&a, "label1", "Jimmy", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + autofill_test::SetProfileInfo(&b, "label1", "Ringo", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + EXPECT_GT(0, a.Compare(b)); + EXPECT_LT(0, b.Compare(a)); +} + } // namespace diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc index 98ba665..a288bf6 100644 --- a/chrome/browser/autofill/credit_card.cc +++ b/chrome/browser/autofill/credit_card.cc @@ -14,6 +14,7 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/field_types.h" +#include "chrome/browser/guid.h" #include "grit/generated_resources.h" namespace { @@ -125,19 +126,30 @@ std::string GetCreditCardType(const string16& number) { } // namespace -CreditCard::CreditCard() +CreditCard::CreditCard(const string16& label, + int unique_id) : expiration_month_(0), expiration_year_(0), + label_(label), billing_address_id_(0), - unique_id_(0) { + unique_id_(unique_id), + guid_(guid::GenerateGUID()) { } -CreditCard::CreditCard(const string16& label, int unique_id) +CreditCard::CreditCard(const std::string& guid) + : expiration_month_(0), + expiration_year_(0), + billing_address_id_(0), + unique_id_(0), + guid_(guid) { +} + +CreditCard::CreditCard() : expiration_month_(0), expiration_year_(0), - label_(label), billing_address_id_(0), - unique_id_(unique_id) { + unique_id_(0), + guid_(guid::GenerateGUID()) { } CreditCard::CreditCard(const CreditCard& card) : FormGroup() { @@ -373,6 +385,7 @@ void CreditCard::operator=(const CreditCard& source) { label_ = source.label_; billing_address_id_ = source.billing_address_id_; unique_id_ = source.unique_id_; + guid_ = source.guid_; } bool CreditCard::operator==(const CreditCard& creditcard) const { @@ -609,6 +622,8 @@ std::ostream& operator<<(std::ostream& os, const CreditCard& creditcard) { << " " << creditcard.unique_id() << " " + << creditcard.guid() + << " " << creditcard.billing_address_id() << " " << UTF16ToUTF8(creditcard.GetFieldText(AutoFillType(CREDIT_CARD_NAME))) diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h index 874385f..f437a90 100644 --- a/chrome/browser/autofill/credit_card.h +++ b/chrome/browser/autofill/credit_card.h @@ -14,11 +14,15 @@ // A form group that stores credit card information. class CreditCard : public FormGroup { public: - CreditCard(); + // DEPRECATED + // TODO(dhollowa): Remove unique ID and label. http://crbug.com/58813 CreditCard(const string16& label, int unique_id); + explicit CreditCard(const std::string& guid); + // For use in STL containers. + CreditCard(); CreditCard(const CreditCard& card); - ~CreditCard(); + virtual ~CreditCard(); // FormGroup implementation: FormGroup* Clone() const; @@ -42,13 +46,18 @@ class CreditCard : public FormGroup { const string16& type() const { return type_; } int billing_address_id() const { return billing_address_id_; } + int unique_id() const { return unique_id_; } + void set_unique_id(int id) { unique_id_ = id; } + + // The guid is the primary identifier for |CreditCard| objects. + const std::string guid() const { return guid_; } + void set_guid(const std::string& guid) { guid_ = guid; } // The caller should verify that the corresponding AutoFillProfile exists. void set_billing_address_id(int address_id) { billing_address_id_ = address_id; } - void set_unique_id(int id) { unique_id_ = id; } // For use in STL containers. void operator=(const CreditCard&); @@ -144,6 +153,9 @@ class CreditCard : public FormGroup { // The unique ID of this credit card. int unique_id_; + + // The guid of this credit card. + std::string guid_; }; // So we can compare CreditCards with EXPECT_EQ(). diff --git a/chrome/browser/guid.cc b/chrome/browser/guid.cc new file mode 100644 index 0000000..b8f46db --- /dev/null +++ b/chrome/browser/guid.cc @@ -0,0 +1,32 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/guid.h" + +#include "base/rand_util.h" +#include "base/stringprintf.h" + +namespace guid { + +bool IsValidGUID(const std::string& guid) { + const size_t kGUIDLength = 36U; + if (guid.length() != kGUIDLength) + return false; + + std::string hexchars = "0123456789ABCDEF"; + for (uint32 i = 0; i < guid.length(); ++i) { + char current = guid[i]; + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (current != '-') + return false; + } else { + if (hexchars.find(current) == std::string::npos) + return false; + } + } + + return true; +} + +} // namespace guid diff --git a/chrome/browser/guid.h b/chrome/browser/guid.h index bc47ed8..b5aa67d 100644 --- a/chrome/browser/guid.h +++ b/chrome/browser/guid.h @@ -19,6 +19,9 @@ namespace guid { // the GUID. The Windows implementation uses system services. std::string GenerateGUID(); +// Returns true if the input string conforms to the GUID format. +bool IsValidGUID(const std::string& guid); + #if defined(OS_POSIX) // For unit testing purposes only. Do not use outside of tests. std::string RandomDataToGUIDString(const uint64 bytes[2]); diff --git a/chrome/browser/guid_unittest.cc b/chrome/browser/guid_unittest.cc index ebbce8f..1951ca1 100644 --- a/chrome/browser/guid_unittest.cc +++ b/chrome/browser/guid_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -26,16 +26,7 @@ TEST(GUIDTest, GUIDCorrectlyFormatted) { const int kIterations = 10; for (int it = 0; it < kIterations; ++it) { std::string guid = guid::GenerateGUID(); - EXPECT_EQ(36U, guid.length()); - std::string hexchars = "0123456789ABCDEF"; - for (uint32 i = 0; i < guid.length(); ++i) { - char current = guid.at(i); - if (i == 8 || i == 13 || i == 18 || i == 23) { - EXPECT_EQ('-', current); - } else { - EXPECT_TRUE(std::string::npos != hexchars.find(current)); - } - } + EXPECT_TRUE(guid::IsValidGUID(guid)); } } diff --git a/chrome/browser/sync/glue/autofill_model_associator.cc b/chrome/browser/sync/glue/autofill_model_associator.cc index e3fac11..9efa191 100644 --- a/chrome/browser/sync/glue/autofill_model_associator.cc +++ b/chrome/browser/sync/glue/autofill_model_associator.cc @@ -130,6 +130,8 @@ bool AutofillModelAssociator::TraverseAndAssociateChromeAutoFillProfiles( return false; } tag = ProfileLabelToTag(label); + // TODO(dhollowa): Replace with |AutoFillProfile::set_guid|. + // http://crbug.com/58813 (*ix)->set_label(label); if (!MakeNewAutofillProfileSyncNode(write_trans, autofill_root, tag, **ix, &sync_id)) { diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc index c611ecc..e541380 100644 --- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc @@ -769,6 +769,8 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeProfile) { ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles)); ASSERT_EQ(1U, new_sync_profiles.size()); + // TODO(dhollowa): Replace with |AutoFillProfile::Compare|. + // http://crbug.com/58813 EXPECT_TRUE(sync_profile == new_sync_profiles[0]); } @@ -829,6 +831,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfile) { ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles)); ASSERT_EQ(1U, new_sync_profiles.size()); + // TODO(dhollowa): Replace with |AutoFillProfile::Compare|. + // http://crbug.com/58813 EXPECT_TRUE(added_profile == new_sync_profiles[0]); } @@ -957,6 +961,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfile) { ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles)); ASSERT_EQ(1U, new_sync_profiles.size()); + // TODO(dhollowa): Replace with |AutoFillProfile::Compare|. + // http://crbug.com/58813 EXPECT_TRUE(update_profile == new_sync_profiles[0]); } @@ -995,6 +1001,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfileRelabel) { ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles)); ASSERT_EQ(1U, new_sync_profiles.size()); + // TODO(dhollowa): Replace with |AutoFillProfile::Compare|. + // http://crbug.com/58813 EXPECT_TRUE(update_profile == new_sync_profiles[0]); } @@ -1029,6 +1037,8 @@ TEST_F(ProfileSyncServiceAutofillTest, // idempotent, settling on the same name and not triggering a sync upload. for (int pass = 0; pass < 2; ++pass) { AutoFillProfile josephine_update(josephine); + // TODO(dhollowa): Replace with |AutoFillProfile::set_guid|. + // http://crbug.com/58813 josephine_update.set_label(ASCIIToUTF16("ExistingLabel")); AutoFillProfile relabelled_profile; diff --git a/chrome/browser/webdata/autofill_change.h b/chrome/browser/webdata/autofill_change.h index de433cc..11723d3 100644 --- a/chrome/browser/webdata/autofill_change.h +++ b/chrome/browser/webdata/autofill_change.h @@ -63,6 +63,8 @@ class AutofillProfileChange : public GenericAutofillChange<string16> { return false; if (type() == REMOVE) return true; + // TODO(dhollowa): Replace with |AutoFillProfile::Compare|. + // http://crbug.com/58813 if (*profile() != *change.profile()) return false; return type() == ADD || pre_update_label_ == change.pre_update_label(); diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc index 04c9c47..36285b7 100644 --- a/chrome/browser/webdata/web_data_service.cc +++ b/chrome/browser/webdata/web_data_service.cc @@ -416,6 +416,16 @@ void WebDataService::RemoveAutoFillProfile(int profile_id) { request)); } +void WebDataService::RemoveAutoFillProfile(const std::string& guid) { + GenericRequest<std::string>* request = + new GenericRequest<std::string>( + this, GetNextRequestHandle(), NULL, guid); + RegisterRequest(request); + ScheduleTask(NewRunnableMethod(this, + &WebDataService::RemoveAutoFillProfileGUIDImpl, + request)); +} + WebDataService::Handle WebDataService::GetAutoFillProfiles( WebDataServiceConsumer* consumer) { WebDataRequest* request = @@ -458,6 +468,16 @@ void WebDataService::RemoveCreditCard(int creditcard_id) { request)); } +void WebDataService::RemoveCreditCard(const std::string& guid) { + GenericRequest<std::string>* request = + new GenericRequest<std::string>( + this, GetNextRequestHandle(), NULL, guid); + RegisterRequest(request); + ScheduleTask(NewRunnableMethod(this, + &WebDataService::RemoveCreditCardGUIDImpl, + request)); +} + WebDataService::Handle WebDataService::GetCreditCards( WebDataServiceConsumer* consumer) { WebDataRequest* request = @@ -1055,6 +1075,34 @@ void WebDataService::RemoveAutoFillProfileImpl( request->RequestComplete(); } +void WebDataService::RemoveAutoFillProfileGUIDImpl( + GenericRequest<std::string>* request) { + InitializeDatabaseIfNecessary(); + if (db_ && !request->IsCancelled()) { + std::string guid = request->GetArgument(); + AutoFillProfile* profile = NULL; + if (!db_->GetAutoFillProfileForGUID(guid, &profile)) + NOTREACHED(); + + if (profile) { + scoped_ptr<AutoFillProfile> dead_profile(profile); + if (!db_->RemoveAutoFillProfile(guid)) + NOTREACHED(); + ScheduleCommit(); + + // TODO(dhollowa): Deprecate and label. http://crbug.com/58813 + AutofillProfileChange change(AutofillProfileChange::REMOVE, + dead_profile->Label(), + NULL, string16()); + NotificationService::current()->Notify( + NotificationType::AUTOFILL_PROFILE_CHANGED, + Source<WebDataService>(this), + Details<AutofillProfileChange>(&change)); + } + } + request->RequestComplete(); +} + void WebDataService::GetAutoFillProfilesImpl(WebDataRequest* request) { InitializeDatabaseIfNecessary(); if (db_ && !request->IsCancelled()) { @@ -1110,19 +1158,47 @@ void WebDataService::RemoveCreditCardImpl( InitializeDatabaseIfNecessary(); if (db_ && !request->IsCancelled()) { int creditcard_id = request->GetArgument(); - CreditCard* dead_card_ptr = NULL; - if (!db_->GetCreditCardForID(creditcard_id, &dead_card_ptr)) + CreditCard* credit_card = NULL; + if (!db_->GetCreditCardForID(creditcard_id, &credit_card)) NOTREACHED(); - scoped_ptr<CreditCard> dead_card(dead_card_ptr); - if (!db_->RemoveCreditCard(creditcard_id)) + if (credit_card) { + scoped_ptr<CreditCard> dead_credit_card(credit_card); + if (!db_->RemoveCreditCard(creditcard_id)) + NOTREACHED(); + + ScheduleCommit(); + + AutofillCreditCardChange change(AutofillCreditCardChange::REMOVE, + dead_credit_card->Label(), NULL); + NotificationService::current()->Notify( + NotificationType::AUTOFILL_CREDIT_CARD_CHANGED, + Source<WebDataService>(this), + Details<AutofillCreditCardChange>(&change)); + } + } + request->RequestComplete(); +} + +void WebDataService::RemoveCreditCardGUIDImpl( + GenericRequest<std::string>* request) { + InitializeDatabaseIfNecessary(); + if (db_ && !request->IsCancelled()) { + std::string guid = request->GetArgument(); + CreditCard* credit_card = NULL; + if (!db_->GetCreditCardForGUID(guid, &credit_card)) NOTREACHED(); - ScheduleCommit(); + if (credit_card) { + scoped_ptr<CreditCard> dead_credit_card(credit_card); + if (!db_->RemoveCreditCard(guid)) + NOTREACHED(); + + ScheduleCommit(); - if (dead_card.get()) { + // TODO(dhollowa): Deprecate and label. http://crbug.com/58813 AutofillCreditCardChange change(AutofillCreditCardChange::REMOVE, - dead_card->Label(), NULL); + dead_credit_card->Label(), NULL); NotificationService::current()->Notify( NotificationType::AUTOFILL_CREDIT_CARD_CHANGED, Source<WebDataService>(this), diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h index 9062d07..02d9720 100644 --- a/chrome/browser/webdata/web_data_service.h +++ b/chrome/browser/webdata/web_data_service.h @@ -70,7 +70,7 @@ typedef enum { AUTOFILL_VALUE_RESULT, // WDResult<std::vector<string16>> AUTOFILL_CHANGES, // WDResult<std::vector<AutofillChange>> AUTOFILL_PROFILE_RESULT, // WDResult<AutoFillProfile> - AUTOFILL_PROFILES_RESULT, // WDResult<std::vector<AutoFillProfile*>> + AUTOFILL_PROFILES_RESULT, // WDResult<std::vector<AutoFillProfile*>> AUTOFILL_CREDITCARD_RESULT, // WDResult<CreditCard> AUTOFILL_CREDITCARDS_RESULT // WDResult<std::vector<CreditCard*>> } WDResultType; @@ -441,8 +441,14 @@ class WebDataService // Schedules a task to remove an AutoFill profile from the web database. // |profile_id| is the unique ID of the profile to remove. + // DEPRECATED + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 void RemoveAutoFillProfile(int profile_id); + // Schedules a task to remove an AutoFill profile from the web database. + // |guid| is the identifer of the profile to remove. + void RemoveAutoFillProfile(const std::string& guid); + // Initiates the request for all AutoFill profiles. The method // OnWebDataServiceRequestDone of |consumer| gets called when the request is // finished, with the profiles included in the argument |result|. The @@ -457,8 +463,14 @@ class WebDataService // Schedules a task to remove a credit card from the web database. // |creditcard_id| is the unique ID of the credit card to remove. + // DEPRECATED + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 void RemoveCreditCard(int creditcard_id); + // Schedules a task to remove a credit card from the web database. + // |guid| is identifer of the credit card to remove. + void RemoveCreditCard(const std::string& guid); + // Initiates the request for all credit cards. The method // OnWebDataServiceRequestDone of |consumer| gets called when the request is // finished, with the credit cards included in the argument |result|. The @@ -597,11 +609,15 @@ class WebDataService GenericRequest2<string16, string16>* request); void AddAutoFillProfileImpl(GenericRequest<AutoFillProfile>* request); void UpdateAutoFillProfileImpl(GenericRequest<AutoFillProfile>* request); + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 void RemoveAutoFillProfileImpl(GenericRequest<int>* request); + void RemoveAutoFillProfileGUIDImpl(GenericRequest<std::string>* request); void GetAutoFillProfilesImpl(WebDataRequest* request); void AddCreditCardImpl(GenericRequest<CreditCard>* request); void UpdateCreditCardImpl(GenericRequest<CreditCard>* request); + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 void RemoveCreditCardImpl(GenericRequest<int>* request); + void RemoveCreditCardGUIDImpl(GenericRequest<std::string>* request); void GetCreditCardsImpl(WebDataRequest* request); void RemoveAutoFillProfilesAndCreditCardsModifiedBetweenImpl( GenericRequest2<base::Time, base::Time>* request); diff --git a/chrome/browser/webdata/web_data_service_unittest.cc b/chrome/browser/webdata/web_data_service_unittest.cc index aeeee2b..81234a0 100644 --- a/chrome/browser/webdata/web_data_service_unittest.cc +++ b/chrome/browser/webdata/web_data_service_unittest.cc @@ -11,6 +11,8 @@ #include "base/path_service.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" +#include "base/scoped_vector.h" +#include "base/stl_util-inl.h" #include "base/string16.h" #include "base/string_util.h" #include "base/time.h" @@ -19,6 +21,7 @@ #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/credit_card.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/guid.h" #include "chrome/browser/webdata/autofill_change.h" #include "chrome/browser/webdata/autofill_entry.h" #include "chrome/browser/webdata/web_data_service.h" @@ -286,6 +289,45 @@ TEST_F(WebDataServiceAutofillTest, ProfileRemove) { done_event_.TimedWait(test_timeout_); } +TEST_F(WebDataServiceAutofillTest, ProfileRemoveGUID) { + AutoFillProfile profile(name1_, unique_id1_); + + // Add a profile. + EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)). + WillOnce(SignalEvent(&done_event_)); + wds_->AddAutoFillProfile(profile); + done_event_.TimedWait(test_timeout_); + + // Check that it was added. + AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer; + WebDataService::Handle handle = wds_->GetAutoFillProfiles(&consumer); + MessageLoop::current()->Run(); + EXPECT_EQ(handle, consumer.handle()); + ASSERT_EQ(1U, consumer.result().size()); + EXPECT_EQ(profile, *consumer.result()[0]); + STLDeleteElements(&consumer.result()); + + // Remove the profile. + const AutofillProfileChange expected_change( + AutofillProfileChange::REMOVE, name1_, NULL, string16()); + EXPECT_CALL( + *observer_helper_->observer(), + Observe(NotificationType(NotificationType::AUTOFILL_PROFILE_CHANGED), + Source<WebDataService>(wds_.get()), + Property(&Details<const AutofillProfileChange>::ptr, + Pointee(expected_change)))). + WillOnce(SignalEvent(&done_event_)); + wds_->RemoveAutoFillProfile(profile.guid()); + done_event_.TimedWait(test_timeout_); + + // Check that it was removed. + AutofillWebDataServiceConsumer<std::vector<AutoFillProfile*> > consumer2; + WebDataService::Handle handle2 = wds_->GetAutoFillProfiles(&consumer2); + MessageLoop::current()->Run(); + EXPECT_EQ(handle2, consumer2.handle()); + ASSERT_EQ(0U, consumer2.result().size()); +} + TEST_F(WebDataServiceAutofillTest, ProfileUpdate) { AutoFillProfile profile1(name1_, unique_id1_); AutoFillProfile profile2(name2_, unique_id2_); @@ -356,6 +398,45 @@ TEST_F(WebDataServiceAutofillTest, CreditRemove) { done_event_.TimedWait(test_timeout_); } +TEST_F(WebDataServiceAutofillTest, CreditCardRemoveGUID) { + CreditCard card(name1_, unique_id1_); + + // Add a credit card. + EXPECT_CALL(*observer_helper_->observer(), Observe(_, _, _)). + WillOnce(SignalEvent(&done_event_)); + wds_->AddCreditCard(card); + done_event_.TimedWait(test_timeout_); + + // Check that it was added. + AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer; + WebDataService::Handle handle = wds_->GetCreditCards(&consumer); + MessageLoop::current()->Run(); + EXPECT_EQ(handle, consumer.handle()); + ASSERT_EQ(1U, consumer.result().size()); + EXPECT_EQ(card, *consumer.result()[0]); + STLDeleteElements(&consumer.result()); + + // Remove the credit card. + const AutofillCreditCardChange expected_change( + AutofillCreditCardChange::REMOVE, name1_, NULL); + EXPECT_CALL( + *observer_helper_->observer(), + Observe(NotificationType(NotificationType::AUTOFILL_CREDIT_CARD_CHANGED), + Source<WebDataService>(wds_.get()), + Property(&Details<const AutofillCreditCardChange>::ptr, + Pointee(expected_change)))). + WillOnce(SignalEvent(&done_event_)); + wds_->RemoveCreditCard(card.guid()); + done_event_.TimedWait(test_timeout_); + + // Check that it was removed. + AutofillWebDataServiceConsumer<std::vector<CreditCard*> > consumer2; + WebDataService::Handle handle2 = wds_->GetCreditCards(&consumer2); + MessageLoop::current()->Run(); + EXPECT_EQ(handle2, consumer2.handle()); + ASSERT_EQ(0U, consumer2.result().size()); +} + TEST_F(WebDataServiceAutofillTest, CreditUpdate) { CreditCard card1(name1_, unique_id1_); CreditCard card2(name2_, unique_id2_); diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc index 4ecdbab..5fa538b 100644 --- a/chrome/browser/webdata/web_database.cc +++ b/chrome/browser/webdata/web_database.cc @@ -21,6 +21,7 @@ #include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/credit_card.h" #include "chrome/browser/diagnostics/sqlite_diagnostics.h" +#include "chrome/browser/guid.h" #include "chrome/browser/history/history_database.h" #include "chrome/browser/password_manager/encryptor.h" #include "chrome/browser/search_engines/template_url.h" @@ -125,6 +126,13 @@ using webkit_glue::PasswordForm; // phone // fax // date_modified The date on which this profile was last modified. +// Added in version 30. +// guid A guid string to uniquely identify the profile. This +// will eventually replace the unique_id above. We need +// to keep both during the transition. +// Added in version 31. +// TODO(dhollowa): Deprecate and remove unique_id. +// http://crbug.com/58813 // // credit_cards This table contains credit card data added by the user // with the AutoFill dialog. Most of the columns are @@ -151,6 +159,13 @@ using webkit_glue::PasswordForm; // card_number_encrypted Stores encrypted credit card number. // verification_code_encrypted The CVC/CVV/CVV2 card security code. // date_modified The date on which this entry was last modified. +// Added in version 30. +// guid A guid string to uniquely identify the profile. This +// will eventually replace the unique_id above. We need +// to keep both during the transition. +// Added in version 31. +// TODO(dhollowa): Deprecate and remove unique_id. +// http://crbug.com/58813 // // web_app_icons // url URL of the web app. @@ -173,8 +188,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 = 30; -const int kCompatibleVersionNumber = 30; +const int kCurrentVersionNumber = 31; +const int kCompatibleVersionNumber = 31; // ID of the url column in keywords. const int kUrlIdPosition = 16; @@ -293,11 +308,13 @@ void BindAutoFillProfileToStatement(const AutoFillProfile& profile, text = profile.GetFieldText(AutoFillType(PHONE_FAX_WHOLE_NUMBER)); s->BindString16(14, LimitDataSize(text)); s->BindInt64(15, Time::Now().ToTimeT()); + DCHECK(guid::IsValidGUID(profile.guid())); + s->BindString(16, profile.guid()); } AutoFillProfile* AutoFillProfileFromStatement(const sql::Statement& s) { - AutoFillProfile* profile = new AutoFillProfile( - s.ColumnString16(0), s.ColumnInt(1)); + AutoFillProfile* profile = new AutoFillProfile(s.ColumnString16(0), + s.ColumnInt(1)); profile->SetInfo(AutoFillType(NAME_FIRST), s.ColumnString16(2)); profile->SetInfo(AutoFillType(NAME_MIDDLE), @@ -325,6 +342,8 @@ AutoFillProfile* AutoFillProfileFromStatement(const sql::Statement& s) { profile->SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER), s.ColumnString16(14)); // Intentionally skip column 15, which stores the profile's modification date. + profile->set_guid(s.ColumnString(16)); + DCHECK(guid::IsValidGUID(profile->guid())); return profile; } @@ -359,11 +378,12 @@ void BindCreditCardToStatement(const CreditCard& credit_card, text.clear(); s->BindBlob(11, text.data(), static_cast<int>(text.length())); s->BindInt64(12, Time::Now().ToTimeT()); + DCHECK(guid::IsValidGUID(credit_card.guid())); + s->BindString(13, credit_card.guid()); } CreditCard* CreditCardFromStatement(const sql::Statement& s) { - CreditCard* credit_card = new CreditCard( - s.ColumnString16(0), s.ColumnInt(1)); + CreditCard* credit_card = new CreditCard(s.ColumnString16(0), s.ColumnInt(1)); credit_card->SetInfo(AutoFillType(CREDIT_CARD_NAME), s.ColumnString16(2)); credit_card->SetInfo(AutoFillType(CREDIT_CARD_TYPE), @@ -393,6 +413,8 @@ CreditCard* CreditCardFromStatement(const sql::Statement& s) { // Column 10 is processed above. // We don't store the encrypted CVV anymore. // Intentionally skip column 12, which stores the modification date. + credit_card->set_guid(s.ColumnString(13)); + DCHECK(guid::IsValidGUID(credit_card->guid())); return credit_card; } @@ -759,7 +781,8 @@ bool WebDatabase::InitAutoFillProfilesTable() { "country VARCHAR, " "phone VARCHAR, " "fax VARCHAR, " - "date_modified INTEGER NOT NULL DEFAULT 0)")) { + "date_modified INTEGER NOT NULL DEFAULT 0, " + "guid VARCHAR NOT NULL DEFAULT \"\")")) { NOTREACHED(); return false; } @@ -787,7 +810,8 @@ bool WebDatabase::InitCreditCardsTable() { "shipping_address VARCHAR, " "card_number_encrypted BLOB, " "verification_code_encrypted BLOB, " - "date_modified INTEGER NOT NULL DEFAULT 0)")) { + "date_modified INTEGER NOT NULL DEFAULT 0, " + "guid VARCHAR NOT NULL DEFAULT \"\")")) { NOTREACHED(); return false; } @@ -797,6 +821,7 @@ bool WebDatabase::InitCreditCardsTable() { return false; } } + return true; } @@ -1636,8 +1661,8 @@ bool WebDatabase::AddAutoFillProfile(const AutoFillProfile& profile) { "INSERT INTO autofill_profiles" "(label, unique_id, first_name, middle_name, last_name, email," " company_name, address_line_1, address_line_2, city, state, zipcode," - " country, phone, fax, date_modified)" - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); + " country, phone, fax, date_modified, guid)" + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); if (!s) { NOTREACHED() << "Statement prepare failed"; return false; @@ -1657,7 +1682,10 @@ bool WebDatabase::GetAutoFillProfileForLabel(const string16& label, AutoFillProfile** profile) { DCHECK(profile); sql::Statement s(db_.GetUniqueStatement( - "SELECT * FROM autofill_profiles " + "SELECT label, unique_id, first_name, middle_name, last_name, email, " + "company_name, address_line_1, address_line_2, city, state, zipcode, " + "country, phone, fax, date_modified, guid " + "FROM autofill_profiles " "WHERE label = ?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1673,12 +1701,40 @@ bool WebDatabase::GetAutoFillProfileForLabel(const string16& label, return s.Succeeded(); } +bool WebDatabase::GetAutoFillProfileForGUID(const std::string& guid, + AutoFillProfile** profile) { + DCHECK(guid::IsValidGUID(guid)); + DCHECK(profile); + sql::Statement s(db_.GetUniqueStatement( + "SELECT label, unique_id, first_name, middle_name, last_name, email, " + "company_name, address_line_1, address_line_2, city, state, zipcode, " + "country, phone, fax, date_modified, guid " + "FROM autofill_profiles " + "WHERE guid = ?")); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.BindString(0, guid); + if (!s.Step()) + return false; + + *profile = AutoFillProfileFromStatement(s); + + return s.Succeeded(); +} + bool WebDatabase::GetAutoFillProfiles( std::vector<AutoFillProfile*>* profiles) { DCHECK(profiles); profiles->clear(); - sql::Statement s(db_.GetUniqueStatement("SELECT * FROM autofill_profiles")); + sql::Statement s(db_.GetUniqueStatement( + "SELECT label, unique_id, first_name, middle_name, last_name, email, " + "company_name, address_line_1, address_line_2, city, state, zipcode, " + "country, phone, fax, date_modified, guid " + "FROM autofill_profiles")); if (!s) { NOTREACHED() << "Statement prepare failed"; return false; @@ -1697,7 +1753,7 @@ bool WebDatabase::UpdateAutoFillProfile(const AutoFillProfile& profile) { "SET label=?, unique_id=?, first_name=?, middle_name=?, last_name=?, " " email=?, company_name=?, address_line_1=?, address_line_2=?, " " city=?, state=?, zipcode=?, country=?, phone=?, fax=?, " - " date_modified=? " + " date_modified=?, guid=? " "WHERE unique_id=?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1705,7 +1761,7 @@ bool WebDatabase::UpdateAutoFillProfile(const AutoFillProfile& profile) { } BindAutoFillProfileToStatement(profile, &s); - s.BindInt(16, profile.unique_id()); + s.BindInt(17, profile.unique_id()); bool result = s.Run(); DCHECK_GT(db_.GetLastChangeCount(), 0); return result; @@ -1724,10 +1780,26 @@ bool WebDatabase::RemoveAutoFillProfile(int profile_id) { return s.Run(); } +bool WebDatabase::RemoveAutoFillProfile(const std::string& guid) { + DCHECK(guid::IsValidGUID(guid)); + sql::Statement s(db_.GetUniqueStatement( + "DELETE FROM autofill_profiles WHERE guid = ?")); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.BindString(0, guid); + return s.Run(); +} + bool WebDatabase::GetAutoFillProfileForID(int profile_id, AutoFillProfile** profile) { sql::Statement s(db_.GetUniqueStatement( - "SELECT * FROM autofill_profiles " + "SELECT label, unique_id, first_name, middle_name, last_name, email, " + "company_name, address_line_1, address_line_2, city, state, zipcode, " + "country, phone, fax, date_modified, guid " + "FROM autofill_profiles " "WHERE unique_id = ?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1746,8 +1818,9 @@ bool WebDatabase::AddCreditCard(const CreditCard& credit_card) { "INSERT INTO credit_cards" "(label, unique_id, name_on_card, type, card_number, expiration_month," " expiration_year, verification_code, billing_address, shipping_address," - " card_number_encrypted, verification_code_encrypted, date_modified)" - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)")); + " card_number_encrypted, verification_code_encrypted, date_modified," + " guid)" + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); if (!s) { NOTREACHED() << "Statement prepare failed"; return false; @@ -1768,7 +1841,11 @@ bool WebDatabase::GetCreditCardForLabel(const string16& label, CreditCard** credit_card) { DCHECK(credit_card); sql::Statement s(db_.GetUniqueStatement( - "SELECT * FROM credit_cards " + "SELECT label, unique_id, name_on_card, type, card_number, " + "expiration_month, expiration_year, verification_code, billing_address, " + "shipping_address, card_number_encrypted, verification_code_encrypted, " + "date_modified, guid " + "FROM credit_cards " "WHERE label = ?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1787,7 +1864,11 @@ bool WebDatabase::GetCreditCardForLabel(const string16& label, bool WebDatabase::GetCreditCardForID(int credit_card_id, CreditCard** credit_card) { sql::Statement s(db_.GetUniqueStatement( - "SELECT * FROM credit_cards " + "SELECT label, unique_id, name_on_card, type, card_number, " + "expiration_month, expiration_year, verification_code, billing_address, " + "shipping_address, card_number_encrypted, verification_code_encrypted, " + "date_modified, guid " + "FROM credit_cards " "WHERE unique_id = ?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1803,12 +1884,41 @@ bool WebDatabase::GetCreditCardForID(int credit_card_id, return s.Succeeded(); } +bool WebDatabase::GetCreditCardForGUID(const std::string& guid, + CreditCard** credit_card) { + DCHECK(guid::IsValidGUID(guid)); + sql::Statement s(db_.GetUniqueStatement( + "SELECT label, unique_id, name_on_card, type, card_number, " + "expiration_month, expiration_year, verification_code, billing_address, " + "shipping_address, card_number_encrypted, verification_code_encrypted, " + "date_modified, guid " + "FROM credit_cards " + "WHERE guid = ?")); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.BindString(0, guid); + if (!s.Step()) + return false; + + *credit_card = CreditCardFromStatement(s); + + return s.Succeeded(); +} + bool WebDatabase::GetCreditCards( std::vector<CreditCard*>* credit_cards) { DCHECK(credit_cards); credit_cards->clear(); - sql::Statement s(db_.GetUniqueStatement("SELECT * FROM credit_cards")); + sql::Statement s(db_.GetUniqueStatement( + "SELECT label, unique_id, name_on_card, type, card_number, " + "expiration_month, expiration_year, verification_code, billing_address, " + "shipping_address, card_number_encrypted, verification_code_encrypted, " + "date_modified, guid " + "FROM credit_cards")); if (!s) { NOTREACHED() << "Statement prepare failed"; return false; @@ -1827,7 +1937,7 @@ bool WebDatabase::UpdateCreditCard(const CreditCard& credit_card) { "SET label=?, unique_id=?, name_on_card=?, type=?, card_number=?, " " expiration_month=?, expiration_year=?, verification_code=?, " " billing_address=?, shipping_address=?, card_number_encrypted=?, " - " verification_code_encrypted=?, date_modified=? " + " verification_code_encrypted=?, date_modified=?, guid=?" "WHERE unique_id=?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1835,7 +1945,7 @@ bool WebDatabase::UpdateCreditCard(const CreditCard& credit_card) { } BindCreditCardToStatement(credit_card, &s); - s.BindInt(13, credit_card.unique_id()); + s.BindInt(14, credit_card.unique_id()); bool result = s.Run(); DCHECK_GT(db_.GetLastChangeCount(), 0); return result; @@ -1854,6 +1964,19 @@ bool WebDatabase::RemoveCreditCard(int credit_card_id) { return s.Run(); } +bool WebDatabase::RemoveCreditCard(const std::string& guid) { + DCHECK(guid::IsValidGUID(guid)); + sql::Statement s(db_.GetUniqueStatement( + "DELETE FROM credit_cards WHERE guid = ?")); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return false; + } + + s.BindString(0, guid); + return s.Run(); +} + bool WebDatabase::RemoveAutoFillProfilesAndCreditCardsModifiedBetween( base::Time delete_begin, base::Time delete_end) { @@ -2356,7 +2479,6 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){ NOTREACHED(); return sql::INIT_FAILURE; } - } meta_table_.SetVersionNumber(30); @@ -2365,6 +2487,100 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){ // FALL THROUGH + case 30: + // Add |guid| column to |autofill_profiles| table. + // Note that we need to check for the guid column's existence due to the + // fact that for a version 22 database the |autofill_profiles| table + // gets created fresh with |InitAutoFillProfilesTable|. + if (!db_.DoesColumnExist("autofill_profiles", "guid")) { + if (!db_.Execute("ALTER TABLE autofill_profiles ADD COLUMN " + "guid VARCHAR NOT NULL DEFAULT \"\"")) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + } + + // Set all the |guid| fields to valid values. + { + sql::Statement s(db_.GetUniqueStatement("SELECT unique_id " + "FROM autofill_profiles")); + + if (!s) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + while (s.Step()) { + sql::Statement update_s( + db_.GetUniqueStatement("UPDATE autofill_profiles " + "SET guid=? WHERE unique_id=?")); + if (!update_s) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + update_s.BindString(0, guid::GenerateGUID()); + update_s.BindInt(1, s.ColumnInt(0)); + + if (!update_s.Run()) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + } + } + + // Add |guid| column to |credit_cards| table. + // Note that we need to check for the guid column's existence due to the + // fact that for a version 22 database the |autofill_profiles| table + // gets created fresh with |InitAutoFillProfilesTable|. + if (!db_.DoesColumnExist("credit_cards", "guid")) { + if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " + "guid VARCHAR NOT NULL DEFAULT \"\"")) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + } + + // Set all the |guid| fields to valid values. + { + sql::Statement s(db_.GetUniqueStatement("SELECT unique_id " + "FROM credit_cards")); + if (!s) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + while (s.Step()) { + sql::Statement update_s( + db_.GetUniqueStatement("UPDATE credit_cards " + "set guid=? WHERE unique_id=?")); + if (!update_s) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + update_s.BindString(0, guid::GenerateGUID()); + update_s.BindInt(1, s.ColumnInt(0)); + + if (!update_s.Run()) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + } + } + + meta_table_.SetVersionNumber(31); + meta_table_.SetCompatibleVersionNumber( + std::min(31, 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 14b59bf..e7fd295 100644 --- a/chrome/browser/webdata/web_database.h +++ b/chrome/browser/webdata/web_database.h @@ -228,15 +228,29 @@ class WebDatabase { // Removes a row from the autofill_profiles table. |profile_id| is the // unique ID of the profile to remove. + // DEPRECATED: In favor of |RemoveAutoFillProfile(const std::string& guid)|. + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 virtual bool RemoveAutoFillProfile(int profile_id); + // Removes a row from the autofill_profiles table. |guid| is the identifier + // of the profile to remove. + virtual bool RemoveAutoFillProfile(const std::string& guid); + // Retrieves profile for unique id |profile_id|, owned by caller. + // DEPRECATED: In favor of |GetAutoFillProfileForGUID(...)|. + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 bool GetAutoFillProfileForID(int profile_id, AutoFillProfile** profile); // Retrieves a profile with label |label|. The caller owns |profile|. + // DEPRECATED: In favor of |GetAutoFillProfileForGUID(...)|. + // TODO(dhollowa): Remove labels. http://crbug.com/58813 bool GetAutoFillProfileForLabel(const string16& label, AutoFillProfile** profile); + // Retrieves a profile with guid |guid|. The caller owns |profile|. + bool GetAutoFillProfileForGUID(const std::string& guid, + AutoFillProfile** profile); + // Retrieves all profiles in the database. Caller owns the returned profiles. virtual bool GetAutoFillProfiles(std::vector<AutoFillProfile*>* profiles); @@ -248,16 +262,30 @@ class WebDatabase { // Removes a row from the credit_cards table. |credit_card_id| is the // unique ID of the credit card to remove. + // DEPRECATED: In favor of |RemoveCreditCard(const std::string& guid)|. + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 bool RemoveCreditCard(int credit_card_id); + // Removes a row from the credit_cards table. |guid| is the identifer of the + // credit card to remove. + bool RemoveCreditCard(const std::string& guid); + // Retrieves a credit card with label |label|. The caller owns // |credit_card_id|. + // DEPRECATED: In favor of |GetCreditCardForGUID()|. + // TODO(dhollowa): Remove labels. http://crbug.com/58813 bool GetCreditCardForLabel(const string16& label, - CreditCard** credit_card); + CreditCard** credit_card); // Retrieves credit card for a card with unique id |credit_card_id|. + // DEPRECATED: In favor of |GetCreditCardForGUID()|. + // TODO(dhollowa): Remove unique IDs. http://crbug.com/58813 bool GetCreditCardForID(int credit_card_id, CreditCard** credit_card); + // Retrieves a credit card with guid |guid|. The caller owns + // |credit_card_id|. + bool GetCreditCardForGUID(const std::string& guid, CreditCard** credit_card); + // Retrieves all credit cards in the database. Caller owns the returned // credit cards. virtual bool GetCreditCards(std::vector<CreditCard*>* credit_cards); diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc index 15615d6..584b4ed 100644 --- a/chrome/browser/webdata/web_database_unittest.cc +++ b/chrome/browser/webdata/web_database_unittest.cc @@ -22,6 +22,7 @@ #include "chrome/browser/autofill/autofill_profile.h" #include "chrome/browser/autofill/autofill_type.h" #include "chrome/browser/autofill/credit_card.h" +#include "chrome/browser/guid.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/password_manager/encryptor.h" #include "chrome/browser/webdata/autofill_change.h" @@ -62,6 +63,8 @@ std::ostream& operator<<(std::ostream& os, const AutofillChange& change) { return os << " " << change.key(); } +namespace { + bool CompareAutofillEntries(const AutofillEntry& a, const AutofillEntry& b) { std::set<base::Time> timestamps1(a.timestamps().begin(), a.timestamps().end()); @@ -90,6 +93,8 @@ bool CompareAutofillEntries(const AutofillEntry& a, const AutofillEntry& b) { return timestamps2.size() != 0U; } +} // namespace + class WebDatabaseTest : public testing::Test { public: WebDatabaseTest() {} @@ -1298,6 +1303,7 @@ TEST_F(WebDatabaseTest, AutoFillProfile) { ASCIIToUTF16("5678 Bottom Street")); billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE2), ASCIIToUTF16("suite 3")); + billing_profile.set_guid(guid::GenerateGUID()); pre_creation_time = Time::Now(); EXPECT_TRUE(db.AddAutoFillProfile(billing_profile)); @@ -1339,6 +1345,35 @@ TEST_F(WebDatabaseTest, AutoFillProfile) { EXPECT_TRUE(db.RemoveAutoFillProfile(billing_profile.unique_id())); EXPECT_FALSE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"), &db_profile)); + + // Add a 'GUID' profile. + AutoFillProfile guid_profile = home_profile; + guid_profile.set_label(ASCIIToUTF16("GUID")); + guid_profile.set_unique_id(14); + guid_profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE1), + ASCIIToUTF16("5678 Top Street")); + guid_profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE2), + ASCIIToUTF16("suite 4")); + guid_profile.set_guid(guid::GenerateGUID()); + + EXPECT_TRUE(db.AddAutoFillProfile(guid_profile)); + ASSERT_TRUE(db.GetAutoFillProfileForGUID(guid_profile.guid(), + &db_profile)); + EXPECT_EQ(guid_profile, *db_profile); + delete db_profile; + + // Update the 'GUID' profile. + guid_profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Jimmy")); + EXPECT_TRUE(db.UpdateAutoFillProfile(guid_profile)); + ASSERT_TRUE(db.GetAutoFillProfileForGUID(guid_profile.guid(), + &db_profile)); + EXPECT_EQ(guid_profile, *db_profile); + delete db_profile; + + // Remove the 'GUID' profile. + EXPECT_TRUE(db.RemoveAutoFillProfile(guid_profile.guid())); + EXPECT_FALSE(db.GetAutoFillProfileForGUID(guid_profile.guid(), + &db_profile)); } TEST_F(WebDatabaseTest, CreditCard) { @@ -1429,6 +1464,39 @@ TEST_F(WebDatabaseTest, CreditCard) { EXPECT_TRUE(db.RemoveCreditCard(target_creditcard.unique_id())); EXPECT_FALSE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), &db_creditcard)); + + // Add a 'GUID' profile. + CreditCard guid_creditcard(ASCIIToUTF16("GUID"), 7); + guid_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME), + ASCIIToUTF16("Jimmy Jones")); + guid_creditcard.SetInfo(AutoFillType(CREDIT_CARD_TYPE), + ASCIIToUTF16("Amex")); + guid_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NUMBER), + ASCIIToUTF16("9999222233334444")); + guid_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_MONTH), + ASCIIToUTF16("07")); + guid_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), + ASCIIToUTF16("2013")); + guid_creditcard.set_billing_address_id(1); + + EXPECT_TRUE(db.AddCreditCard(guid_creditcard)); + ASSERT_TRUE(db.GetCreditCardForGUID(guid_creditcard.guid(), + &db_creditcard)); + EXPECT_EQ(guid_creditcard, *db_creditcard); + delete db_creditcard; + + // Update the 'GUID' profile. + guid_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME), + ASCIIToUTF16("Jimmy Grady")); + EXPECT_TRUE(db.UpdateCreditCard(guid_creditcard)); + ASSERT_TRUE(db.GetCreditCardForGUID(guid_creditcard.guid(), &db_creditcard)); + EXPECT_EQ(guid_creditcard, *db_creditcard); + delete db_creditcard; + + // Remove the 'GUID' profile. + EXPECT_TRUE(db.RemoveCreditCard(guid_creditcard.guid())); + EXPECT_FALSE(db.GetCreditCardForGUID(guid_creditcard.guid(), + &db_creditcard)); } TEST_F(WebDatabaseTest, RemoveAutoFillProfilesAndCreditCardsModifiedBetween) { @@ -1438,29 +1506,29 @@ TEST_F(WebDatabaseTest, RemoveAutoFillProfilesAndCreditCardsModifiedBetween) { // Populate the autofill_profiles and credit_cards tables. ASSERT_TRUE(db.db_.Execute( "INSERT INTO \"autofill_profiles\" VALUES('P1',1,'','','','','','','',''," - "'','','','','',11);" + "'','','','','',11,'00000000-0000-0000-0000-000000000000');" "INSERT INTO \"autofill_profiles\" VALUES('P2',2,'','','','','','','',''," - "'','','','','',21);" + "'','','','','',21,'00000000-0000-0000-0000-000000000001');" "INSERT INTO \"autofill_profiles\" VALUES('P3',3,'','','','','','','',''," - "'','','','','',31);" + "'','','','','',31,'00000000-0000-0000-0000-000000000002');" "INSERT INTO \"autofill_profiles\" VALUES('P4',4,'','','','','','','',''," - "'','','','','',41);" + "'','','','','',41,'00000000-0000-0000-0000-000000000003');" "INSERT INTO \"autofill_profiles\" VALUES('P5',5,'','','','','','','',''," - "'','','','','',51);" + "'','','','','',51,'00000000-0000-0000-0000-000000000004');" "INSERT INTO \"autofill_profiles\" VALUES('P6',6,'','','','','','','',''," - "'','','','','',61);" + "'','','','','',61,'00000000-0000-0000-0000-000000000005');" "INSERT INTO \"credit_cards\" VALUES('C10',10,'','','',10,2010,'','',''," - "X'',X'',17);" + "X'',X'',17,'00000000-0000-0000-0000-000000000006');" "INSERT INTO \"credit_cards\" VALUES('C20',20,'','','',10,2010,'','',''," - "X'',X'',27);" + "X'',X'',27,'00000000-0000-0000-0000-000000000007');" "INSERT INTO \"credit_cards\" VALUES('C30',30,'','','',10,2010,'','',''," - "X'',X'',37);" + "X'',X'',37,'00000000-0000-0000-0000-000000000008');" "INSERT INTO \"credit_cards\" VALUES('C40',40,'','','',10,2010,'','',''," - "X'',X'',47);" + "X'',X'',47,'00000000-0000-0000-0000-000000000009');" "INSERT INTO \"credit_cards\" VALUES('C50',50,'','','',10,2010,'','',''," - "X'',X'',57);" + "X'',X'',57,'00000000-0000-0000-0000-000000000010');" "INSERT INTO \"credit_cards\" VALUES('C60',60,'','','',10,2010,'','',''," - "X'',X'',67);")); + "X'',X'',67,'00000000-0000-0000-0000-000000000011');")); // Remove all entries modified in the bounded time range [17,41). db.RemoveAutoFillProfilesAndCreditCardsModifiedBetween( @@ -1721,6 +1789,7 @@ class WebDatabaseMigrationTest : public testing::Test { void SetUpVersion27Database(); void SetUpVersion28Database(); void SetUpVersion29Database(); + void SetUpVersion30Database(); // Assertion testing for migrating from version 27 and 28. void MigrateVersion28Assertions(); @@ -1731,7 +1800,7 @@ class WebDatabaseMigrationTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest); }; -const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 30; +const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 31; // This schema is taken from a build prior to the addition of the |credit_card| // table. Version 22 of the schema. Contrast this with the corrupt version @@ -2029,8 +2098,8 @@ void WebDatabaseMigrationTest::SetUpVersion26Database() { ASSERT_TRUE(connection.Execute( "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY," "value LONGVARCHAR);" - "INSERT INTO \"meta\" VALUES('version','25');" - "INSERT INTO \"meta\" VALUES('last_compatible_version','25');" + "INSERT INTO \"meta\" VALUES('version','26');" + "INSERT INTO \"meta\" VALUES('last_compatible_version','26');" "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," @@ -2296,6 +2365,103 @@ void WebDatabaseMigrationTest::SetUpVersion29Database() { ASSERT_TRUE(connection.CommitTransaction()); } +// TODO(dhollowa): Move these sql dumps to external files and load them +// dynamically. http://crbug.com/59685 +void WebDatabaseMigrationTest::SetUpVersion30Database() { + sql::Connection connection; + ASSERT_TRUE(connection.Open(GetDatabasePath())); + ASSERT_TRUE(connection.BeginTransaction()); + ASSERT_TRUE(connection.Execute( + "CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY," + "value LONGVARCHAR);" + "INSERT INTO \"meta\" VALUES('version','30');" + "INSERT INTO \"meta\" VALUES('last_compatible_version','30');" + "INSERT INTO \"meta\" VALUES('Default Search Provider ID','2');" + "INSERT INTO \"meta\" VALUES('Builtin Keyword Version','30');" + "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,6245,0,'{google:baseURL}search?{google:RLZ}" + "sourceid=chrome-instant&ie={inputEncoding}&q={searchTerms}');" + "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,6262,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,6239,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 ( label VARCHAR, " + "unique_id INTEGER PRIMARY KEY, 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('Jim Johnson, 789 4th Street'," + "1,'Jim','','Johnson','jim@acme.com','Acme Inc.','789 4th Street'," + "'Apt. #4','San Francisco','CA','94102','USA','4155512255'," + "'4155512233',1287508123);" + "INSERT INTO \"autofill_profiles\" VALUES('Billy Jean, 1 Ghost Blvd.',3," + "'Billy','','Jean','billy@thriller.com','Thriller Inc.'," + "'1 Ghost Blvd.','','Santa Monica','CA','98990','USA','4431110000',''," + "1287508123);" + "CREATE TABLE credit_cards ( label VARCHAR, unique_id " + "INTEGER PRIMARY KEY, name_on_card VARCHAR, type VARCHAR, " + "card_number VARCHAR, expiration_month INTEGER, expiration_year " + "INTEGER, verification_code VARCHAR, billing_address VARCHAR, " + "shipping_address VARCHAR, card_number_encrypted BLOB, " + "verification_code_encrypted BLOB, date_modified INTEGER NOT NULL " + "DEFAULT 0);" + "INSERT INTO \"credit_cards\" VALUES('',2,'Jim X Johnson','','',1,2011," + "'','1','',X'763130B83A1BEE0CFD7C447C270685B5E2BFF5EC0BC700B38F4C4DD" + "60CDD5D8D66EB09',X'',1287508123);" + "INSERT INTO \"credit_cards\" VALUES('2',4,'Billy X Jean','','',7,2017," + "'','3','',X'763130EB3DC27FA61AAC9EAC92B303978DD7B62E901B4D9DFB459905" + "E09AAAE7AE7BA1',X'',1287508123);" + "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);" + )); + ASSERT_TRUE(connection.CommitTransaction()); +} + void WebDatabaseMigrationTest::MigrateVersion28Assertions() { // Load the database via the WebDatabase class and migrate the database to // the current version. @@ -2556,17 +2722,15 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion25ToCurrent) { // the test makes sure a stored label is converted to an ID. TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringLabels) { // Initialize the database. - SetUpVersion25Database(); + SetUpVersion26Database(); - // Verify pre-conditions. These are expectations for version 25 of the + // Verify pre-conditions. These are expectations for version 26 of the // database. { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); // Columns existing and not existing before current version. - ASSERT_TRUE(connection.DoesColumnExist("keywords", "id")); - ASSERT_FALSE(connection.DoesColumnExist("keywords", "created_by_policy")); EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); std::string stmt = "INSERT INTO autofill_profiles" @@ -2634,9 +2798,9 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringLabels) { // the test makes sure a stored string ID is converted to an integer ID. TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringIDs) { // Initialize the database. - SetUpVersion25Database(); + SetUpVersion26Database(); - // Verify pre-conditions. These are expectations for version 25 of the + // Verify pre-conditions. These are expectations for version 26 of the // database. { sql::Connection connection; @@ -2807,3 +2971,53 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion29ToCurrent) { EXPECT_TRUE(s_credit_cards.Succeeded()); } } + +// Makes sure guids are added to autofill_profiles and credit_cards tables. +TEST_F(WebDatabaseMigrationTest, MigrateVersion30ToCurrent) { + SetUpVersion30Database(); + + // Verify pre-conditions. These are expectations for version 29 of the + // database. + { + sql::Connection connection; + ASSERT_TRUE(connection.Open(GetDatabasePath())); + + EXPECT_FALSE(connection.DoesColumnExist("autofill_profiles", "guid")); + EXPECT_FALSE(connection.DoesColumnExist("credit_cards", "guid")); + } + + // 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)); + + ASSERT_TRUE(connection.DoesColumnExist("autofill_profiles", "guid")); + ASSERT_TRUE(connection.DoesColumnExist("credit_cards", "guid")); + + // Check that guids are non-null, non-empty, conforms to guid format, and + // are different. + sql::Statement s( + connection.GetUniqueStatement("SELECT guid FROM autofill_profiles")); + + ASSERT_TRUE(s.Step()); + std::string guid1 = s.ColumnString(0); + EXPECT_TRUE(guid::IsValidGUID(guid1)); + + ASSERT_TRUE(s.Step()); + std::string guid2 = s.ColumnString(0); + EXPECT_TRUE(guid::IsValidGUID(guid2)); + + EXPECT_NE(guid1, guid2); + } +} |