diff options
author | isherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-19 00:14:58 +0000 |
---|---|---|
committer | isherman@chromium.org <isherman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-19 00:14:58 +0000 |
commit | 18f92d4f0942235f2aac9290b43dc426626427f6 (patch) | |
tree | c342a8e9623a26c6054cbacaa3bfa51daca5f90a /chrome/browser/webdata | |
parent | e3b16e356ac41268eeb28c6329256d03ceb6a87e (diff) | |
download | chromium_src-18f92d4f0942235f2aac9290b43dc426626427f6.zip chromium_src-18f92d4f0942235f2aac9290b43dc426626427f6.tar.gz chromium_src-18f92d4f0942235f2aac9290b43dc426626427f6.tar.bz2 |
Clear AutoFill data along with Form Autocomplete data from Clear Browsing Data dialog
BUG=49128
TEST=none
Review URL: http://codereview.chromium.org/3807009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62997 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/webdata')
-rw-r--r-- | chrome/browser/webdata/web_data_service.cc | 31 | ||||
-rw-r--r-- | chrome/browser/webdata/web_data_service.h | 7 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.cc | 157 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.h | 10 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database_unittest.cc | 292 |
5 files changed, 472 insertions, 25 deletions
diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc index 138596a..04c9c47 100644 --- a/chrome/browser/webdata/web_data_service.cc +++ b/chrome/browser/webdata/web_data_service.cc @@ -470,6 +470,22 @@ WebDataService::Handle WebDataService::GetCreditCards( return request->GetHandle(); } +void WebDataService::RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + const Time& delete_begin, + const Time& delete_end) { + GenericRequest2<Time, Time>* request = + new GenericRequest2<Time, Time>(this, + GetNextRequestHandle(), + NULL, + delete_begin, + delete_end); + RegisterRequest(request); + ScheduleTask(NewRunnableMethod( + this, + &WebDataService::RemoveAutoFillProfilesAndCreditCardsModifiedBetweenImpl, + request)); +} + WebDataService::~WebDataService() { if (is_running_ && db_) { DLOG_ASSERT("WebDataService dtor called without Shutdown"); @@ -1128,6 +1144,21 @@ void WebDataService::GetCreditCardsImpl(WebDataRequest* request) { request->RequestComplete(); } +void WebDataService::RemoveAutoFillProfilesAndCreditCardsModifiedBetweenImpl( + GenericRequest2<Time, Time>* request) { + InitializeDatabaseIfNecessary(); + if (db_ && !request->IsCancelled()) { + if (db_->RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + request->GetArgument1(), + request->GetArgument2())) { + // Note: It is the caller's responsibility to post notifications for any + // changes, e.g. by calling the Refresh() method of PersonalDataManager. + ScheduleCommit(); + } + } + request->RequestComplete(); +} + //////////////////////////////////////////////////////////////////////////////// // // WebDataRequest implementation. diff --git a/chrome/browser/webdata/web_data_service.h b/chrome/browser/webdata/web_data_service.h index b3cf46b..9062d07 100644 --- a/chrome/browser/webdata/web_data_service.h +++ b/chrome/browser/webdata/web_data_service.h @@ -465,6 +465,11 @@ class WebDataService // consumer owns the credit cards. Handle GetCreditCards(WebDataServiceConsumer* consumer); + // Removes AutoFill records from the database. + void RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + const base::Time& delete_begin, + const base::Time& delete_end); + // Testing #ifdef UNIT_TEST void set_failed_init(bool value) { failed_init_ = value; } @@ -598,6 +603,8 @@ class WebDataService void UpdateCreditCardImpl(GenericRequest<CreditCard>* request); void RemoveCreditCardImpl(GenericRequest<int>* request); void GetCreditCardsImpl(WebDataRequest* request); + void RemoveAutoFillProfilesAndCreditCardsModifiedBetweenImpl( + GenericRequest2<base::Time, base::Time>* request); // True once initialization has started. bool is_running_; diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc index 4277a26..4ecdbab 100644 --- a/chrome/browser/webdata/web_database.cc +++ b/chrome/browser/webdata/web_database.cc @@ -124,6 +124,7 @@ using webkit_glue::PasswordForm; // country // phone // fax +// date_modified The date on which this profile was last modified. // // credit_cards This table contains credit card data added by the user // with the AutoFill dialog. Most of the columns are @@ -149,6 +150,7 @@ using webkit_glue::PasswordForm; // chrome/browser/sync/protocol/autofill_specifics.proto // 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. // // web_app_icons // url URL of the web app. @@ -171,8 +173,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 = 29; -const int kCompatibleVersionNumber = 29; +const int kCurrentVersionNumber = 30; +const int kCompatibleVersionNumber = 30; // ID of the url column in keywords. const int kUrlIdPosition = 16; @@ -290,6 +292,7 @@ void BindAutoFillProfileToStatement(const AutoFillProfile& profile, s->BindString16(13, LimitDataSize(text)); text = profile.GetFieldText(AutoFillType(PHONE_FAX_WHOLE_NUMBER)); s->BindString16(14, LimitDataSize(text)); + s->BindInt64(15, Time::Now().ToTimeT()); } AutoFillProfile* AutoFillProfileFromStatement(const sql::Statement& s) { @@ -321,6 +324,7 @@ AutoFillProfile* AutoFillProfileFromStatement(const sql::Statement& s) { s.ColumnString16(13)); profile->SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER), s.ColumnString16(14)); + // Intentionally skip column 15, which stores the profile's modification date. return profile; } @@ -354,6 +358,7 @@ void BindCreditCardToStatement(const CreditCard& credit_card, // We don't store the CVV anymore. text.clear(); s->BindBlob(11, text.data(), static_cast<int>(text.length())); + s->BindInt64(12, Time::Now().ToTimeT()); } CreditCard* CreditCardFromStatement(const sql::Statement& s) { @@ -386,7 +391,8 @@ CreditCard* CreditCardFromStatement(const sql::Statement& s) { credit_card->set_billing_address_id(s.ColumnInt(8)); // We don't store the shipping address anymore. // Column 10 is processed above. - // Column 11 is processed above. + // We don't store the encrypted CVV anymore. + // Intentionally skip column 12, which stores the modification date. return credit_card; } @@ -752,7 +758,8 @@ bool WebDatabase::InitAutoFillProfilesTable() { "zipcode VARCHAR, " "country VARCHAR, " "phone VARCHAR, " - "fax VARCHAR)")) { + "fax VARCHAR, " + "date_modified INTEGER NOT NULL DEFAULT 0)")) { NOTREACHED(); return false; } @@ -779,7 +786,8 @@ bool WebDatabase::InitCreditCardsTable() { "billing_address VARCHAR, " "shipping_address VARCHAR, " "card_number_encrypted BLOB, " - "verification_code_encrypted BLOB)")) { + "verification_code_encrypted BLOB, " + "date_modified INTEGER NOT NULL DEFAULT 0)")) { NOTREACHED(); return false; } @@ -1628,8 +1636,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)" - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); + " country, phone, fax, date_modified)" + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")); if (!s) { NOTREACHED() << "Statement prepare failed"; return false; @@ -1688,7 +1696,8 @@ bool WebDatabase::UpdateAutoFillProfile(const AutoFillProfile& profile) { "UPDATE autofill_profiles " "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=? " + " city=?, state=?, zipcode=?, country=?, phone=?, fax=?, " + " date_modified=? " "WHERE unique_id=?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1696,7 +1705,7 @@ bool WebDatabase::UpdateAutoFillProfile(const AutoFillProfile& profile) { } BindAutoFillProfileToStatement(profile, &s); - s.BindInt(15, profile.unique_id()); + s.BindInt(16, profile.unique_id()); bool result = s.Run(); DCHECK_GT(db_.GetLastChangeCount(), 0); return result; @@ -1735,10 +1744,10 @@ bool WebDatabase::GetAutoFillProfileForID(int profile_id, bool WebDatabase::AddCreditCard(const CreditCard& credit_card) { sql::Statement s(db_.GetUniqueStatement( "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)" - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)")); + "(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 (?,?,?,?,?,?,?,?,?,?,?,?,?)")); if (!s) { NOTREACHED() << "Statement prepare failed"; return false; @@ -1818,7 +1827,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=? " + " verification_code_encrypted=?, date_modified=? " "WHERE unique_id=?")); if (!s) { NOTREACHED() << "Statement prepare failed"; @@ -1826,7 +1835,7 @@ bool WebDatabase::UpdateCreditCard(const CreditCard& credit_card) { } BindCreditCardToStatement(credit_card, &s); - s.BindInt(12, credit_card.unique_id()); + s.BindInt(13, credit_card.unique_id()); bool result = s.Run(); DCHECK_GT(db_.GetLastChangeCount(), 0); return result; @@ -1845,6 +1854,56 @@ bool WebDatabase::RemoveCreditCard(int credit_card_id) { return s.Run(); } +bool WebDatabase::RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + base::Time delete_begin, + base::Time delete_end) { + DCHECK(!delete_begin.is_null()); + DCHECK(delete_end.is_null() || delete_begin < delete_end); + + time_t delete_begin_t = delete_begin.ToTimeT(); + time_t delete_end_t = delete_end.is_null() ? + std::numeric_limits<time_t>::max() : + delete_end.ToTimeT(); + + // Remove AutoFill profiles in the time range. + sql::Statement s_profiles(db_.GetUniqueStatement( + "DELETE FROM autofill_profiles " + "WHERE date_modified >= ? AND date_modified < ?")); + if (!s_profiles) { + NOTREACHED() << "AutoFill profiles statement prepare failed"; + return false; + } + + s_profiles.BindInt64(0, delete_begin_t); + s_profiles.BindInt64(1, delete_end_t); + s_profiles.Run(); + + if (!s_profiles.Succeeded()) { + NOTREACHED(); + return false; + } + + // Remove AutoFill profiles in the time range. + sql::Statement s_credit_cards(db_.GetUniqueStatement( + "DELETE FROM credit_cards " + "WHERE date_modified >= ? AND date_modified < ?")); + if (!s_credit_cards) { + NOTREACHED() << "AutoFill credit cards statement prepare failed"; + return false; + } + + s_credit_cards.BindInt64(0, delete_begin_t); + s_credit_cards.BindInt64(1, delete_end_t); + s_credit_cards.Run(); + + if (!s_credit_cards.Succeeded()) { + NOTREACHED(); + return false; + } + + return true; +} + bool WebDatabase::AddToCountOfFormElement(int64 pair_id, int delta, bool* was_removed) { @@ -2141,11 +2200,6 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){ return sql::INIT_FAILURE; } - meta_table_.SetVersionNumber(26); - meta_table_.SetCompatibleVersionNumber( - std::min(26, kCompatibleVersionNumber)); - // FALL THROUGH - for (std::map<int, int>::const_iterator iter = cc_billing_map.begin(); iter != cc_billing_map.end(); ++iter) { sql::Statement s(db_.GetCachedStatement( @@ -2248,6 +2302,69 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){ meta_table_.SetCompatibleVersionNumber( std::min(29, kCompatibleVersionNumber)); + // FALL THROUGH + + case 29: + // Add date_modified to autofill_profiles. + if (!db_.DoesColumnExist("autofill_profiles", "date_modified")) { + if (!db_.Execute("ALTER TABLE autofill_profiles ADD COLUMN " + "date_modified INTEGER NON NULL DEFAULT 0")) { + LOG(WARNING) << "Unable to update web database to version 30"; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + sql::Statement s(db_.GetUniqueStatement( + "UPDATE autofill_profiles SET date_modified=?")); + if (!s) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + s.BindInt64(0, Time::Now().ToTimeT()); + + if (!s.Run()) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + } + + // Add date_modified to credit_cards. + if (!db_.DoesColumnExist("credit_cards", "date_modified")) { + if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " + "date_modified INTEGER NON NULL DEFAULT 0")) { + LOG(WARNING) << "Unable to update web database to version 30"; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + sql::Statement s(db_.GetUniqueStatement( + "UPDATE credit_cards SET date_modified=?")); + if (!s) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + s.BindInt64(0, Time::Now().ToTimeT()); + + if (!s.Run()) { + LOG(WARNING) << "Unable to update web database to version 30."; + NOTREACHED(); + return sql::INIT_FAILURE; + } + + } + + meta_table_.SetVersionNumber(30); + meta_table_.SetCompatibleVersionNumber( + std::min(30, 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 697e2f2..14b59bf 100644 --- a/chrome/browser/webdata/web_database.h +++ b/chrome/browser/webdata/web_database.h @@ -262,6 +262,12 @@ class WebDatabase { // credit cards. virtual bool GetCreditCards(std::vector<CreditCard*>* credit_cards); + // Removes rows from autofill_profiles and credit_cards if they were created + // on or after |delete_begin| and strictly before |delete_end|. + bool RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + base::Time delete_begin, + base::Time delete_end); + ////////////////////////////////////////////////////////////////////////////// // // Web Apps @@ -308,6 +314,10 @@ class WebDatabase { Autofill_GetAllAutofillEntries_TwoSame); FRIEND_TEST_ALL_PREFIXES(WebDatabaseTest, Autofill_UpdateDontReplace); FRIEND_TEST_ALL_PREFIXES(WebDatabaseTest, Autofill_AddFormFieldValues); + FRIEND_TEST_ALL_PREFIXES(WebDatabaseTest, AutoFillProfile); + FRIEND_TEST_ALL_PREFIXES(WebDatabaseTest, CreditCard); + FRIEND_TEST_ALL_PREFIXES(WebDatabaseTest, + RemoveAutoFillProfilesAndCreditCardsModifiedBetween); // Methods for adding autofill entries at a specified time. For // testing only. diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc index 6132ad5..15615d6 100644 --- a/chrome/browser/webdata/web_database_unittest.cc +++ b/chrome/browser/webdata/web_database_unittest.cc @@ -107,7 +107,7 @@ class WebDatabaseTest : public testing::Test { #endif PathService::Get(chrome::DIR_TEST_DATA, &file_); const std::string test_db = "TestWebDatabase" + - base::Int64ToString(base::Time::Now().ToInternalValue()) + + base::Int64ToString(base::Time::Now().ToTimeT()) + ".db"; file_ = file_.AppendASCII(test_db); file_util::Delete(file_, false); @@ -1273,12 +1273,21 @@ TEST_F(WebDatabaseTest, AutoFillProfile) { home_profile.SetInfo(AutoFillType(PHONE_FAX_WHOLE_NUMBER), ASCIIToUTF16("1915243678")); + Time pre_creation_time = Time::Now(); EXPECT_TRUE(db.AddAutoFillProfile(home_profile)); + Time post_creation_time = Time::Now(); // Get the 'Home' profile. AutoFillProfile* db_profile; ASSERT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Home"), &db_profile)); EXPECT_EQ(home_profile, *db_profile); + sql::Statement s_home(db.db_.GetUniqueStatement( + "SELECT * FROM autofill_profiles WHERE label='Home'")); + ASSERT_TRUE(s_home); + ASSERT_TRUE(s_home.Step()); + EXPECT_GE(s_home.ColumnInt64(15), pre_creation_time.ToTimeT()); + EXPECT_LE(s_home.ColumnInt64(15), post_creation_time.ToTimeT()); + EXPECT_FALSE(s_home.Step()); delete db_profile; // Add a 'Billing' profile. @@ -1290,18 +1299,40 @@ TEST_F(WebDatabaseTest, AutoFillProfile) { billing_profile.SetInfo(AutoFillType(ADDRESS_HOME_LINE2), ASCIIToUTF16("suite 3")); + pre_creation_time = Time::Now(); EXPECT_TRUE(db.AddAutoFillProfile(billing_profile)); + post_creation_time = Time::Now(); + + // Get the 'Billing' profile. ASSERT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"), &db_profile)); EXPECT_EQ(billing_profile, *db_profile); + sql::Statement s_billing(db.db_.GetUniqueStatement( + "SELECT * FROM autofill_profiles WHERE label='Billing'")); + ASSERT_TRUE(s_billing); + ASSERT_TRUE(s_billing.Step()); + EXPECT_GE(s_billing.ColumnInt64(15), pre_creation_time.ToTimeT()); + EXPECT_LE(s_billing.ColumnInt64(15), post_creation_time.ToTimeT()); + EXPECT_FALSE(s_billing.Step()); delete db_profile; // Update the 'Billing' profile. billing_profile.SetInfo(AutoFillType(NAME_FIRST), ASCIIToUTF16("Jane")); + Time pre_modification_time = Time::Now(); EXPECT_TRUE(db.UpdateAutoFillProfile(billing_profile)); + Time post_modification_time = Time::Now(); ASSERT_TRUE(db.GetAutoFillProfileForLabel(ASCIIToUTF16("Billing"), &db_profile)); EXPECT_EQ(billing_profile, *db_profile); + sql::Statement s_billing_updated(db.db_.GetUniqueStatement( + "SELECT * FROM autofill_profiles WHERE label='Billing'")); + ASSERT_TRUE(s_billing_updated); + ASSERT_TRUE(s_billing_updated.Step()); + EXPECT_GE(s_billing_updated.ColumnInt64(15), + pre_modification_time.ToTimeT()); + EXPECT_LE(s_billing_updated.ColumnInt64(15), + post_modification_time.ToTimeT()); + EXPECT_FALSE(s_billing_updated.Step()); delete db_profile; // Remove the 'Billing' profile. @@ -1329,15 +1360,24 @@ TEST_F(WebDatabaseTest, CreditCard) { ASCIIToUTF16("2013")); work_creditcard.set_billing_address_id(1); + Time pre_creation_time = Time::Now(); EXPECT_TRUE(db.AddCreditCard(work_creditcard)); + Time post_creation_time = Time::Now(); // Get the 'Work' credit card. CreditCard* db_creditcard; ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Work"), &db_creditcard)); EXPECT_EQ(work_creditcard, *db_creditcard); + sql::Statement s_work(db.db_.GetUniqueStatement( + "SELECT * FROM credit_cards WHERE label='Work'")); + ASSERT_TRUE(s_work); + ASSERT_TRUE(s_work.Step()); + EXPECT_GE(s_work.ColumnInt64(12), pre_creation_time.ToTimeT()); + EXPECT_LE(s_work.ColumnInt64(12), post_creation_time.ToTimeT()); + EXPECT_FALSE(s_work.Step()); delete db_creditcard; - // Add a 'Target' profile. + // Add a 'Target' credit card. CreditCard target_creditcard(ASCIIToUTF16("Target"), 7); target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Jack Torrance")); @@ -1351,26 +1391,122 @@ TEST_F(WebDatabaseTest, CreditCard) { ASCIIToUTF16("2012")); target_creditcard.set_billing_address_id(1); + pre_creation_time = Time::Now(); EXPECT_TRUE(db.AddCreditCard(target_creditcard)); + post_creation_time = Time::Now(); ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), &db_creditcard)); EXPECT_EQ(target_creditcard, *db_creditcard); + sql::Statement s_target(db.db_.GetUniqueStatement( + "SELECT * FROM credit_cards WHERE label='Target'")); + ASSERT_TRUE(s_target); + ASSERT_TRUE(s_target.Step()); + EXPECT_GE(s_target.ColumnInt64(12), pre_creation_time.ToTimeT()); + EXPECT_LE(s_target.ColumnInt64(12), post_creation_time.ToTimeT()); + EXPECT_FALSE(s_target.Step()); delete db_creditcard; - // Update the 'Target' profile. + // Update the 'Target' credit card. target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME), ASCIIToUTF16("Charles Grady")); + Time pre_modification_time = Time::Now(); EXPECT_TRUE(db.UpdateCreditCard(target_creditcard)); + Time post_modification_time = Time::Now(); ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), &db_creditcard)); EXPECT_EQ(target_creditcard, *db_creditcard); + sql::Statement s_target_updated(db.db_.GetUniqueStatement( + "SELECT * FROM credit_cards WHERE label='Target'")); + ASSERT_TRUE(s_target_updated); + ASSERT_TRUE(s_target_updated.Step()); + EXPECT_GE(s_target_updated.ColumnInt64(12), + pre_modification_time.ToTimeT()); + EXPECT_LE(s_target_updated.ColumnInt64(12), + post_modification_time.ToTimeT()); + EXPECT_FALSE(s_target_updated.Step()); delete db_creditcard; - // Remove the 'Billing' profile. + // Remove the 'Target' credit card. EXPECT_TRUE(db.RemoveCreditCard(target_creditcard.unique_id())); EXPECT_FALSE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), &db_creditcard)); } +TEST_F(WebDatabaseTest, RemoveAutoFillProfilesAndCreditCardsModifiedBetween) { + WebDatabase db; + ASSERT_EQ(sql::INIT_OK, db.Init(file_)); + + // Populate the autofill_profiles and credit_cards tables. + ASSERT_TRUE(db.db_.Execute( + "INSERT INTO \"autofill_profiles\" VALUES('P1',1,'','','','','','','',''," + "'','','','','',11);" + "INSERT INTO \"autofill_profiles\" VALUES('P2',2,'','','','','','','',''," + "'','','','','',21);" + "INSERT INTO \"autofill_profiles\" VALUES('P3',3,'','','','','','','',''," + "'','','','','',31);" + "INSERT INTO \"autofill_profiles\" VALUES('P4',4,'','','','','','','',''," + "'','','','','',41);" + "INSERT INTO \"autofill_profiles\" VALUES('P5',5,'','','','','','','',''," + "'','','','','',51);" + "INSERT INTO \"autofill_profiles\" VALUES('P6',6,'','','','','','','',''," + "'','','','','',61);" + "INSERT INTO \"credit_cards\" VALUES('C10',10,'','','',10,2010,'','',''," + "X'',X'',17);" + "INSERT INTO \"credit_cards\" VALUES('C20',20,'','','',10,2010,'','',''," + "X'',X'',27);" + "INSERT INTO \"credit_cards\" VALUES('C30',30,'','','',10,2010,'','',''," + "X'',X'',37);" + "INSERT INTO \"credit_cards\" VALUES('C40',40,'','','',10,2010,'','',''," + "X'',X'',47);" + "INSERT INTO \"credit_cards\" VALUES('C50',50,'','','',10,2010,'','',''," + "X'',X'',57);" + "INSERT INTO \"credit_cards\" VALUES('C60',60,'','','',10,2010,'','',''," + "X'',X'',67);")); + + // Remove all entries modified in the bounded time range [17,41). + db.RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + base::Time::FromTimeT(17), base::Time::FromTimeT(41)); + sql::Statement s_autofill_profiles_bounded(db.db_.GetUniqueStatement( + "SELECT * FROM autofill_profiles")); + ASSERT_TRUE(s_autofill_profiles_bounded); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(11, s_autofill_profiles_bounded.ColumnInt64(15)); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(41, s_autofill_profiles_bounded.ColumnInt64(15)); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(51, s_autofill_profiles_bounded.ColumnInt64(15)); + ASSERT_TRUE(s_autofill_profiles_bounded.Step()); + EXPECT_EQ(61, s_autofill_profiles_bounded.ColumnInt64(15)); + EXPECT_FALSE(s_autofill_profiles_bounded.Step()); + sql::Statement s_credit_cards_bounded(db.db_.GetUniqueStatement( + "SELECT * FROM credit_cards")); + ASSERT_TRUE(s_credit_cards_bounded); + ASSERT_TRUE(s_credit_cards_bounded.Step()); + EXPECT_EQ(47, s_credit_cards_bounded.ColumnInt64(12)); + ASSERT_TRUE(s_credit_cards_bounded.Step()); + EXPECT_EQ(57, s_credit_cards_bounded.ColumnInt64(12)); + ASSERT_TRUE(s_credit_cards_bounded.Step()); + EXPECT_EQ(67, s_credit_cards_bounded.ColumnInt64(12)); + EXPECT_FALSE(s_credit_cards_bounded.Step()); + + // Remove all entries modified on or after time 51 (unbounded range). + db.RemoveAutoFillProfilesAndCreditCardsModifiedBetween( + base::Time::FromTimeT(51), base::Time()); + sql::Statement s_autofill_profiles_unbounded(db.db_.GetUniqueStatement( + "SELECT * FROM autofill_profiles")); + ASSERT_TRUE(s_autofill_profiles_unbounded); + ASSERT_TRUE(s_autofill_profiles_unbounded.Step()); + EXPECT_EQ(11, s_autofill_profiles_unbounded.ColumnInt64(15)); + ASSERT_TRUE(s_autofill_profiles_unbounded.Step()); + EXPECT_EQ(41, s_autofill_profiles_unbounded.ColumnInt64(15)); + EXPECT_FALSE(s_autofill_profiles_unbounded.Step()); + sql::Statement s_credit_cards_unbounded(db.db_.GetUniqueStatement( + "SELECT * FROM credit_cards")); + ASSERT_TRUE(s_credit_cards_unbounded); + ASSERT_TRUE(s_credit_cards_unbounded.Step()); + EXPECT_EQ(47, s_credit_cards_unbounded.ColumnInt64(12)); + EXPECT_FALSE(s_credit_cards_unbounded.Step()); +} + TEST_F(WebDatabaseTest, Autofill_GetAllAutofillEntries_NoResults) { WebDatabase db; @@ -1584,6 +1720,7 @@ class WebDatabaseMigrationTest : public testing::Test { void SetUpVersion26Database(); void SetUpVersion27Database(); void SetUpVersion28Database(); + void SetUpVersion29Database(); // Assertion testing for migrating from version 27 and 28. void MigrateVersion28Assertions(); @@ -1594,7 +1731,7 @@ class WebDatabaseMigrationTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest); }; -const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 29; +const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 30; // 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 @@ -2080,6 +2217,85 @@ void WebDatabaseMigrationTest::SetUpVersion28Database() { ASSERT_TRUE(connection.CommitTransaction()); } +void WebDatabaseMigrationTest::SetUpVersion29Database() { + 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','29');" + "INSERT INTO \"meta\" VALUES('last_compatible_version','29');" + "INSERT INTO \"meta\" VALUES('Default Search Provider ID','2');" + "INSERT INTO \"meta\" VALUES('Builtin Keyword Version','29');" + "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);" + "INSERT INTO \"autofill_profiles\" VALUES('Santa Claus, 1 Reindeer Lane',1," + "'Santa','','Claus','','','1 Reindeer Lane','P.O. Box 56009'," + "'North Pole','','H0H 0H0','CANADA','','');" + "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);" + "INSERT INTO \"credit_cards\" VALUES('',2,'Kris Kringle','','',12,2020,''," + "'1','',X'',X'');" + "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. @@ -2525,3 +2741,69 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion28ToCurrent) { MigrateVersion28Assertions(); } + +// Makes sure date_modified is added correctly to autofill_profiles and +// credit_cards. +TEST_F(WebDatabaseMigrationTest, MigrateVersion29ToCurrent) { + // Initialize the database. + SetUpVersion29Database(); + + // 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", + "date_modified")); + EXPECT_FALSE(connection.DoesColumnExist("credit_cards", + "date_modified")); + } + + // Load the database via the WebDatabase class and migrate the database to + // the current version. + Time pre_creation_time = Time::Now(); + { + WebDatabase db; + ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath())); + } + Time post_creation_time = Time::Now(); + + // 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)); + + // Check that the columns were created. + EXPECT_TRUE(connection.DoesColumnExist("autofill_profiles", + "date_modified")); + EXPECT_TRUE(connection.DoesColumnExist("credit_cards", + "date_modified")); + + sql::Statement s_profiles(connection.GetUniqueStatement( + "SELECT * FROM autofill_profiles ")); + ASSERT_TRUE(s_profiles); + while (s_profiles.Step()) { + EXPECT_GE(s_profiles.ColumnInt64(15), + pre_creation_time.ToTimeT()); + EXPECT_LE(s_profiles.ColumnInt64(15), + post_creation_time.ToTimeT()); + } + EXPECT_TRUE(s_profiles.Succeeded()); + + sql::Statement s_credit_cards(connection.GetUniqueStatement( + "SELECT * FROM credit_cards ")); + ASSERT_TRUE(s_credit_cards); + while (s_credit_cards.Step()) { + EXPECT_GE(s_credit_cards.ColumnInt64(12), + pre_creation_time.ToTimeT()); + EXPECT_LE(s_credit_cards.ColumnInt64(12), + post_creation_time.ToTimeT()); + } + EXPECT_TRUE(s_credit_cards.Succeeded()); + } +} |