diff options
author | avayvod@chromium.org <avayvod@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-03 08:45:24 +0000 |
---|---|---|
committer | avayvod@chromium.org <avayvod@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-03 08:45:24 +0000 |
commit | 67bb274ea8015b43706f81d207f15153f31ac3a4 (patch) | |
tree | e1a10329ca6b70b91c1710aeca4bb4c679fc4be5 | |
parent | a46748425a6d409ebeb0cb098ba85fa8091c0cac (diff) | |
download | chromium_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.cc | 5 | ||||
-rw-r--r-- | chrome/browser/protector/histograms.h | 8 | ||||
-rw-r--r-- | chrome/browser/webdata/keyword_table.cc | 366 | ||||
-rw-r--r-- | chrome/browser/webdata/keyword_table.h | 52 | ||||
-rw-r--r-- | chrome/browser/webdata/keyword_table_unittest.cc | 85 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database.cc | 11 | ||||
-rw-r--r-- | chrome/browser/webdata/web_database_migration_unittest.cc | 103 | ||||
-rw-r--r-- | chrome/test/data/web_database/version_24.sql | 1 | ||||
-rw-r--r-- | chrome/test/data/web_database/version_25.sql | 1 | ||||
-rw-r--r-- | chrome/test/data/web_database/version_26.sql | 1 | ||||
-rw-r--r-- | chrome/test/data/web_database/version_27.sql | 1 | ||||
-rw-r--r-- | chrome/test/data/web_database/version_41.sql | 30 |
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, ¤t_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; + + |