summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsmckay@chromium.org <smckay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-11 19:27:51 +0000
committersmckay@chromium.org <smckay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-11 19:27:51 +0000
commit40ca780c7e423ced96e7fcdba630d98161064f78 (patch)
tree823f0fac708c17c98cd6f2a77bf46977b3b88e95
parent764864e768df050b1f946648c86a5b33f265d6ae (diff)
downloadchromium_src-40ca780c7e423ced96e7fcdba630d98161064f78.zip
chromium_src-40ca780c7e423ced96e7fcdba630d98161064f78.tar.gz
chromium_src-40ca780c7e423ced96e7fcdba630d98161064f78.tar.bz2
Add "scheme" column to web_intents and web_intents_defaults tables.
Includes support for recovering from at least some bad schema states. Added test to verify the new recovery behavior in addition to standard migration coverage. BUG=129199, 129200 TEST=WebDatabaseMigrationTest.MigrateVersion45ToCurrent, WebDatabaseMigrationTest.MigrateVersion45InvalidToCurrent Review URL: https://chromiumcodereview.appspot.com/10543059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141458 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/webdata/web_database.cc11
-rw-r--r--chrome/browser/webdata/web_database_migration_unittest.cc166
-rw-r--r--chrome/browser/webdata/web_intents_table.cc102
-rw-r--r--chrome/browser/webdata/web_intents_table.h3
-rw-r--r--chrome/test/data/web_database/version_45.sql53
-rw-r--r--chrome/test/data/web_database/version_45_invalid.sql52
6 files changed, 361 insertions, 26 deletions
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index 48e9262..122f3de 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -21,11 +21,11 @@
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
// static
-const int WebDatabase::kCurrentVersionNumber = 45;
+const int WebDatabase::kCurrentVersionNumber = 46;
namespace {
-const int kCompatibleVersionNumber = 45;
+const int kCompatibleVersionNumber = 46;
// Change the version number and possibly the compatibility version of
// |meta_table_|.
@@ -329,6 +329,13 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded() {
ChangeVersion(&meta_table_, 45, true);
// FALL THROUGH
+ case 45:
+ if (!web_intents_table_->MigrateToVersion46AddSchemeColumn())
+ return FailedMigrationTo(46);
+
+ ChangeVersion(&meta_table_, 46, true);
+ // 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_migration_unittest.cc b/chrome/browser/webdata/web_database_migration_unittest.cc
index f60f1ae..d1c7478 100644
--- a/chrome/browser/webdata/web_database_migration_unittest.cc
+++ b/chrome/browser/webdata/web_database_migration_unittest.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/webdata/autofill_entry.h"
#include "chrome/browser/webdata/keyword_table.h"
#include "chrome/browser/webdata/web_database.h"
+#include "chrome/browser/webdata/web_intents_table.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/guid.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -194,7 +195,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 45;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 46;
void WebDatabaseMigrationTest::LoadDatabase(const FilePath::StringType& file) {
std::string contents;
@@ -224,17 +225,19 @@ TEST_F(WebDatabaseMigrationTest, MigrateEmptyToCurrent) {
EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
// Check that expected tables are present.
- EXPECT_TRUE(connection.DoesTableExist("meta"));
- EXPECT_TRUE(connection.DoesTableExist("keywords"));
- // The logins table is obsolete. (We used to store saved passwords here.)
- EXPECT_FALSE(connection.DoesTableExist("logins"));
- EXPECT_TRUE(connection.DoesTableExist("web_app_icons"));
- EXPECT_TRUE(connection.DoesTableExist("web_apps"));
EXPECT_TRUE(connection.DoesTableExist("autofill"));
EXPECT_TRUE(connection.DoesTableExist("autofill_dates"));
EXPECT_TRUE(connection.DoesTableExist("autofill_profiles"));
EXPECT_TRUE(connection.DoesTableExist("credit_cards"));
+ EXPECT_TRUE(connection.DoesTableExist("keywords"));
+ // The logins table is obsolete. (We used to store saved passwords here.)
+ EXPECT_FALSE(connection.DoesTableExist("logins"));
+ EXPECT_TRUE(connection.DoesTableExist("meta"));
EXPECT_TRUE(connection.DoesTableExist("token_service"));
+ EXPECT_TRUE(connection.DoesTableExist("web_app_icons"));
+ EXPECT_TRUE(connection.DoesTableExist("web_apps"));
+ EXPECT_TRUE(connection.DoesTableExist("web_intents"));
+ EXPECT_TRUE(connection.DoesTableExist("web_intents_defaults"));
}
}
@@ -2020,3 +2023,152 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion44CorruptBackupToCurrent) {
EXPECT_FALSE(connection.DoesTableExist("keywords_backup"));
}
}
+
+// Tests that the web_intents and web_intents_defaults tables are
+// modified to include "scheme" columns.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion45ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_45.sql")));
+
+ // Verify pre-conditions. These are expectations for version 45 of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(&connection, 45, 45));
+
+ ASSERT_FALSE(connection.DoesColumnExist("scheme", "web_intents"));
+ ASSERT_FALSE(connection.DoesColumnExist(
+ "scheme", "web_intents_defaults"));
+ }
+
+ // 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()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(
+ &connection,
+ kCurrentTestedVersionNumber,
+ kCurrentTestedVersionNumber));
+
+ // A new "scheme" column should have been added to each web_intents table.
+ EXPECT_TRUE(connection.DoesColumnExist("web_intents", "scheme"));
+ EXPECT_TRUE(connection.DoesColumnExist("web_intents_defaults", "scheme"));
+
+ // Verify existing user data was copied.
+ sql::Statement s1(
+ connection.GetUniqueStatement("SELECT * FROM web_intents"));
+
+ ASSERT_TRUE(s1.Step());
+ EXPECT_EQ("http://poodles.com/fuzzer", s1.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("fuzz"), s1.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16("poodle/*"), s1.ColumnString16(2));
+ EXPECT_EQ(ASCIIToUTF16("Poodle Fuzzer"), s1.ColumnString16(3));
+ EXPECT_EQ(ASCIIToUTF16("window"), s1.ColumnString16(4));
+ EXPECT_EQ(ASCIIToUTF16(""), s1.ColumnString16(5));
+ ASSERT_FALSE(s1.Step());
+
+ // Now we want to verify existing user data was copied
+ sql::Statement s2(
+ connection.GetUniqueStatement("SELECT * FROM web_intents_defaults"));
+
+ ASSERT_TRUE(s2.Step());
+ EXPECT_EQ("fuzz", s2.ColumnString(0));
+ EXPECT_EQ(ASCIIToUTF16("poodle/*"), s2.ColumnString16(1));
+ EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(2));
+ EXPECT_EQ(0, s2.ColumnInt(3));
+ EXPECT_EQ(0, s2.ColumnInt(4));
+ EXPECT_EQ(ASCIIToUTF16("http://poodles.com/fuzzer"), s2.ColumnString16(5));
+ EXPECT_EQ(ASCIIToUTF16(""), s2.ColumnString16(6));
+ ASSERT_FALSE(s2.Step());
+
+ // finally ensure the migration code cleaned up after itself
+ EXPECT_FALSE(connection.DoesTableExist("old_web_intents"));
+ EXPECT_FALSE(connection.DoesTableExist("old_web_intents_defaults"));
+ }
+}
+
+// Tests that the web_intents and web_intents_defaults tables are
+// modified to include "scheme" columns.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion45InvalidToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(
+ LoadDatabase(FILE_PATH_LITERAL("version_45_invalid.sql")));
+
+ // Verify pre-conditions. These are expectations for version 45 of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(&connection, 45, 45));
+
+ ASSERT_FALSE(connection.DoesColumnExist("scheme", "web_intents"));
+ ASSERT_FALSE(connection.DoesColumnExist(
+ "scheme", "web_intents_defaults"));
+ }
+
+ // 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()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(
+ &connection,
+ kCurrentTestedVersionNumber,
+ kCurrentTestedVersionNumber));
+
+ // A new "scheme" column should have been added to each web_intents table.
+ EXPECT_TRUE(connection.DoesColumnExist("web_intents", "scheme"));
+ EXPECT_TRUE(connection.DoesColumnExist("web_intents_defaults", "scheme"));
+
+ // Verify existing user data was copied.
+ sql::Statement s1(
+ connection.GetUniqueStatement("SELECT * FROM web_intents"));
+
+ ASSERT_FALSE(s1.Step()); // Basically should be empty at this point.
+
+ // Now we want to verify existing user data was copied
+ sql::Statement s2(
+ connection.GetUniqueStatement("SELECT * FROM web_intents_defaults"));
+
+ // We were still able to copy the contents of the deafults table.
+ // Further verification is supplied in MigrateVersion45ToCurrent.
+ ASSERT_TRUE(s2.Step());
+ ASSERT_FALSE(s2.Step());
+
+ // Finally ensure the migration code cleaned up after itself.
+ EXPECT_FALSE(connection.DoesTableExist("old_web_intents"));
+ EXPECT_FALSE(connection.DoesTableExist("old_web_intents_defaults"));
+ }
+}
diff --git a/chrome/browser/webdata/web_intents_table.cc b/chrome/browser/webdata/web_intents_table.cc
index a5a9242..a14206b 100644
--- a/chrome/browser/webdata/web_intents_table.cc
+++ b/chrome/browser/webdata/web_intents_table.cc
@@ -55,35 +55,46 @@ WebIntentsTable::~WebIntentsTable() {
bool WebIntentsTable::Init() {
if (!db_->DoesTableExist("web_intents")) {
if (!db_->Execute("CREATE TABLE web_intents ("
- "service_url LONGVARCHAR,"
- "action VARCHAR,"
- "type VARCHAR,"
- "title LONGVARCHAR,"
- "disposition VARCHAR,"
- "UNIQUE (service_url, action, type))")) {
+ " service_url LONGVARCHAR,"
+ " action VARCHAR,"
+ " type VARCHAR,"
+ " title LONGVARCHAR,"
+ " disposition VARCHAR,"
+ " scheme VARCHAR,"
+ " UNIQUE (service_url, action, scheme, type))")) {
return false;
}
}
if (!db_->DoesTableExist("web_intents_defaults")) {
if (!db_->Execute("CREATE TABLE web_intents_defaults ("
- "action VARCHAR,"
- "type VARCHAR,"
- "url_pattern LONGVARCHAR,"
- "user_date INTEGER,"
- "suppression INTEGER,"
- "service_url LONGVARCHAR,"
- "UNIQUE (action, type, url_pattern))")) {
+ " action VARCHAR,"
+ " type VARCHAR,"
+ " url_pattern LONGVARCHAR,"
+ " user_date INTEGER,"
+ " suppression INTEGER,"
+ " service_url LONGVARCHAR,"
+ " scheme VARCHAR,"
+ " UNIQUE (action, scheme, type, url_pattern))")) {
return false;
}
}
- if (!db_->Execute("CREATE INDEX IF NOT EXISTS web_intents_index "
- "ON web_intents (action)"))
+ if (!db_->Execute("CREATE INDEX IF NOT EXISTS web_intents_index"
+ " ON web_intents (action)"))
return false;
- if (!db_->Execute("CREATE INDEX IF NOT EXISTS web_intents_default_index "
- "ON web_intents_defaults (action)")) {
+ if (!db_->Execute("CREATE INDEX IF NOT EXISTS web_intents_default_index"
+ " ON web_intents_defaults (action)")) {
+ return false;
+ }
+
+ if (!db_->Execute("CREATE INDEX IF NOT EXISTS web_intents_index"
+ " ON web_intents (scheme)"))
+ return false;
+
+ if (!db_->Execute("CREATE INDEX IF NOT EXISTS web_intents_default_index"
+ " ON web_intents_defaults (scheme)")) {
return false;
}
@@ -95,6 +106,63 @@ bool WebIntentsTable::IsSyncable() {
return false;
}
+// Updates the table by way of renaming the old tables, rerunning
+// the Init method, then selecting old values into the new tables.
+bool WebIntentsTable::MigrateToVersion46AddSchemeColumn() {
+ if (!db_->Execute("ALTER TABLE web_intents RENAME TO old_web_intents")) {
+ DLOG(WARNING) << "Could not backup web_intents table.";
+ return false;
+ }
+
+ if (!db_->Execute("ALTER TABLE web_intents_defaults"
+ " RENAME TO old_web_intents_defaults")) {
+ DLOG(WARNING) << "Could not backup web_intents_defaults table.";
+ return false;
+ }
+
+ if (!Init()) return false;
+
+ // The database is known to be in an invalid state in the wild
+ // with a missing "title" column. Guard against this.
+ if (db_->DoesColumnExist("old_web_intents", "title")) {
+ if (!db_->Execute(
+ "INSERT INTO web_intents"
+ " (service_url, action, type, title, disposition)"
+ " SELECT "
+ " service_url, action, type, title, disposition"
+ " FROM old_web_intents")) {
+
+ DLOG(WARNING) << "Could not copy old intent data to updated table.";
+ }
+ } else {
+ DLOG(WARNING) << "'title' column missing from old_web_intents table."
+ " Skipping copy.";
+ }
+
+ if (!db_->Execute(
+ "INSERT INTO web_intents_defaults"
+ " (service_url, action, type, url_pattern, user_date, suppression)"
+ " SELECT "
+ " service_url, action, type, url_pattern, user_date, suppression"
+ " FROM old_web_intents_defaults")) {
+
+ DLOG(WARNING) << "Could not copy old intent defaults data to"
+ " updated table.";
+ }
+
+ if (!db_->Execute("DROP table old_web_intents")) {
+ LOG(WARNING) << "Could not drop backup web_intents table.";
+ return false;
+ }
+
+ if (!db_->Execute("DROP table old_web_intents_defaults")) {
+ DLOG(WARNING) << "Could not drop backup web_intents_defaults table.";
+ return false;
+ }
+
+ return true;
+}
+
bool WebIntentsTable::GetWebIntentServices(
const string16& action,
std::vector<WebIntentServiceData>* services) {
diff --git a/chrome/browser/webdata/web_intents_table.h b/chrome/browser/webdata/web_intents_table.h
index 6f61ac3..9a3a00b 100644
--- a/chrome/browser/webdata/web_intents_table.h
+++ b/chrome/browser/webdata/web_intents_table.h
@@ -56,6 +56,9 @@ class WebIntentsTable : public WebDatabaseTable {
virtual bool Init() OVERRIDE;
virtual bool IsSyncable() OVERRIDE;
+ // Adds "scheme" column to the web_intents and web_intents_defaults tables.
+ bool MigrateToVersion46AddSchemeColumn();
+
// Adds a web intent service to the WebIntents table.
// If |service| already exists, replaces it.
bool SetWebIntentService(const webkit_glue::WebIntentServiceData& service);
diff --git a/chrome/test/data/web_database/version_45.sql b/chrome/test/data/web_database/version_45.sql
new file mode 100644
index 0000000..4b1e70a
--- /dev/null
+++ b/chrome/test/data/web_database/version_45.sql
@@ -0,0 +1,53 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('Default Search Provider ID','2');
+INSERT INTO "meta" VALUES('version','45');
+INSERT INTO "meta" VALUES('last_compatible_version','45');
+INSERT INTO "meta" VALUES('Default Search Provider ID Backup','2');
+INSERT INTO "meta" VALUES('Default Search Provider ID Backup Signature','');
+INSERT INTO "meta" VALUES('Builtin Keyword Version','39');
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, pair_id INTEGER PRIMARY KEY, count INTEGER DEFAULT 1);
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_dates ( pair_id INTEGER DEFAULT 0, date_created INTEGER DEFAULT 0);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, address_line_1 VARCHAR, address_line_2 VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, country VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR);
+CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
+CREATE TABLE autofill_profile_phones ( guid VARCHAR, type INTEGER DEFAULT 0, number VARCHAR);
+CREATE TABLE autofill_profiles_trash ( guid VARCHAR);
+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 token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE TABLE web_intents (service_url LONGVARCHAR,action VARCHAR,type VARCHAR,title LONGVARCHAR,disposition VARCHAR,UNIQUE (service_url, action, type));
+CREATE TABLE web_intents_defaults (action VARCHAR,type VARCHAR,url_pattern LONGVARCHAR,user_date INTEGER,suppression INTEGER,service_url LONGVARCHAR,UNIQUE (action, type, url_pattern));
+CREATE TABLE "keywords" (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,show_in_default_list INTEGER,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,instant_url VARCHAR,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR);
+CREATE TABLE keywords_backup(
+ id INT,
+ short_name TEXT,
+ keyword TEXT,
+ favicon_url TEXT,
+ url TEXT,
+ safe_for_autoreplace INT,
+ originating_url TEXT,
+ date_created INT,
+ usage_count INT,
+ input_encodings TEXT,
+ show_in_default_list INT,
+ suggest_url TEXT,
+ prepopulate_id INT,
+ created_by_policy INT,
+ instant_url TEXT,
+ last_modified INT,
+ sync_guid TEXT
+);
+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 web_apps_url_index ON web_apps (url);
+CREATE INDEX web_intents_index ON web_intents (action);
+CREATE INDEX web_intents_default_index ON web_intents_defaults (action);
+-- following statements are required for testing migration to version 46
+INSERT INTO web_intents VALUES ('http://poodles.com/fuzzer', 'fuzz', 'poodle/*', 'Poodle Fuzzer', 'window');
+INSERT INTO web_intents_defaults VALUES ('fuzz', 'poodle/*', '', 0, 0, 'http://poodles.com/fuzzer');
+COMMIT;
+
diff --git a/chrome/test/data/web_database/version_45_invalid.sql b/chrome/test/data/web_database/version_45_invalid.sql
new file mode 100644
index 0000000..504006d
--- /dev/null
+++ b/chrome/test/data/web_database/version_45_invalid.sql
@@ -0,0 +1,52 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('Default Search Provider ID','2');
+INSERT INTO "meta" VALUES('version','45');
+INSERT INTO "meta" VALUES('last_compatible_version','45');
+INSERT INTO "meta" VALUES('Default Search Provider ID Backup','2');
+INSERT INTO "meta" VALUES('Default Search Provider ID Backup Signature','');
+INSERT INTO "meta" VALUES('Builtin Keyword Version','39');
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, pair_id INTEGER PRIMARY KEY, count INTEGER DEFAULT 1);
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_dates ( pair_id INTEGER DEFAULT 0, date_created INTEGER DEFAULT 0);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, address_line_1 VARCHAR, address_line_2 VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, country VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR);
+CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
+CREATE TABLE autofill_profile_phones ( guid VARCHAR, type INTEGER DEFAULT 0, number VARCHAR);
+CREATE TABLE autofill_profiles_trash ( guid VARCHAR);
+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 token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE TABLE web_intents (service_url LONGVARCHAR,action VARCHAR,type VARCHAR,disposition VARCHAR,UNIQUE (service_url, action, type));
+CREATE TABLE web_intents_defaults (action VARCHAR,type VARCHAR,url_pattern LONGVARCHAR,user_date INTEGER,suppression INTEGER,service_url LONGVARCHAR,UNIQUE (action, type, url_pattern));
+CREATE TABLE "keywords" (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,show_in_default_list INTEGER,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,instant_url VARCHAR,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR);
+CREATE TABLE keywords_backup(
+ id INT,
+ short_name TEXT,
+ keyword TEXT,
+ favicon_url TEXT,
+ url TEXT,
+ safe_for_autoreplace INT,
+ originating_url TEXT,
+ date_created INT,
+ usage_count INT,
+ input_encodings TEXT,
+ show_in_default_list INT,
+ suggest_url TEXT,
+ prepopulate_id INT,
+ created_by_policy INT,
+ instant_url TEXT,
+ last_modified INT,
+ sync_guid TEXT
+);
+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 web_apps_url_index ON web_apps (url);
+CREATE INDEX web_intents_index ON web_intents (action);
+CREATE INDEX web_intents_default_index ON web_intents_defaults (action);
+-- following statements are required for testing migration to version 46
+INSERT INTO web_intents VALUES ('http://poodles.com/fuzzer', 'fuzz', 'poodle/*', 'window');
+INSERT INTO web_intents_defaults VALUES ('fuzz', 'poodle/*', '', 0, 0, 'http://poodles.com/fuzzer');
+COMMIT;