diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-13 20:38:57 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-13 20:38:57 +0000 |
commit | c47c9d80e93941924c8d6c5e4d7845971552b390 (patch) | |
tree | ba148e054621c580be7c6ca48c217de344f5eb04 /chrome/browser/webdata | |
parent | 4cd978f396db700a1fb3e2d6e081e76817264c9b (diff) | |
download | chromium_src-c47c9d80e93941924c8d6c5e4d7845971552b390.zip chromium_src-c47c9d80e93941924c8d6c5e4d7845971552b390.tar.gz chromium_src-c47c9d80e93941924c8d6c5e4d7845971552b390.tar.bz2 |
DOMUI: Implement adding and editing credit cards in the AutoFill page.
BUG=49094
TEST=none
Review URL: http://codereview.chromium.org/3308006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59276 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/webdata')
-rw-r--r-- | chrome/browser/webdata/web_database.cc | 121 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.h | 6 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database_unittest.cc | 222 |
3 files changed, 338 insertions, 11 deletions
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc index 7028b1f..eaeb623 100644 --- a/chrome/browser/webdata/web_database.cc +++ b/chrome/browser/webdata/web_database.cc @@ -12,6 +12,7 @@ #include "app/l10n_util.h" #include "app/sql/statement.h" #include "app/sql/transaction.h" +#include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/tuple.h" #include "base/utf_string_conversions.h" @@ -167,8 +168,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 = 26; -const int kCompatibleVersionNumber = 26; +const int kCurrentVersionNumber = 27; +const int kCompatibleVersionNumber = 27; const int kUrlIdPosition = 15; // Keys used in the meta table. @@ -339,7 +340,7 @@ void BindCreditCardToStatement(const CreditCard& credit_card, s->BindString16(6, LimitDataSize(text)); text.clear(); s->BindString16(7, LimitDataSize(text)); - s->BindString16(8, credit_card.billing_address()); + s->BindInt(8, credit_card.billing_address_id()); // We don't store the shipping address anymore. text.clear(); s->BindString16(9, LimitDataSize(text)); @@ -380,7 +381,7 @@ CreditCard* CreditCardFromStatement(const sql::Statement& s) { string16 credit_card_verification_code = s.ColumnString16(7); // We don't store the CVV anymore. - credit_card->set_billing_address(s.ColumnString16(8)); + 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. @@ -2039,11 +2040,123 @@ void WebDatabase::MigrateOldVersionsAsNeeded(){ LOG(WARNING) << "Unable to update web database to version 26."; return; } + + meta_table_.SetVersionNumber(26); + meta_table_.SetCompatibleVersionNumber( + std::min(26, kCompatibleVersionNumber)); + // FALL THROUGH + + case 26: { + // Change the credit_cards.billing_address column from a string to an int. + // The stored string is the label of an address, so we have to select the + // unique ID of this address using the label as a foreign key into the + // |autofill_profiles| table. + std::string stmt = + "SELECT credit_cards.unique_id, autofill_profiles.unique_id " + "FROM autofill_profiles, credit_cards " + "WHERE credit_cards.billing_address = autofill_profiles.label"; + sql::Statement s(db_.GetUniqueStatement(stmt.c_str())); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return; + } + + std::map<int, int> cc_billing_map; + while (s.Step()) + cc_billing_map[s.ColumnInt(0)] = s.ColumnInt(1); + + // Windows already stores the IDs as strings in |billing_address|. Try to + // convert those. + if (cc_billing_map.empty()) { + std::string stmt = + "SELECT unique_id,billing_address FROM credit_cards"; + sql::Statement s(db_.GetUniqueStatement(stmt.c_str())); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return; + } + + while (s.Step()) { + int id = 0; + if (base::StringToInt(s.ColumnString(1), &id)) + cc_billing_map[s.ColumnInt(0)] = id; + } + } + + if (!db_.Execute("CREATE TABLE credit_cards_temp ( " + "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 INTEGER, " + "shipping_address VARCHAR, " + "card_number_encrypted BLOB, " + "verification_code_encrypted BLOB)")) { + NOTREACHED(); + LOG(WARNING) << "Unable to update web database to version 27."; + return; + } + + if (!db_.Execute( + "INSERT INTO credit_cards_temp " + "SELECT label,unique_id,name_on_card,type,card_number," + "expiration_month,expiration_year,verification_code,0," + "shipping_address,card_number_encrypted,verification_code_encrypted " + "FROM credit_cards")) { + NOTREACHED(); + LOG(WARNING) << "Unable to update web database to version 27."; + return; + } + + if (!db_.Execute("DROP TABLE credit_cards")) { + NOTREACHED(); + LOG(WARNING) << "Unable to update web database to version 27."; + return; + } + + if (!db_.Execute( + "ALTER TABLE credit_cards_temp RENAME TO credit_cards")) { + NOTREACHED(); + LOG(WARNING) << "Unable to update web database to version 27."; + return; + } + 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( + SQL_FROM_HERE, + "UPDATE credit_cards SET billing_address=? WHERE unique_id=?")); + if (!s) { + NOTREACHED() << "Statement prepare failed"; + return; + } + + s.BindInt(0, (*iter).second); + s.BindInt(1, (*iter).first); + + if (!s.Run()) { + NOTREACHED(); + LOG(WARNING) << "Unable to update web database to version 27."; + return; + } + } + + meta_table_.SetVersionNumber(27); + meta_table_.SetCompatibleVersionNumber( + std::min(27, 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 b15f688..9358533 100644 --- a/chrome/browser/webdata/web_database.h +++ b/chrome/browser/webdata/web_database.h @@ -129,14 +129,14 @@ class WebDatabase { // Loads the complete list of password forms into the specified vector |forms| // if include_blacklisted is true, otherwise only loads those which are - // actually autofillable; i.e haven't been blacklisted by the user selecting + // actually autofill-able; i.e haven't been blacklisted by the user selecting // the 'Never for this site' button. bool GetAllLogins(std::vector<webkit_glue::PasswordForm*>* forms, bool include_blacklisted); ////////////////////////////////////////////////////////////////////////////// // - // Autofill + // AutoFill // ////////////////////////////////////////////////////////////////////////////// @@ -285,7 +285,7 @@ class WebDatabase { // Remove all tokens previously set with SetTokenForService. bool RemoveAllTokens(); - // Retrives all tokens previously set with SetTokenForService. + // Retrieves all tokens previously set with SetTokenForService. // Returns true if there were tokens and we decrypted them, // false if there was a failure somehow bool GetAllTokens(std::map<std::string, std::string>* tokens); diff --git a/chrome/browser/webdata/web_database_unittest.cc b/chrome/browser/webdata/web_database_unittest.cc index 998e027..4bfa827 100644 --- a/chrome/browser/webdata/web_database_unittest.cc +++ b/chrome/browser/webdata/web_database_unittest.cc @@ -1318,7 +1318,7 @@ TEST_F(WebDatabaseTest, CreditCard) { ASCIIToUTF16("04")); work_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), ASCIIToUTF16("2013")); - work_creditcard.set_billing_address(ASCIIToUTF16("Overlook Hotel")); + work_creditcard.set_billing_address_id(1); EXPECT_TRUE(db.AddCreditCard(work_creditcard)); @@ -1340,7 +1340,7 @@ TEST_F(WebDatabaseTest, CreditCard) { ASCIIToUTF16("06")); target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_EXP_4_DIGIT_YEAR), ASCIIToUTF16("2012")); - target_creditcard.set_billing_address(ASCIIToUTF16("Overlook Hotel")); + target_creditcard.set_billing_address_id(1); EXPECT_TRUE(db.AddCreditCard(target_creditcard)); ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), @@ -1350,7 +1350,7 @@ TEST_F(WebDatabaseTest, CreditCard) { // Update the 'Target' profile. target_creditcard.SetInfo(AutoFillType(CREDIT_CARD_NAME), - ASCIIToUTF16("Charles Grady")); + ASCIIToUTF16("Charles Grady")); EXPECT_TRUE(db.UpdateCreditCard(target_creditcard)); ASSERT_TRUE(db.GetCreditCardForLabel(ASCIIToUTF16("Target"), &db_creditcard)); EXPECT_EQ(target_creditcard, *db_creditcard); @@ -1572,6 +1572,7 @@ class WebDatabaseMigrationTest : public testing::Test { void SetUpVersion22CorruptDatabase(); void SetUpVersion24Database(); void SetUpVersion25Database(); + void SetUpVersion26Database(); private: ScopedTempDir temp_dir_; @@ -1579,7 +1580,7 @@ class WebDatabaseMigrationTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest); }; -const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 26; +const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 27; // 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 @@ -1868,6 +1869,67 @@ void WebDatabaseMigrationTest::SetUpVersion25Database() { ASSERT_TRUE(connection.CommitTransaction()); } +// This schema is taken from a build prior to the change of column type for +// credit_cards.billing_address from string to int. +void WebDatabaseMigrationTest::SetUpVersion26Database() { + 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','25');" + "INSERT INTO \"meta\" VALUES('last_compatible_version','25');" + "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);" + "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);" + "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);" + "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()); +} + // Tests that the all migrations from an empty database succeed. TEST_F(WebDatabaseMigrationTest, MigrateEmptyToCurrent) { // Load the database via the WebDatabase class and migrate the database to @@ -2039,10 +2101,144 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion25ToCurrent) { { sql::Connection connection; ASSERT_TRUE(connection.Open(GetDatabasePath())); + } + + // 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)); + + // |keywords| |logo_id| column should have been added. + EXPECT_TRUE(connection.DoesColumnExist("keywords", "id")); + EXPECT_TRUE(connection.DoesColumnExist("keywords", "created_by_policy")); + } +} + +// Tests that the credit_cards.billing_address column is changed from a string +// to an int whilst preserving the associated billing address. This version of +// the test makes sure a stored label is converted to an ID. +TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringLabels) { + // Initialize the database. + SetUpVersion25Database(); + + // Verify pre-conditions. These are expectations for version 25 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" + "(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 ('Home',1,'','','','','','','','','','','','','')"; + sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); + ASSERT_TRUE(s.Run()); + + // Insert a CC linked to an existing address. + std::string stmt2 = "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',2,'Jack','Visa','1234',2,2012,'','Home','','','')"; + sql::Statement s2(connection.GetUniqueStatement(stmt2.c_str())); + ASSERT_TRUE(s2.Run()); + + // |billing_address| is a string. + std::string stmt3 = "SELECT billing_address FROM credit_cards"; + sql::Statement s3(connection.GetUniqueStatement(stmt3.c_str())); + ASSERT_TRUE(s3.Step()); + EXPECT_EQ(s3.ColumnType(0), sql::COLUMN_TYPE_TEXT); + } + + // 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)); + EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); + + // |billing_address| is an integer. Also Verify the credit card data is + // converted. + std::string stmt = "SELECT * FROM credit_cards"; + sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); + ASSERT_TRUE(s.Step()); + EXPECT_EQ(s.ColumnType(8), sql::COLUMN_TYPE_INTEGER); + EXPECT_EQ("label", s.ColumnString(0)); + EXPECT_EQ(2, s.ColumnInt(1)); + EXPECT_EQ("Jack", s.ColumnString(2)); + EXPECT_EQ("Visa", s.ColumnString(3)); + EXPECT_EQ("1234", s.ColumnString(4)); + EXPECT_EQ(2, s.ColumnInt(5)); + EXPECT_EQ(2012, s.ColumnInt(6)); + EXPECT_EQ(std::string(), s.ColumnString(7)); + EXPECT_EQ(1, s.ColumnInt(8)); + // The remaining columns are unused or blobs. + } +} + +// Tests that the credit_cards.billing_address column is changed from a string +// to an int whilst preserving the associated billing address. This version of +// the test makes sure a stored string ID is converted to an integer ID. +TEST_F(WebDatabaseMigrationTest, MigrateVersion26ToCurrentStringIDs) { + // Initialize the database. + SetUpVersion25Database(); + + // Verify pre-conditions. These are expectations for version 25 of the + // database. + { + sql::Connection connection; + ASSERT_TRUE(connection.Open(GetDatabasePath())); + EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); + + std::string stmt = "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 ('Home',1,'','','','','','','','','','','','','')"; + sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); + ASSERT_TRUE(s.Run()); + + // Insert a CC linked to an existing address. + std::string stmt2 = "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',2,'Jack','Visa','1234',2,2012,'','1','','','')"; + sql::Statement s2(connection.GetUniqueStatement(stmt2.c_str())); + ASSERT_TRUE(s2.Run()); + + // |billing_address| is a string. + std::string stmt3 = "SELECT billing_address FROM credit_cards"; + sql::Statement s3(connection.GetUniqueStatement(stmt3.c_str())); + ASSERT_TRUE(s3.Step()); + EXPECT_EQ(s3.ColumnType(0), sql::COLUMN_TYPE_TEXT); } // Load the database via the WebDatabase class and migrate the database to @@ -2064,5 +2260,23 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion25ToCurrent) { // |keywords| |logo_id| column should have been added. EXPECT_TRUE(connection.DoesColumnExist("keywords", "id")); EXPECT_TRUE(connection.DoesColumnExist("keywords", "created_by_policy")); + EXPECT_TRUE(connection.DoesColumnExist("credit_cards", "billing_address")); + + // |billing_address| is an integer. Also Verify the credit card data is + // converted. + std::string stmt = "SELECT * FROM credit_cards"; + sql::Statement s(connection.GetUniqueStatement(stmt.c_str())); + ASSERT_TRUE(s.Step()); + EXPECT_EQ(s.ColumnType(8), sql::COLUMN_TYPE_INTEGER); + EXPECT_EQ("label", s.ColumnString(0)); + EXPECT_EQ(2, s.ColumnInt(1)); + EXPECT_EQ("Jack", s.ColumnString(2)); + EXPECT_EQ("Visa", s.ColumnString(3)); + EXPECT_EQ("1234", s.ColumnString(4)); + EXPECT_EQ(2, s.ColumnInt(5)); + EXPECT_EQ(2012, s.ColumnInt(6)); + EXPECT_EQ(std::string(), s.ColumnString(7)); + EXPECT_EQ(1, s.ColumnInt(8)); + // The remaining columns are unused or blobs. } } |