// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/webdata/keyword_table.h"
#include "app/sql/statement.h"
#include "base/logging.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/search_engines/template_url.h"
#include "googleurl/src/gurl.h"
using base::Time;
namespace {
// ID of the url column in keywords.
const int kUrlIdPosition = 16;
// Keys used in the meta table.
const char* kDefaultSearchProviderKey = "Default Search Provider ID";
const char* kBuiltinKeywordVersion = "Builtin Keyword Version";
void BindURLToStatement(const TemplateURL& url, sql::Statement* s) {
s->BindString(0, UTF16ToUTF8(url.short_name()));
s->BindString(1, UTF16ToUTF8(url.keyword()));
GURL favicon_url = url.GetFaviconURL();
if (!favicon_url.is_valid()) {
s->BindString(2, std::string());
} else {
s->BindString(2, history::HistoryDatabase::GURLToDatabaseURL(
url.GetFaviconURL()));
}
s->BindString(3, url.url() ? url.url()->url() : std::string());
s->BindInt(4, url.safe_for_autoreplace() ? 1 : 0);
if (!url.originating_url().is_valid()) {
s->BindString(5, std::string());
} else {
s->BindString(5, history::HistoryDatabase::GURLToDatabaseURL(
url.originating_url()));
}
s->BindInt64(6, url.date_created().ToTimeT());
s->BindInt(7, url.usage_count());
s->BindString(8, JoinString(url.input_encodings(), ';'));
s->BindInt(9, url.show_in_default_list() ? 1 : 0);
s->BindString(10, url.suggestions_url() ? url.suggestions_url()->url() :
std::string());
s->BindInt(11, url.prepopulate_id());
s->BindInt(12, url.autogenerate_keyword() ? 1 : 0);
s->BindInt(13, url.logo_id());
s->BindBool(14, url.created_by_policy());
s->BindString(15, url.instant_url() ? url.instant_url()->url() :
std::string());
}
} // anonymous namespace
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)")) {
NOTREACHED();
return false;
}
}
return true;
}
bool KeywordTable::IsSyncable() {
return true;
}
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,
"INSERT INTO keywords "
"(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, "
"id) VALUES "
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
}
BindURLToStatement(url, &s);
s.BindInt64(kUrlIdPosition, url.id());
if (!s.Run()) {
NOTREACHED();
return false;
}
return true;
}
bool KeywordTable::RemoveKeyword(TemplateURLID id) {
DCHECK(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();
}
bool KeywordTable::GetKeywords(std::vector<TemplateURL*>* urls) {
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 "
"FROM keywords ORDER BY id ASC"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
}
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->set_prepopulate_id(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);
urls->push_back(template_url);
}
return s.Succeeded();
}
bool KeywordTable::UpdateKeyword(const TemplateURL& url) {
DCHECK(url.id());
// Be sure to change kUrlIdPosition if you add columns
sql::Statement s(db_->GetUniqueStatement(
"UPDATE keywords "
"SET 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=? WHERE id=?"));
if (!s) {
NOTREACHED() << "Statement prepare failed";
return false;
}
BindURLToStatement(url, &s);
s.BindInt64(kUrlIdPosition, url.id());
return s.Run();
}
bool KeywordTable::SetDefaultSearchProviderID(int64 id) {
return meta_table_->SetValue(kDefaultSearchProviderKey, id);
}
int64 KeywordTable::GetDefaulSearchProviderID() {
int64 value = 0;
meta_table_->GetValue(kDefaultSearchProviderKey, &value);
return value;
}
bool KeywordTable::SetBuitinKeywordVersion(int version) {
return meta_table_->SetValue(kBuiltinKeywordVersion, version);
}
int KeywordTable::GetBuitinKeywordVersion() {
int version = 0;
meta_table_->GetValue(kBuiltinKeywordVersion, &version);
return version;
}
bool KeywordTable::MigrateToVersion21AutoGenerateKeywordColumn() {
return db_->Execute("ALTER TABLE keywords ADD COLUMN autogenerate_keyword "
"INTEGER DEFAULT 0");
}
bool KeywordTable::MigrateToVersion25AddLogoIDColumn() {
return db_->Execute(
"ALTER TABLE keywords ADD COLUMN logo_id INTEGER DEFAULT 0");
}
bool KeywordTable::MigrateToVersion26AddCreatedByPolicyColumn() {
return db_->Execute("ALTER TABLE keywords ADD COLUMN created_by_policy "
"INTEGER DEFAULT 0");
}
bool KeywordTable::MigrateToVersion28SupportsInstantColumn() {
return db_->Execute("ALTER TABLE keywords ADD COLUMN supports_instant "
"INTEGER DEFAULT 0");
}
bool KeywordTable::MigrateToVersion29InstantUrlToSupportsInstant() {
if (!db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url VARCHAR"))
return false;
if (!db_->Execute("CREATE TABLE keywords_temp ("
"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)")) {
return false;
}
if (!db_->Execute(
"INSERT INTO keywords_temp "
"SELECT id, short_name, keyword, favicon_url, url, "
"show_in_default_list, safe_for_autoreplace, originating_url, "
"date_created, usage_count, input_encodings, suggest_url, "
"prepopulate_id, autogenerate_keyword, logo_id, created_by_policy, "
"instant_url FROM keywords")) {
return false;
}
if (!db_->Execute("DROP TABLE keywords"))
return false;
if (!db_->Execute("ALTER TABLE keywords_temp RENAME TO keywords"))
return false;
return true;
}