summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravayvod@chromium.org <avayvod@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-03 08:45:24 +0000
committeravayvod@chromium.org <avayvod@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-03 08:45:24 +0000
commit67bb274ea8015b43706f81d207f15153f31ac3a4 (patch)
treee1a10329ca6b70b91c1710aeca4bb4c679fc4be5
parenta46748425a6d409ebeb0cb098ba85fa8091c0cac (diff)
downloadchromium_src-67bb274ea8015b43706f81d207f15153f31ac3a4.zip
chromium_src-67bb274ea8015b43706f81d207f15153f31ac3a4.tar.gz
chromium_src-67bb274ea8015b43706f81d207f15153f31ac3a4.tar.bz2
Backup keywords, sign all backup settings together.
R=sky@chromium.org BUG=94447 TEST=Verify that migration to this build of Chrome goes smoothly and changing any search engine in Web Data file triggers the bubble. Review URL: http://codereview.chromium.org/8567004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112884 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/protector/histograms.cc5
-rw-r--r--chrome/browser/protector/histograms.h8
-rw-r--r--chrome/browser/webdata/keyword_table.cc366
-rw-r--r--chrome/browser/webdata/keyword_table.h52
-rw-r--r--chrome/browser/webdata/keyword_table_unittest.cc85
-rw-r--r--chrome/browser/webdata/web_database.cc11
-rw-r--r--chrome/browser/webdata/web_database_migration_unittest.cc103
-rw-r--r--chrome/test/data/web_database/version_24.sql1
-rw-r--r--chrome/test/data/web_database/version_25.sql1
-rw-r--r--chrome/test/data/web_database/version_26.sql1
-rw-r--r--chrome/test/data/web_database/version_27.sql1
-rw-r--r--chrome/test/data/web_database/version_41.sql30
12 files changed, 513 insertions, 151 deletions
diff --git a/chrome/browser/protector/histograms.cc b/chrome/browser/protector/histograms.cc
index b4b416c..d6cd061 100644
--- a/chrome/browser/protector/histograms.cc
+++ b/chrome/browser/protector/histograms.cc
@@ -14,11 +14,6 @@ namespace protector {
const char kProtectorHistogramDefaultSearchProvider[] =
"Protector.DefaultSearchProvider";
-const char kProtectorBackupInvalidCounter[] =
- "Protector.BackupInvalidCounter";
-const char kProtectorValueChangedCounter[] = "Protector.ValueChangedCounter";
-const char kProtectorValueValidCounter[] = "Protector.ValueValidCounter";
-
const char kProtectorHistogramNewSearchProvider[] =
"Protector.SearchProvider.New";
const char kProtectorHistogramSearchProviderApplied[] =
diff --git a/chrome/browser/protector/histograms.h b/chrome/browser/protector/histograms.h
index 5dc301e..b9d538f 100644
--- a/chrome/browser/protector/histograms.h
+++ b/chrome/browser/protector/histograms.h
@@ -14,18 +14,12 @@ namespace protector {
// provider. Values are below.
extern const char kProtectorHistogramDefaultSearchProvider[];
-// Histogram value to report that the backup value is invalid or missing.
-extern const char kProtectorBackupInvalidCounter[];
-// Histogram value to report that the value does not match the backup.
-extern const char kProtectorValueChangedCounter[];
-// Histogram value to report that the value matches the backup.
-extern const char kProtectorValueValidCounter[];
-
// Protector histogram values.
enum ProtectorError {
kProtectorErrorBackupInvalid,
kProtectorErrorValueChanged,
kProtectorErrorValueValid,
+ kProtectorErrorValueValidZero,
// This is for convenience only, must always be the last.
kProtectorErrorCount
diff --git a/chrome/browser/webdata/keyword_table.cc b/chrome/browser/webdata/keyword_table.cc
index 611784e..85898b8 100644
--- a/chrome/browser/webdata/keyword_table.cc
+++ b/chrome/browser/webdata/keyword_table.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/search_engines/template_url.h"
#include "googleurl/src/gurl.h"
#include "sql/statement.h"
+#include "sql/transaction.h"
using base::Time;
@@ -30,12 +31,16 @@ const char kDefaultSearchProviderKey[] = "Default Search Provider ID";
const char kBuiltinKeywordVersion[] = "Builtin Keyword Version";
// Meta table key to store backup value for the default search provider.
-const char kDefaultSearchProviderBackupKey[] =
+const char kDefaultSearchBackupKey[] = "Default Search Provider Backup";
+
+// Meta table key to store backup value for the default search provider id.
+const char kDefaultSearchIDBackupKey[] =
"Default Search Provider ID Backup";
// Meta table key to store backup value signature for the default search
-// provider.
-const char kDefaultSearchProviderBackupSignatureKey[] =
+// provider. Default search provider id, its row in |keywords| table and
+// the whole |keywords| table are signed.
+const char kBackupSignatureKey[] =
"Default Search Provider ID Backup Signature";
void BindURLToStatement(const TemplateURL& url, sql::Statement* s) {
@@ -89,33 +94,32 @@ KeywordTable::~KeywordTable() {}
bool KeywordTable::Init() {
if (!db_->DoesTableExist("keywords")) {
- if (!db_->Execute("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,"
- "last_modified INTEGER DEFAULT 0,"
- "sync_guid VARCHAR)")) {
+ if (!db_->Execute(
+ "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,"
+ "last_modified INTEGER DEFAULT 0,"
+ "sync_guid VARCHAR)")) {
NOTREACHED();
return false;
}
- // Initialize default search engine provider for new profile to have it
- // signed properly. TemplateURLService treats 0 as not existing id and
- // resets the value to the actual default search provider id.
- SetDefaultSearchProviderID(0);
+ if (!UpdateBackupSignature())
+ return false;
}
return true;
}
@@ -127,7 +131,7 @@ bool KeywordTable::IsSyncable() {
bool KeywordTable::AddKeyword(const TemplateURL& url) {
DCHECK(url.id());
// Be sure to change kUrlIdPosition if you add columns
- sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE,
+ sql::Statement s(db_->GetUniqueStatement(
"INSERT INTO keywords "
"(short_name, keyword, favicon_url, url, safe_for_autoreplace, "
"originating_url, date_created, usage_count, input_encodings, "
@@ -145,19 +149,18 @@ bool KeywordTable::AddKeyword(const TemplateURL& url) {
NOTREACHED();
return false;
}
- return true;
+ return UpdateBackupSignature();
}
bool KeywordTable::RemoveKeyword(TemplateURLID id) {
DCHECK(id);
- sql::Statement s(
- db_->GetUniqueStatement("DELETE FROM keywords WHERE id = ?"));
+ sql::Statement s(db_->GetUniqueStatement("DELETE FROM keywords WHERE id=?"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
}
s.BindInt64(0, id);
- return s.Run();
+ return s.Run() && UpdateBackupSignature();
}
bool KeywordTable::GetKeywords(std::vector<TemplateURL*>* urls) {
@@ -174,53 +177,7 @@ bool KeywordTable::GetKeywords(std::vector<TemplateURL*>* urls) {
}
while (s.Step()) {
TemplateURL* template_url = new TemplateURL();
- template_url->set_id(s.ColumnInt64(0));
-
- std::string tmp;
- tmp = s.ColumnString(1);
- DCHECK(!tmp.empty());
- template_url->set_short_name(UTF8ToUTF16(tmp));
-
- template_url->set_keyword(UTF8ToUTF16(s.ColumnString(2)));
-
- tmp = s.ColumnString(3);
- if (!tmp.empty())
- template_url->SetFaviconURL(GURL(tmp));
-
- template_url->SetURL(s.ColumnString(4), 0, 0);
-
- template_url->set_safe_for_autoreplace(s.ColumnInt(5) == 1);
-
- tmp = s.ColumnString(6);
- if (!tmp.empty())
- template_url->set_originating_url(GURL(tmp));
-
- template_url->set_date_created(Time::FromTimeT(s.ColumnInt64(7)));
-
- template_url->set_usage_count(s.ColumnInt(8));
-
- std::vector<std::string> encodings;
- base::SplitString(s.ColumnString(9), ';', &encodings);
- template_url->set_input_encodings(encodings);
-
- template_url->set_show_in_default_list(s.ColumnInt(10) == 1);
-
- template_url->SetSuggestionsURL(s.ColumnString(11), 0, 0);
-
- template_url->SetPrepopulateId(s.ColumnInt(12));
-
- template_url->set_autogenerate_keyword(s.ColumnInt(13) == 1);
-
- template_url->set_logo_id(s.ColumnInt(14));
-
- template_url->set_created_by_policy(s.ColumnBool(15));
-
- template_url->SetInstantURL(s.ColumnString(16), 0, 0);
-
- template_url->set_last_modified(Time::FromTimeT(s.ColumnInt64(17)));
-
- template_url->set_sync_guid(s.ColumnString(18));
-
+ GetURLFromStatement(s, template_url);
urls->push_back(template_url);
}
return s.Succeeded();
@@ -243,12 +200,12 @@ bool KeywordTable::UpdateKeyword(const TemplateURL& url) {
}
BindURLToStatement(url, &s);
s.BindInt64(kUrlIdPosition, url.id());
- return s.Run();
+ return s.Run() && UpdateBackupSignature();
}
bool KeywordTable::SetDefaultSearchProviderID(int64 id) {
return meta_table_->SetValue(kDefaultSearchProviderKey, id) &&
- SetDefaultSearchProviderBackupID(id);
+ UpdateBackupSignature();
}
int64 KeywordTable::GetDefaultSearchProviderID() {
@@ -258,43 +215,52 @@ int64 KeywordTable::GetDefaultSearchProviderID() {
}
int64 KeywordTable::GetDefaultSearchProviderIDBackup() {
- int64 backup_value = 0;
- meta_table_->GetValue(kDefaultSearchProviderBackupKey, &backup_value);
- std::string backup_signature;
- meta_table_->GetValue(
- kDefaultSearchProviderBackupSignatureKey, &backup_signature);
- if (!IsSearchProviderIDValid(backup_value, backup_signature))
+ if (!IsBackupSignatureValid())
return 0;
+ int64 backup_value = 0;
+ meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_value);
return backup_value;
}
bool KeywordTable::DidDefaultSearchProviderChange() {
- int64 backup_value = 0;
- meta_table_->GetValue(kDefaultSearchProviderBackupKey, &backup_value);
- std::string backup_signature;
- meta_table_->GetValue(
- kDefaultSearchProviderBackupSignatureKey, &backup_signature);
- if (!IsSearchProviderIDValid(backup_value, backup_signature)) {
+ if (!IsBackupSignatureValid()) {
UMA_HISTOGRAM_ENUMERATION(
protector::kProtectorHistogramDefaultSearchProvider,
protector::kProtectorErrorBackupInvalid,
protector::kProtectorErrorCount);
- SIMPLE_STATS_COUNTER(protector::kProtectorBackupInvalidCounter);
- return true;
- } else if (backup_value != GetDefaultSearchProviderID()) {
- UMA_HISTOGRAM_ENUMERATION(
- protector::kProtectorHistogramDefaultSearchProvider,
- protector::kProtectorErrorValueChanged,
- protector::kProtectorErrorCount);
- SIMPLE_STATS_COUNTER(protector::kProtectorValueChangedCounter);
return true;
}
+
+ int64 backup_id = 0;
+ meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_id);
+ int64 current_id = GetDefaultSearchProviderID();
+ if (backup_id == current_id) {
+ std::string backup_url;
+ std::string current_url;
+ // Either this is a new profile and both IDs are zero or the search
+ // engines with the ids are equal.
+ if (backup_id == 0) {
+ UMA_HISTOGRAM_ENUMERATION(
+ protector::kProtectorHistogramDefaultSearchProvider,
+ protector::kProtectorErrorValueValidZero,
+ protector::kProtectorErrorCount);
+ return false;
+ } else if (meta_table_->GetValue(kDefaultSearchBackupKey, &backup_url) &&
+ GetTemplateURLBackup(current_id, &current_url) &&
+ current_url == backup_url) {
+ UMA_HISTOGRAM_ENUMERATION(
+ protector::kProtectorHistogramDefaultSearchProvider,
+ protector::kProtectorErrorValueValid,
+ protector::kProtectorErrorCount);
+ return false;
+ }
+ }
+
UMA_HISTOGRAM_ENUMERATION(
protector::kProtectorHistogramDefaultSearchProvider,
- protector::kProtectorErrorValueValid,
+ protector::kProtectorErrorValueChanged,
protector::kProtectorErrorCount);
- SIMPLE_STATS_COUNTER(protector::kProtectorValueValidCounter);
- return false;
+ return true;
}
bool KeywordTable::SetBuiltinKeywordVersion(int version) {
@@ -385,31 +351,191 @@ bool KeywordTable::MigrateToVersion39AddSyncGUIDColumn() {
bool KeywordTable::MigrateToVersion40AddDefaultSearchProviderBackup() {
int64 value = 0;
if (!meta_table_->GetValue(kDefaultSearchProviderKey, &value)) {
- // Set default search provider ID and its backup.
- return SetDefaultSearchProviderID(0);
+ // Write default search provider id if it's absent. TemplateURLService
+ // will replace 0 with some real value.
+ if (!meta_table_->SetValue(kDefaultSearchProviderKey, 0))
+ return false;
}
- return SetDefaultSearchProviderBackupID(value);
+ return meta_table_->SetValue(kDefaultSearchIDBackupKey, value) &&
+ meta_table_->SetValue(
+ kBackupSignatureKey,
+ GetSearchProviderIDSignature(value));
}
bool KeywordTable::MigrateToVersion41RewriteDefaultSearchProviderBackup() {
// Due to crbug.com/101815 version 40 may contain corrupt or empty
// signature. So ignore the signature and simply rewrite it.
- int64 value = 0;
- if (!meta_table_->GetValue(kDefaultSearchProviderKey, &value)) {
- // Set default search provider ID and its backup.
- return SetDefaultSearchProviderID(0);
+ return MigrateToVersion40AddDefaultSearchProviderBackup();
+}
+
+bool KeywordTable::MigrateToVersion42AddKeywordsBackupTable() {
+ return UpdateBackupSignature();
+}
+
+std::string KeywordTable::GetSignatureData() {
+ int64 backup_value = 0;
+ if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_value)) {
+ NOTREACHED() << "Couldn't get id backup.";
+ return std::string();
+ }
+ std::string backup_data = base::Int64ToString(backup_value);
+
+ std::string backup_url;
+ if (!meta_table_->GetValue(kDefaultSearchBackupKey, &backup_url)) {
+ NOTREACHED() << "Couldn't get backup url";
+ return std::string();
+ }
+ backup_data += backup_url;
+
+ sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE,
+ "SELECT id || short_name || keyword || favicon_url || url || "
+ "safe_for_autoreplace || originating_url || date_created || "
+ "usage_count || input_encodings || show_in_default_list || "
+ "suggest_url || prepopulate_id || autogenerate_keyword || logo_id || "
+ "created_by_policy || instant_url || last_modified || sync_guid "
+ "FROM keywords ORDER BY id ASC"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return std::string();
+ }
+ while (s.Step())
+ backup_data += s.ColumnString(0);
+ if (!s.Succeeded()) {
+ NOTREACHED() << "Statement execution failed";
+ return std::string();
}
- return SetDefaultSearchProviderBackupID(value);
+ return backup_data;
}
-bool KeywordTable::SetDefaultSearchProviderBackupID(int64 id) {
- return
- meta_table_->SetValue(kDefaultSearchProviderBackupKey, id) &&
- SetDefaultSearchProviderBackupIDSignature(id);
+bool KeywordTable::UpdateBackupSignature() {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin()) {
+ NOTREACHED() << "Failed to begin transaction.";
+ return false;
+ }
+
+ // Backup of default search provider id.
+ int64 id = GetDefaultSearchProviderID();
+ if (!meta_table_->SetValue(kDefaultSearchIDBackupKey, id)) {
+ NOTREACHED() << "Failed to write backup id.";
+ return false;
+ }
+
+ // Backup of the default search provider info.
+ if (!UpdateDefaultSearchProviderBackup(id)) {
+ NOTREACHED() << "Failed to update backup.";
+ return false;
+ }
+
+ // Now calculate and update the signature.
+ std::string data_to_sign = GetSignatureData();
+ if (data_to_sign.empty()) {
+ NOTREACHED() << "Can't get data to sign";
+ return false;
+ }
+ std::string signature = protector::SignSetting(data_to_sign);
+ if (signature.empty()) {
+ NOTREACHED() << "Signature is empty";
+ return false;
+ }
+ if (!meta_table_->SetValue(kBackupSignatureKey, signature)) {
+ NOTREACHED() << "Failed to write signature.";
+ return false;
+ }
+
+ return transaction.Commit();
+}
+
+bool KeywordTable::IsBackupSignatureValid() {
+ std::string signature;
+ return meta_table_->GetValue(kBackupSignatureKey, &signature) &&
+ protector::IsSettingValid(GetSignatureData(), signature);
}
-bool KeywordTable::SetDefaultSearchProviderBackupIDSignature(int64 id) {
- return meta_table_->SetValue(
- kDefaultSearchProviderBackupSignatureKey,
- GetSearchProviderIDSignature(id));
+void KeywordTable::GetURLFromStatement(
+ const sql::Statement& s,
+ TemplateURL* url) {
+ url->set_id(s.ColumnInt64(0));
+
+ std::string tmp;
+ tmp = s.ColumnString(1);
+ DCHECK(!tmp.empty());
+ url->set_short_name(UTF8ToUTF16(tmp));
+
+ url->set_keyword(UTF8ToUTF16(s.ColumnString(2)));
+
+ tmp = s.ColumnString(3);
+ if (!tmp.empty())
+ url->SetFaviconURL(GURL(tmp));
+
+ url->SetURL(s.ColumnString(4), 0, 0);
+
+ url->set_safe_for_autoreplace(s.ColumnInt(5) == 1);
+
+ tmp = s.ColumnString(6);
+ if (!tmp.empty())
+ url->set_originating_url(GURL(tmp));
+
+ url->set_date_created(Time::FromTimeT(s.ColumnInt64(7)));
+
+ url->set_usage_count(s.ColumnInt(8));
+
+ std::vector<std::string> encodings;
+ base::SplitString(s.ColumnString(9), ';', &encodings);
+ url->set_input_encodings(encodings);
+
+ url->set_show_in_default_list(s.ColumnInt(10) == 1);
+
+ url->SetSuggestionsURL(s.ColumnString(11), 0, 0);
+
+ url->SetPrepopulateId(s.ColumnInt(12));
+
+ url->set_autogenerate_keyword(s.ColumnInt(13) == 1);
+
+ url->set_logo_id(s.ColumnInt(14));
+
+ url->set_created_by_policy(s.ColumnBool(15));
+
+ url->SetInstantURL(s.ColumnString(16), 0, 0);
+
+ url->set_last_modified(Time::FromTimeT(s.ColumnInt64(17)));
+
+ url->set_sync_guid(s.ColumnString(18));
+}
+
+bool KeywordTable::GetTemplateURLBackup(TemplateURLID id,
+ std::string* result) {
+ sql::Statement s(db_->GetUniqueStatement(
+ "SELECT id || short_name || keyword || favicon_url || url || "
+ "safe_for_autoreplace || originating_url || date_created || "
+ "usage_count || input_encodings || show_in_default_list || "
+ "suggest_url || prepopulate_id || autogenerate_keyword || logo_id || "
+ "created_by_policy || instant_url || last_modified || sync_guid "
+ "FROM keywords WHERE id=?"));
+ if (!s) {
+ NOTREACHED() << "Statement prepare failed";
+ return false;
+ }
+ s.BindInt64(0, id);
+ if (!s.Step()) {
+ LOG(WARNING) << "No keyword with id: " << id << ", ignoring.";
+ return true;
+ }
+
+ if (!s.Succeeded()) {
+ NOTREACHED() << "Statement failed.";
+ return false;
+ }
+
+ *result = s.ColumnString(0);
+ return true;
+}
+
+bool KeywordTable::UpdateDefaultSearchProviderBackup(TemplateURLID id) {
+ std::string backup;
+ if (id != 0 && !GetTemplateURLBackup(id, &backup)) {
+ NOTREACHED() << "Failed to get the keyword with id " << id;
+ return false;
+ }
+ return meta_table_->SetValue(kDefaultSearchBackupKey, backup);
}
diff --git a/chrome/browser/webdata/keyword_table.h b/chrome/browser/webdata/keyword_table.h
index 47bf5ef..bdcae34 100644
--- a/chrome/browser/webdata/keyword_table.h
+++ b/chrome/browser/webdata/keyword_table.h
@@ -16,6 +16,10 @@
class TemplateURL;
+namespace sql {
+class Statement;
+} // namespace sql
+
// This class manages the |keywords| MetaTable within the SQLite database
// passed to the constructor. It expects the following schema:
//
@@ -50,6 +54,24 @@ class TemplateURL;
// sync_guid See TemplateURL::sync_guid. This was added in
// version 39.
//
+// This class also manages some fields in the |meta| table:
+// Default Search Provider ID The id of the default search provider.
+// Default Search Provider ID Backup
+// Backup copy of the above for restoring it
+// in case the setting was hijacked or
+// corrupted. This was added in version 40.
+// Default Search Provider Backup Backup copy of the raw in |keywords|
+// with the default search provider ID to
+// restore all provider info. This was added
+// in version 42.
+// Default Search Provider ID Backup Signature
+// The signature of backup data and
+// |keywords| table contents to be able to
+// verify the backup and understand when the
+// settings were changed. This was added
+// in version 40.
+// Builtin Keyword Version The version of builtin keywords data.
+//
class KeywordTable : public WebDatabaseTable {
public:
KeywordTable(sql::Connection* db, sql::MetaTable* meta_table)
@@ -101,17 +123,35 @@ class KeywordTable : public WebDatabaseTable {
bool MigrateToVersion39AddSyncGUIDColumn();
bool MigrateToVersion40AddDefaultSearchProviderBackup();
bool MigrateToVersion41RewriteDefaultSearchProviderBackup();
+ bool MigrateToVersion42AddKeywordsBackupTable();
private:
FRIEND_TEST_ALL_PREFIXES(KeywordTableTest, DefaultSearchProviderBackup);
- // Sets backup for id of the default search provider.
- // Backup value is used to notice when unexpected change of the id
- // occurred (i.e. by third-party process trying to modify user settings).
- bool SetDefaultSearchProviderBackupID(int64 id);
+ // Returns contents of |keywords| table and default search provider backup
+ // as a string.
+ std::string GetSignatureData();
+
+ // Updates settings backup, signs it and stores the signature in the
+ // database. Returns true on success.
+ bool UpdateBackupSignature();
+
+ // Checks the signature for the current settings backup. Returns true
+ // if signature is valid, false otherwise.
+ bool IsBackupSignatureValid();
+
+ // Parses TemplateURL out of SQL statement result.
+ void GetURLFromStatement(const sql::Statement& s, TemplateURL* url);
+
+ // Gets a string representation for TemplateURL with id specified.
+ // Used to store its result in |meta| table or to compare with this
+ // backup. Returns true on success, false otherwise.
+ bool GetTemplateURLBackup(TemplateURLID id, std::string* result);
- // Sets signature for the backup field.
- bool SetDefaultSearchProviderBackupIDSignature(int64 id);
+ // Updates default search provider backup with TemplateURL data with
+ // specified id. Returns true on success.
+ // If id is 0, sets an empty string as a backup.
+ bool UpdateDefaultSearchProviderBackup(TemplateURLID id);
DISALLOW_COPY_AND_ASSIGN(KeywordTable);
};
diff --git a/chrome/browser/webdata/keyword_table_unittest.cc b/chrome/browser/webdata/keyword_table_unittest.cc
index 8f282fa..37e923f 100644
--- a/chrome/browser/webdata/keyword_table_unittest.cc
+++ b/chrome/browser/webdata/keyword_table_unittest.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/webdata/keyword_table.h"
#include "chrome/browser/webdata/web_database.h"
+#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
@@ -149,6 +150,30 @@ TEST_F(KeywordTableTest, KeywordMisc) {
ASSERT_EQ(0, db.GetKeywordTable()->GetDefaultSearchProviderID());
ASSERT_EQ(0, db.GetKeywordTable()->GetBuiltinKeywordVersion());
+ TemplateURL template_url;
+ template_url.set_short_name(ASCIIToUTF16("short_name"));
+ template_url.set_keyword(ASCIIToUTF16("keyword"));
+ GURL favicon_url("http://favicon.url/");
+ GURL originating_url("http://google.com/");
+ template_url.SetFaviconURL(favicon_url);
+ template_url.SetURL("http://url/", 0, 0);
+ template_url.set_safe_for_autoreplace(true);
+ Time created_time = Time::Now();
+ template_url.set_date_created(created_time);
+ Time last_modified_time = created_time + TimeDelta::FromSeconds(10);
+ template_url.set_last_modified(last_modified_time);
+ template_url.set_show_in_default_list(true);
+ template_url.set_originating_url(originating_url);
+ template_url.set_usage_count(32);
+ template_url.add_input_encoding("UTF-8");
+ template_url.add_input_encoding("UTF-16");
+ set_prepopulate_id(&template_url, 10);
+ set_logo_id(&template_url, 1000);
+ template_url.set_created_by_policy(true);
+ template_url.SetInstantURL("http://instant/", 0, 0);
+ SetID(10, &template_url);
+ ASSERT_TRUE(db.GetKeywordTable()->AddKeyword(template_url));
+
ASSERT_TRUE(db.GetKeywordTable()->SetDefaultSearchProviderID(10));
ASSERT_TRUE(db.GetKeywordTable()->SetBuiltinKeywordVersion(11));
@@ -163,14 +188,62 @@ TEST_F(KeywordTableTest, DefaultSearchProviderBackup) {
EXPECT_EQ(0, db.GetKeywordTable()->GetDefaultSearchProviderID());
- ASSERT_TRUE(db.GetKeywordTable()->SetDefaultSearchProviderID(10));
- EXPECT_EQ(10, db.GetKeywordTable()->GetDefaultSearchProviderID());
- EXPECT_EQ(10, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
+ TemplateURL template_url;
+ template_url.set_short_name(ASCIIToUTF16("short_name"));
+ template_url.set_keyword(ASCIIToUTF16("keyword"));
+ GURL favicon_url("http://favicon.url/");
+ GURL originating_url("http://originating.url/");
+ template_url.SetFaviconURL(favicon_url);
+ template_url.SetURL("http://url/", 0, 0);
+ template_url.set_safe_for_autoreplace(true);
+ template_url.set_show_in_default_list(true);
+ template_url.SetSuggestionsURL("url2", 0, 0);
+ SetID(1, &template_url);
+
+ EXPECT_TRUE(db.GetKeywordTable()->AddKeyword(template_url));
+
+ ASSERT_TRUE(db.GetKeywordTable()->SetDefaultSearchProviderID(1));
+ EXPECT_TRUE(db.GetKeywordTable()->IsBackupSignatureValid());
+ EXPECT_EQ(1, db.GetKeywordTable()->GetDefaultSearchProviderID());
+ EXPECT_EQ(1, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
EXPECT_FALSE(db.GetKeywordTable()->DidDefaultSearchProviderChange());
- ASSERT_TRUE(db.GetKeywordTable()->SetDefaultSearchProviderBackupID(11));
- EXPECT_EQ(10, db.GetKeywordTable()->GetDefaultSearchProviderID());
- EXPECT_EQ(11, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
+ // Change the actual setting.
+ ASSERT_TRUE(db.GetKeywordTable()->meta_table_->SetValue(
+ "Default Search Provider ID", 2));
+ EXPECT_TRUE(db.GetKeywordTable()->IsBackupSignatureValid());
+ EXPECT_EQ(2, db.GetKeywordTable()->GetDefaultSearchProviderID());
+ EXPECT_EQ(1, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
+ EXPECT_TRUE(db.GetKeywordTable()->DidDefaultSearchProviderChange());
+
+ // Change the backup.
+ ASSERT_TRUE(db.GetKeywordTable()->meta_table_->SetValue(
+ "Default Search Provider ID", 1));
+ ASSERT_TRUE(db.GetKeywordTable()->meta_table_->SetValue(
+ "Default Search Provider ID Backup", 2));
+ EXPECT_FALSE(db.GetKeywordTable()->IsBackupSignatureValid());
+ EXPECT_EQ(1, db.GetKeywordTable()->GetDefaultSearchProviderID());
+ EXPECT_EQ(0, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
+ EXPECT_TRUE(db.GetKeywordTable()->DidDefaultSearchProviderChange());
+
+ // Change the signature.
+ ASSERT_TRUE(db.GetKeywordTable()->meta_table_->SetValue(
+ "Default Search Provider ID Backup", 1));
+ ASSERT_TRUE(db.GetKeywordTable()->meta_table_->SetValue(
+ "Default Search Provider ID Backup Signature", ""));
+ EXPECT_FALSE(db.GetKeywordTable()->IsBackupSignatureValid());
+ EXPECT_EQ(1, db.GetKeywordTable()->GetDefaultSearchProviderID());
+ EXPECT_EQ(0, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
+ EXPECT_TRUE(db.GetKeywordTable()->DidDefaultSearchProviderChange());
+
+ // Change keywords.
+ ASSERT_TRUE(db.GetKeywordTable()->UpdateBackupSignature());
+ sql::Statement remove_keyword(db.GetKeywordTable()->db_->GetUniqueStatement(
+ "DELETE FROM keywords WHERE id=1"));
+ ASSERT_TRUE(remove_keyword.Run());
+ EXPECT_FALSE(db.GetKeywordTable()->IsBackupSignatureValid());
+ EXPECT_EQ(1, db.GetKeywordTable()->GetDefaultSearchProviderID());
+ EXPECT_EQ(0, db.GetKeywordTable()->GetDefaultSearchProviderIDBackup());
EXPECT_TRUE(db.GetKeywordTable()->DidDefaultSearchProviderChange());
}
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index ab93542..be598de 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -22,8 +22,8 @@ namespace {
// 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 = 41;
-const int kCompatibleVersionNumber = 41;
+const int kCurrentVersionNumber = 42;
+const int kCompatibleVersionNumber = 42;
// Change the version number and possibly the compatibility version of
// |meta_table_|.
@@ -319,6 +319,13 @@ sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded() {
ChangeVersion(&meta_table_, 41, true);
// FALL THROUGH
+ case 41:
+ if (!keyword_table_->MigrateToVersion42AddKeywordsBackupTable())
+ return FailedMigrationTo(42);
+
+ ChangeVersion(&meta_table_, 42, 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 ef5dbd1..76004d5 100644
--- a/chrome/browser/webdata/web_database_migration_unittest.cc
+++ b/chrome/browser/webdata/web_database_migration_unittest.cc
@@ -196,7 +196,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 41;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 42;
void WebDatabaseMigrationTest::LoadDatabase(const FilePath::StringType& file) {
std::string contents;
@@ -1655,3 +1655,104 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion40ToCurrent) {
}
}
+// Tests that all keywords are backed up and signed.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion41ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_41.sql")));
+
+ // Verify pre-conditions. These are expectations for version 40 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, 41, 41));
+
+ int64 default_search_provider_id = 0;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider ID",
+ &default_search_provider_id));
+
+ int64 default_search_provider_id_backup = 0;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider ID Backup",
+ &default_search_provider_id_backup));
+
+ std::string default_search_provider_id_backup_signature;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider ID Backup Signature",
+ &default_search_provider_id_backup_signature));
+ EXPECT_FALSE(default_search_provider_id_backup_signature.empty());
+
+ std::string default_search_provider_backup;
+ EXPECT_FALSE(meta_table.GetValue(
+ "Default Search Provider Backup",
+ &default_search_provider_backup));
+ }
+
+ // 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));
+
+ int64 default_search_provider_id = 0;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider ID",
+ &default_search_provider_id));
+ EXPECT_NE(0, default_search_provider_id);
+
+ int64 default_search_provider_id_backup = 0;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider ID Backup",
+ &default_search_provider_id_backup));
+ EXPECT_EQ(default_search_provider_id, default_search_provider_id_backup);
+
+ std::string default_search_provider_id_backup_signature;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider ID Backup Signature",
+ &default_search_provider_id_backup_signature));
+ EXPECT_FALSE(default_search_provider_id_backup_signature.empty());
+
+ std::string default_search_provider_backup;
+ EXPECT_TRUE(meta_table.GetValue(
+ "Default Search Provider Backup",
+ &default_search_provider_backup));
+ EXPECT_EQ("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}"
+ "100"
+ "UTF-8"
+ "1"
+ "{google:baseSuggestURL}search?client=chrome&hl={language}&"
+ "q={searchTerms}"
+ "1162620"
+ "{google:baseURL}webhp?{google:RLZ}sourceid=chrome-instant&"
+ "ie={inputEncoding}&ion=1{searchTerms}&nord=10"
+ "{1234-5678-90AB-CDEF}",
+ default_search_provider_backup);
+ }
+}
+
diff --git a/chrome/test/data/web_database/version_24.sql b/chrome/test/data/web_database/version_24.sql
index 5cc2bb6..624f7e5 100644
--- a/chrome/test/data/web_database/version_24.sql
+++ b/chrome/test/data/web_database/version_24.sql
@@ -3,7 +3,6 @@ BEGIN TRANSACTION;
CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
INSERT INTO "meta" VALUES('version','24');
INSERT INTO "meta" VALUES('last_compatible_version','24');
-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);
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));
diff --git a/chrome/test/data/web_database/version_25.sql b/chrome/test/data/web_database/version_25.sql
index 3e17f85..986ca9f 100644
--- a/chrome/test/data/web_database/version_25.sql
+++ b/chrome/test/data/web_database/version_25.sql
@@ -3,7 +3,6 @@ BEGIN TRANSACTION;
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('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);
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));
diff --git a/chrome/test/data/web_database/version_26.sql b/chrome/test/data/web_database/version_26.sql
index 3ef7dd5..5cf1a97 100644
--- a/chrome/test/data/web_database/version_26.sql
+++ b/chrome/test/data/web_database/version_26.sql
@@ -3,7 +3,6 @@ BEGIN TRANSACTION;
CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
INSERT INTO "meta" VALUES('version','26');
INSERT INTO "meta" VALUES('last_compatible_version','26');
-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);
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));
diff --git a/chrome/test/data/web_database/version_27.sql b/chrome/test/data/web_database/version_27.sql
index 91985ff..4733afa 100644
--- a/chrome/test/data/web_database/version_27.sql
+++ b/chrome/test/data/web_database/version_27.sql
@@ -3,7 +3,6 @@ BEGIN TRANSACTION;
CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
INSERT INTO "meta" VALUES('version','27');
INSERT INTO "meta" VALUES('last_compatible_version','27');
-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);
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);
diff --git a/chrome/test/data/web_database/version_41.sql b/chrome/test/data/web_database/version_41.sql
new file mode 100644
index 0000000..8f7497f
--- /dev/null
+++ b/chrome/test/data/web_database/version_41.sql
@@ -0,0 +1,30 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','40');
+INSERT INTO "meta" VALUES('last_compatible_version','40');
+INSERT INTO "meta" VALUES('Default Search Provider ID','2');
+INSERT INTO "meta" VALUES('Default Search Provider ID Backup','2');
+INSERT INTO "meta" VALUES('Default Search Provider ID Backup Signature','Signature');
+INSERT INTO "meta" VALUES('Builtin Keyword Version','33');
+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,last_modified INTEGER DEFAULT 0, sync_guid 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,6262,0,'{google:baseURL}webhp?{google:RLZ}sourceid=chrome-instant&ie={inputEncoding}&ion=1{searchTerms}&nord=1',0,'{1234-5678-90AB-CDEF}');
+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 ( 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 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 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);
+COMMIT;
+
+