| Index: chrome/browser/webdata/keyword_table.cc
|
| diff --git a/chrome/browser/webdata/keyword_table.cc b/chrome/browser/webdata/keyword_table.cc
|
| index fd0cb029d3ea712f231f6fadefade100292c7940..6d3a06453dafdd7a3ff111088450ef46809bba3a 100644
|
| --- a/chrome/browser/webdata/keyword_table.cc
|
| +++ b/chrome/browser/webdata/keyword_table.cc
|
| @@ -6,6 +6,8 @@
|
|
|
| #include <set>
|
|
|
| +#include "base/json/json_reader.h"
|
| +#include "base/json/json_writer.h"
|
| #include "base/logging.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/metrics/histogram.h"
|
| @@ -15,6 +17,7 @@
|
| #include "base/string_util.h"
|
| #include "base/stringprintf.h"
|
| #include "base/utf_string_conversions.h"
|
| +#include "base/values.h"
|
| #include "chrome/browser/history/history_database.h"
|
| #include "chrome/browser/protector/histograms.h"
|
| #include "chrome/browser/protector/protector_utils.h"
|
| @@ -35,40 +38,45 @@ const char KeywordTable::kDefaultSearchIDBackupKey[] =
|
| "Default Search Provider ID Backup";
|
| const char KeywordTable::kBackupSignatureKey[] =
|
| "Default Search Provider ID Backup Signature";
|
| -const char KeywordTable::kKeywordColumns[] = "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, created_by_policy, instant_url, last_modified, sync_guid";
|
|
|
| namespace {
|
|
|
| // Keys used in the meta table.
|
| const char kBuiltinKeywordVersion[] = "Builtin Keyword Version";
|
|
|
| -// The set of columns up through version 44. (There were different columns
|
| -// below version 29 but none of the code below needs to worry about that case.)
|
| -const char kKeywordColumnsVersion44Concatenated[] = "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";
|
| -const char kKeywordColumnsVersion44[] = "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";
|
| -// NOTE: Remember to change what |kKeywordColumnsVersion45| says if the column
|
| -// set in |kKeywordColumns| changes, and update any code that needs to switch
|
| -// column sets based on a version number!
|
| -const char* const kKeywordColumnsVersion45 = KeywordTable::kKeywordColumns;
|
| -
|
| -// The current columns.
|
| -const char kKeywordColumnsConcatenated[] = "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 || created_by_policy || instant_url || "
|
| - "last_modified || sync_guid";
|
| +const std::string ColumnsForVersion(int version, bool concatenated) {
|
| + std::vector<std::string> columns;
|
| +
|
| + columns.push_back("id");
|
| + columns.push_back("short_name");
|
| + columns.push_back("keyword");
|
| + columns.push_back("favicon_url");
|
| + columns.push_back("url");
|
| + columns.push_back("safe_for_autoreplace");
|
| + columns.push_back("originating_url");
|
| + columns.push_back("date_created");
|
| + columns.push_back("usage_count");
|
| + columns.push_back("input_encodings");
|
| + columns.push_back("show_in_default_list");
|
| + columns.push_back("suggest_url");
|
| + columns.push_back("prepopulate_id");
|
| + if (version <= 44) {
|
| + // Columns removed after version 44.
|
| + columns.push_back("autogenerate_keyword");
|
| + columns.push_back("logo_id");
|
| + }
|
| + columns.push_back("created_by_policy");
|
| + columns.push_back("instant_url");
|
| + columns.push_back("last_modified");
|
| + columns.push_back("sync_guid");
|
| + if (version >= 47) {
|
| + // Column added in version 47.
|
| + columns.push_back("alternate_urls");
|
| + }
|
| +
|
| + return JoinString(columns, std::string(concatenated ? " || " : ", "));
|
| +}
|
| +
|
|
|
| // Inserts the data from |data| into |s|. |s| is assumed to have slots for all
|
| // the columns in the keyword table. |id_column| is the slot number to bind
|
| @@ -78,6 +86,16 @@ void BindURLToStatement(const TemplateURLData& data,
|
| sql::Statement* s,
|
| int id_column,
|
| int starting_column) {
|
| + // Serialize |alternate_urls| to JSON.
|
| + // TODO(beaudoin): Check what it would take to use a new table to store
|
| + // alternate_urls while keeping backups and table signature in a good state.
|
| + // See: crbug.com/153520
|
| + ListValue alternate_urls_value;
|
| + for (size_t i = 0; i < data.alternate_urls.size(); ++i)
|
| + alternate_urls_value.AppendString(data.alternate_urls[i]);
|
| + std::string alternate_urls;
|
| + base::JSONWriter::Write(&alternate_urls_value, &alternate_urls);
|
| +
|
| s->BindInt64(id_column, data.id);
|
| s->BindString16(starting_column, data.short_name);
|
| s->BindString16(starting_column + 1, data.keyword());
|
| @@ -99,6 +117,7 @@ void BindURLToStatement(const TemplateURLData& data,
|
| s->BindString(starting_column + 13, data.instant_url);
|
| s->BindInt64(starting_column + 14, data.last_modified.ToTimeT());
|
| s->BindString(starting_column + 15, data.sync_guid);
|
| + s->BindString(starting_column + 16, alternate_urls);
|
| }
|
|
|
| } // anonymous namespace
|
| @@ -129,7 +148,8 @@ bool KeywordTable::Init() {
|
| "created_by_policy INTEGER DEFAULT 0,"
|
| "instant_url VARCHAR,"
|
| "last_modified INTEGER DEFAULT 0,"
|
| - "sync_guid VARCHAR)") &&
|
| + "sync_guid VARCHAR,"
|
| + "alternate_urls VARCHAR)") &&
|
| UpdateBackupSignature(WebDatabase::kCurrentVersionNumber));
|
| }
|
|
|
| @@ -139,8 +159,8 @@ bool KeywordTable::IsSyncable() {
|
|
|
| bool KeywordTable::AddKeyword(const TemplateURLData& data) {
|
| DCHECK(data.id);
|
| - std::string query("INSERT INTO keywords (" + std::string(kKeywordColumns) +
|
| - ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
| + std::string query("INSERT INTO keywords (" + GetKeywordColumns() +
|
| + ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
| sql::Statement s(db_->GetUniqueStatement(query.c_str()));
|
| BindURLToStatement(data, &s, 0, 1);
|
|
|
| @@ -157,7 +177,7 @@ bool KeywordTable::RemoveKeyword(TemplateURLID id) {
|
| }
|
|
|
| bool KeywordTable::GetKeywords(Keywords* keywords) {
|
| - std::string query("SELECT " + std::string(kKeywordColumns) +
|
| + std::string query("SELECT " + GetKeywordColumns() +
|
| " FROM keywords ORDER BY id ASC");
|
| sql::Statement s(db_->GetUniqueStatement(query.c_str()));
|
|
|
| @@ -182,9 +202,9 @@ bool KeywordTable::UpdateKeyword(const TemplateURLData& data) {
|
| "keyword=?, favicon_url=?, url=?, safe_for_autoreplace=?, "
|
| "originating_url=?, date_created=?, usage_count=?, input_encodings=?, "
|
| "show_in_default_list=?, suggest_url=?, prepopulate_id=?, "
|
| - "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=? WHERE "
|
| - "id=?"));
|
| - BindURLToStatement(data, &s, 16, 0); // "16" binds id() as the last item.
|
| + "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=?, "
|
| + "alternate_urls=? WHERE id=?"));
|
| + BindURLToStatement(data, &s, 17, 0); // "17" binds id() as the last item.
|
|
|
| return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber);
|
| }
|
| @@ -212,7 +232,7 @@ bool KeywordTable::GetDefaultSearchProviderBackup(TemplateURLData* backup) {
|
| LOG(ERROR) << "No default search id backup found.";
|
| return false;
|
| }
|
| - std::string query("SELECT " + std::string(kKeywordColumns) +
|
| + std::string query("SELECT " + GetKeywordColumns() +
|
| " FROM keywords_backup WHERE id=?");
|
| sql::Statement s(db_->GetUniqueStatement(query.c_str()));
|
| s.BindInt64(0, backup_id);
|
| @@ -289,6 +309,11 @@ int KeywordTable::GetBuiltinKeywordVersion() {
|
| return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0;
|
| }
|
|
|
| +// static
|
| +std::string KeywordTable::GetKeywordColumns() {
|
| + return ColumnsForVersion(WebDatabase::kCurrentVersionNumber, false);
|
| +}
|
| +
|
| bool KeywordTable::MigrateToVersion21AutoGenerateKeywordColumn() {
|
| return db_->Execute("ALTER TABLE keywords ADD COLUMN autogenerate_keyword "
|
| "INTEGER DEFAULT 0");
|
| @@ -309,7 +334,7 @@ bool KeywordTable::MigrateToVersion28SupportsInstantColumn() {
|
| "INTEGER DEFAULT 0");
|
| }
|
|
|
| -bool KeywordTable::MigrateToVersion29InstantUrlToSupportsInstant() {
|
| +bool KeywordTable::MigrateToVersion29InstantURLToSupportsInstant() {
|
| sql::Transaction transaction(db_);
|
| return transaction.Begin() &&
|
| db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url VARCHAR") &&
|
| @@ -386,10 +411,39 @@ bool KeywordTable::MigrateToVersion45RemoveLogoIDAndAutogenerateColumns() {
|
| return transaction.Commit();
|
| }
|
|
|
| +bool KeywordTable::MigrateToVersion47AddAlternateURLsColumn() {
|
| + sql::Transaction transaction(db_);
|
| +
|
| + // Fill the |alternate_urls| column with empty strings, otherwise it breaks
|
| + // code relying on GetTableContents that concatenates the strings from all
|
| + // the columns.
|
| + if (!transaction.Begin() ||
|
| + !db_->Execute("ALTER TABLE keywords ADD COLUMN "
|
| + "alternate_urls VARCHAR DEFAULT ''"))
|
| + return false;
|
| +
|
| + if (IsBackupSignatureValid(46)) {
|
| + // Migrate the keywords backup table as well.
|
| + if (!db_->Execute("ALTER TABLE keywords_backup ADD COLUMN "
|
| + "alternate_urls VARCHAR DEFAULT ''") ||
|
| + !SignBackup(47))
|
| + return false;
|
| + } else {
|
| + // Old backup was invalid; drop the table entirely, which will trigger the
|
| + // protector code to prompt the user and recreate the table.
|
| + if (db_->DoesTableExist("keywords_backup") &&
|
| + !db_->Execute("DROP TABLE keywords_backup"))
|
| + return false;
|
| + }
|
| +
|
| + return transaction.Commit();
|
| +}
|
| +
|
| // static
|
| bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
|
| TemplateURLData* data) {
|
| DCHECK(data);
|
| +
|
| data->short_name = s.ColumnString16(1);
|
| data->SetKeyword(s.ColumnString16(2));
|
| // Due to past bugs, we might have persisted entries with empty URLs. Avoid
|
| @@ -413,6 +467,19 @@ bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
|
| data->usage_count = s.ColumnInt(8);
|
| data->prepopulate_id = s.ColumnInt(12);
|
| data->sync_guid = s.ColumnString(16);
|
| +
|
| + data->alternate_urls.clear();
|
| + base::JSONReader json_reader;
|
| + scoped_ptr<Value> value(json_reader.ReadToValue(s.ColumnString(17)));
|
| + ListValue* alternate_urls_value;
|
| + if (value.get() && value->GetAsList(&alternate_urls_value)) {
|
| + std::string alternate_url;
|
| + for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) {
|
| + if (alternate_urls_value->GetString(i, &alternate_url))
|
| + data->alternate_urls.push_back(alternate_url);
|
| + }
|
| + }
|
| +
|
| return true;
|
| }
|
|
|
| @@ -444,9 +511,7 @@ bool KeywordTable::GetTableContents(const char* table_name,
|
| return false;
|
|
|
| contents->clear();
|
| - std::string query("SELECT " +
|
| - std::string((table_version <= 44) ?
|
| - kKeywordColumnsVersion44Concatenated : kKeywordColumnsConcatenated) +
|
| + std::string query("SELECT " + ColumnsForVersion(table_version, true) +
|
| " FROM " + std::string(table_name) + " ORDER BY id ASC");
|
| sql::Statement s((table_version == WebDatabase::kCurrentVersionNumber) ?
|
| db_->GetCachedStatement(sql::StatementID(table_name), query.c_str()) :
|
| @@ -473,8 +538,7 @@ bool KeywordTable::UpdateBackupSignature(int table_version) {
|
| return false;
|
|
|
| std::string query("CREATE TABLE keywords_backup AS SELECT " +
|
| - std::string((table_version <= 44) ?
|
| - kKeywordColumnsVersion44 : kKeywordColumns) +
|
| + ColumnsForVersion(table_version, false) +
|
| " FROM keywords ORDER BY id ASC");
|
| if (!db_->Execute(query.c_str())) {
|
| LOG(ERROR) << "Failed to create keywords_backup table.";
|
| @@ -511,7 +575,8 @@ bool KeywordTable::IsBackupSignatureValid(int table_version) {
|
| bool KeywordTable::GetKeywordAsString(TemplateURLID id,
|
| const std::string& table_name,
|
| std::string* result) {
|
| - std::string query("SELECT " + std::string(kKeywordColumnsConcatenated) +
|
| + std::string query("SELECT " +
|
| + ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) +
|
| " FROM " + table_name + " WHERE id=?");
|
| sql::Statement s(db_->GetUniqueStatement(query.c_str()));
|
| s.BindInt64(0, id);
|
| @@ -564,7 +629,7 @@ bool KeywordTable::MigrateKeywordsTableForVersion45(const std::string& name) {
|
| "sync_guid VARCHAR)"))
|
| return false;
|
| std::string sql("INSERT INTO keywords_temp SELECT " +
|
| - std::string(kKeywordColumnsVersion45) + " FROM " + name);
|
| + ColumnsForVersion(46, false) + " FROM " + name);
|
| if (!db_->Execute(sql.c_str()))
|
| return false;
|
|
|
|
|