15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/webdata/keyword_table.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_database.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/search_engines/search_terms_data.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_database.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/transaction.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char KeywordTable::kDefaultSearchProviderKey[] =
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Default Search Provider ID";
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keys used in the meta table.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kBuiltinKeywordVersion[] = "Builtin Keyword Version";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string ColumnsForVersion(int version, bool concatenated) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> columns;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("id");
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("short_name");
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("keyword");
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("favicon_url");
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("url");
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("safe_for_autoreplace");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("originating_url");
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("date_created");
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("usage_count");
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("input_encodings");
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("show_in_default_list");
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("suggest_url");
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("prepopulate_id");
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version <= 44) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Columns removed after version 44.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    columns.push_back("autogenerate_keyword");
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    columns.push_back("logo_id");
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("created_by_policy");
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("instant_url");
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("last_modified");
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  columns.push_back("sync_guid");
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (version >= 47) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Column added in version 47.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    columns.push_back("alternate_urls");
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (version >= 49) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Column added in version 49.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    columns.push_back("search_terms_replacement_key");
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (version >= 52) {
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Column added in version 52.
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    columns.push_back("image_url");
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    columns.push_back("search_url_post_params");
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    columns.push_back("suggest_url_post_params");
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    columns.push_back("instant_url_post_params");
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    columns.push_back("image_url_post_params");
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (version >= 53) {
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Column added in version 53.
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    columns.push_back("new_tab_url");
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return JoinString(columns, std::string(concatenated ? " || " : ", "));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Inserts the data from |data| into |s|.  |s| is assumed to have slots for all
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the columns in the keyword table.  |id_column| is the slot number to bind
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |data|'s |id| to; |starting_column| is the slot number of the first of a
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contiguous set of slots to bind all the other fields to.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BindURLToStatement(const TemplateURLData& data,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sql::Statement* s,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int id_column,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int starting_column) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Serialize |alternate_urls| to JSON.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(beaudoin): Check what it would take to use a new table to store
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // alternate_urls while keeping backups and table signature in a good state.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See: crbug.com/153520
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue alternate_urls_value;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < data.alternate_urls.size(); ++i)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    alternate_urls_value.AppendString(data.alternate_urls[i]);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string alternate_urls;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::JSONWriter::Write(&alternate_urls_value, &alternate_urls);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindInt64(id_column, data.id);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString16(starting_column, data.short_name);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString16(starting_column + 1, data.keyword());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 2, data.favicon_url.is_valid() ?
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history::HistoryDatabase::GURLToDatabaseURL(data.favicon_url) :
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 3, data.url());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindBool(starting_column + 4, data.safe_for_autoreplace);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 5, data.originating_url.is_valid() ?
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      history::HistoryDatabase::GURLToDatabaseURL(data.originating_url) :
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindInt64(starting_column + 6, data.date_created.ToTimeT());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindInt(starting_column + 7, data.usage_count);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 8, JoinString(data.input_encodings, ';'));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindBool(starting_column + 9, data.show_in_default_list);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 10, data.suggestions_url);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindInt(starting_column + 11, data.prepopulate_id);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindBool(starting_column + 12, data.created_by_policy);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 13, data.instant_url);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindInt64(starting_column + 14, data.last_modified.ToTimeT());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 15, data.sync_guid);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(starting_column + 16, alternate_urls);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  s->BindString(starting_column + 17, data.search_terms_replacement_key);
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  s->BindString(starting_column + 18, data.image_url);
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  s->BindString(starting_column + 19, data.search_url_post_params);
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  s->BindString(starting_column + 20, data.suggestions_url_post_params);
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  s->BindString(starting_column + 21, data.instant_url_post_params);
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  s->BindString(starting_column + 22, data.image_url_post_params);
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  s->BindString(starting_column + 23, data.new_tab_url);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebDatabaseTable::TypeKey GetKey() {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We just need a unique constant. Use the address of a static that
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // COMDAT folding won't touch in an optimizing linker.
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static int table_key = 0;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return reinterpret_cast<void*>(&table_key);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeywordTable::KeywordTable() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)KeywordTable::~KeywordTable() {}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeywordTable* KeywordTable::FromWebDatabase(WebDatabase* db) {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<KeywordTable*>(db->GetTable(GetKey()));
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebDatabaseTable::TypeKey KeywordTable::GetTypeKey() const {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetKey();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool KeywordTable::CreateTablesIfNecessary() {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->DoesTableExist("keywords") ||
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      db_->Execute("CREATE TABLE keywords ("
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "id INTEGER PRIMARY KEY,"
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "short_name VARCHAR NOT NULL,"
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "keyword VARCHAR NOT NULL,"
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "favicon_url VARCHAR NOT NULL,"
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "url VARCHAR NOT NULL,"
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "safe_for_autoreplace INTEGER,"
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "originating_url VARCHAR,"
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "date_created INTEGER DEFAULT 0,"
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "usage_count INTEGER DEFAULT 0,"
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "input_encodings VARCHAR,"
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "show_in_default_list INTEGER,"
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "suggest_url VARCHAR,"
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "prepopulate_id INTEGER DEFAULT 0,"
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "created_by_policy INTEGER DEFAULT 0,"
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "instant_url VARCHAR,"
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "last_modified INTEGER DEFAULT 0,"
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "sync_guid VARCHAR,"
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   "alternate_urls VARCHAR,"
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   "search_terms_replacement_key VARCHAR,"
180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   "image_url VARCHAR,"
181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   "search_url_post_params VARCHAR,"
182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   "suggest_url_post_params VARCHAR,"
183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   "instant_url_post_params VARCHAR,"
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "image_url_post_params VARCHAR,"
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "new_tab_url VARCHAR)");
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::IsSyncable() {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool KeywordTable::MigrateToVersion(int version,
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    bool* update_compatible_version) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Migrate if necessary.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (version) {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 21:
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion21AutoGenerateKeywordColumn();
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 25:
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion25AddLogoIDColumn();
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 26:
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion26AddCreatedByPolicyColumn();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 28:
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion28SupportsInstantColumn();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 29:
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion29InstantURLToSupportsInstant();
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 38:
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion38AddLastModifiedColumn();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 39:
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion39AddSyncGUIDColumn();
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 44:
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion44AddDefaultSearchProviderBackup();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 45:
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion45RemoveLogoIDAndAutogenerateColumns();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 47:
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion47AddAlternateURLsColumn();
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 48:
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion48RemoveKeywordsBackup();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 49:
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *update_compatible_version = true;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return MigrateToVersion49AddSearchTermsReplacementKeyColumn();
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case 52:
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      *update_compatible_version = true;
234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return MigrateToVersion52AddImageSearchAndPOSTSupport();
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case 53:
2363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *update_compatible_version = true;
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return MigrateToVersion53AddNewTabURLColumn();
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
243e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool KeywordTable::PerformOperations(const Operations& operations) {
244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  sql::Transaction transaction(db_);
245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!transaction.Begin())
246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return false;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
248e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (Operations::const_iterator i(operations.begin()); i != operations.end();
249e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       ++i) {
250e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    switch (i->first) {
251e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      case ADD:
252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        if (!AddKeyword(i->second))
253e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          return false;
254e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        break;
255e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
256e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      case REMOVE:
257e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        if (!RemoveKeyword(i->second.id))
258e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          return false;
259e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        break;
260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      case UPDATE:
262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        if (!UpdateKeyword(i->second))
263e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          return false;
264e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        break;
265e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
268e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return transaction.Commit();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::GetKeywords(Keywords* keywords) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query("SELECT " + GetKeywordColumns() +
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    " FROM keywords ORDER BY id ASC");
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(query.c_str()));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<TemplateURLID> bad_entries;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step()) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keywords->push_back(TemplateURLData());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetKeywordDataFromStatement(s, &keywords->back())) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bad_entries.insert(s.ColumnInt64(0));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keywords->pop_back();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool succeeded = s.Succeeded();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::set<TemplateURLID>::const_iterator i(bad_entries.begin());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != bad_entries.end(); ++i)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    succeeded &= RemoveKeyword(*i);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return succeeded;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::SetDefaultSearchProviderID(int64 id) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return meta_table_->SetValue(kDefaultSearchProviderKey, id);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 KeywordTable::GetDefaultSearchProviderID() {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 value = kInvalidTemplateURLID;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  meta_table_->GetValue(kDefaultSearchProviderKey, &value);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::SetBuiltinKeywordVersion(int version) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return meta_table_->SetValue(kBuiltinKeywordVersion, version);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int KeywordTable::GetBuiltinKeywordVersion() {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int version = 0;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string KeywordTable::GetKeywordColumns() {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ColumnsForVersion(WebDatabase::kCurrentVersionNumber, false);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion21AutoGenerateKeywordColumn() {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute("ALTER TABLE keywords ADD COLUMN autogenerate_keyword "
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "INTEGER DEFAULT 0");
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion25AddLogoIDColumn() {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "ALTER TABLE keywords ADD COLUMN logo_id INTEGER DEFAULT 0");
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion26AddCreatedByPolicyColumn() {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute("ALTER TABLE keywords ADD COLUMN created_by_policy "
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "INTEGER DEFAULT 0");
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion28SupportsInstantColumn() {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute("ALTER TABLE keywords ADD COLUMN supports_instant "
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "INTEGER DEFAULT 0");
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion29InstantURLToSupportsInstant() {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transaction.Begin() &&
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url VARCHAR") &&
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_->Execute("CREATE TABLE keywords_temp ("
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "id INTEGER PRIMARY KEY,"
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "short_name VARCHAR NOT NULL,"
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "keyword VARCHAR NOT NULL,"
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "favicon_url VARCHAR NOT NULL,"
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "url VARCHAR NOT NULL,"
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "safe_for_autoreplace INTEGER,"
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "originating_url VARCHAR,"
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "date_created INTEGER DEFAULT 0,"
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "usage_count INTEGER DEFAULT 0,"
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "input_encodings VARCHAR,"
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "show_in_default_list INTEGER,"
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "suggest_url VARCHAR,"
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "prepopulate_id INTEGER DEFAULT 0,"
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "autogenerate_keyword INTEGER DEFAULT 0,"
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "logo_id INTEGER DEFAULT 0,"
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "created_by_policy INTEGER DEFAULT 0,"
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "instant_url VARCHAR)") &&
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_->Execute("INSERT INTO keywords_temp SELECT id, short_name, keyword, "
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "favicon_url, url, safe_for_autoreplace, originating_url, "
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "date_created, usage_count, input_encodings, "
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "show_in_default_list, suggest_url, prepopulate_id, "
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "autogenerate_keyword, logo_id, created_by_policy, "
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "instant_url FROM keywords") &&
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_->Execute("DROP TABLE keywords") &&
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords_temp RENAME TO keywords") &&
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transaction.Commit();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion38AddLastModifiedColumn() {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute(
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "ALTER TABLE keywords ADD COLUMN last_modified INTEGER DEFAULT 0");
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion39AddSyncGUIDColumn() {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute("ALTER TABLE keywords ADD COLUMN sync_guid VARCHAR");
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion44AddDefaultSearchProviderBackup() {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string query("CREATE TABLE keywords_backup AS SELECT " +
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ColumnsForVersion(44, false) + " FROM keywords ORDER BY id ASC");
380e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  sql::Transaction transaction(db_);
381e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return transaction.Begin() &&
382e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      meta_table_->SetValue("Default Search Provider ID Backup",
383e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                            GetDefaultSearchProviderID()) &&
384e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      (!db_->DoesTableExist("keywords_backup") ||
385e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch       db_->Execute("DROP TABLE keywords_backup")) &&
386e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      db_->Execute(query.c_str()) &&
387e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      transaction.Commit();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion45RemoveLogoIDAndAutogenerateColumns() {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!transaction.Begin())
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The version 43 migration should have been written to do this, but since it
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wasn't, we'll do it now.  Unfortunately a previous change deleted this for
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // some users, so we can't be sure this will succeed (so don't bail on error).
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  meta_table_->DeleteKey("Default Search Provider Backup");
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
400e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return MigrateKeywordsTableForVersion45("keywords") &&
401e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      MigrateKeywordsTableForVersion45("keywords_backup") &&
402e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      meta_table_->SetValue("Default Search Provider ID Backup Signature",
403e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                            std::string()) &&
404e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      transaction.Commit();
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateToVersion47AddAlternateURLsColumn() {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Transaction transaction(db_);
409e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return transaction.Begin() &&
410e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      db_->Execute("ALTER TABLE keywords ADD COLUMN "
411e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   "alternate_urls VARCHAR DEFAULT ''") &&
412e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      db_->Execute("ALTER TABLE keywords_backup ADD COLUMN "
413e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   "alternate_urls VARCHAR DEFAULT ''") &&
414e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      meta_table_->SetValue("Default Search Provider ID Backup Signature",
415e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                            std::string()) &&
416e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      transaction.Commit();
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool KeywordTable::MigrateToVersion48RemoveKeywordsBackup() {
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sql::Transaction transaction(db_);
421e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return transaction.Begin() &&
422e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      meta_table_->DeleteKey("Default Search Provider ID Backup") &&
423e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      meta_table_->DeleteKey("Default Search Provider ID Backup Signature") &&
424e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      db_->Execute("DROP TABLE keywords_backup") &&
425e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      transaction.Commit();
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool KeywordTable::MigrateToVersion49AddSearchTermsReplacementKeyColumn() {
429e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return db_->Execute("ALTER TABLE keywords ADD COLUMN "
430e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      "search_terms_replacement_key VARCHAR DEFAULT ''");
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool KeywordTable::MigrateToVersion52AddImageSearchAndPOSTSupport() {
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  sql::Transaction transaction(db_);
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return transaction.Begin() &&
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords ADD COLUMN image_url "
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "VARCHAR DEFAULT ''") &&
438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords ADD COLUMN search_url_post_params "
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "VARCHAR DEFAULT ''") &&
440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords ADD COLUMN suggest_url_post_params "
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "VARCHAR DEFAULT ''") &&
442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url_post_params "
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "VARCHAR DEFAULT ''") &&
444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      db_->Execute("ALTER TABLE keywords ADD COLUMN image_url_post_params "
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   "VARCHAR DEFAULT ''") &&
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      transaction.Commit();
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool KeywordTable::MigrateToVersion53AddNewTabURLColumn() {
450e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return db_->Execute("ALTER TABLE keywords ADD COLUMN new_tab_url "
451e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      "VARCHAR DEFAULT ''");
452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               TemplateURLData* data) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(data);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->short_name = s.ColumnString16(1);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->SetKeyword(s.ColumnString16(2));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Due to past bugs, we might have persisted entries with empty URLs.  Avoid
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reading these out.  (GetKeywords() will delete these entries on return.)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: This code should only be needed as long as we might be reading such
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // potentially-old data and can be removed afterward.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s.ColumnString(4).empty())
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->SetURL(s.ColumnString(4));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->suggestions_url = s.ColumnString(11);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->instant_url = s.ColumnString(14);
470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data->image_url = s.ColumnString(19);
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  data->new_tab_url = s.ColumnString(24);
472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data->search_url_post_params = s.ColumnString(20);
473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data->suggestions_url_post_params = s.ColumnString(21);
474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data->instant_url_post_params = s.ColumnString(22);
475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data->image_url_post_params = s.ColumnString(23);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->favicon_url = GURL(s.ColumnString(3));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->originating_url = GURL(s.ColumnString(6));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->show_in_default_list = s.ColumnBool(10);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->safe_for_autoreplace = s.ColumnBool(5);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(s.ColumnString(9), ';', &data->input_encodings);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->id = s.ColumnInt64(0);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->date_created = Time::FromTimeT(s.ColumnInt64(7));
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->last_modified = Time::FromTimeT(s.ColumnInt64(15));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->created_by_policy = s.ColumnBool(13);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->usage_count = s.ColumnInt(8);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->prepopulate_id = s.ColumnInt(12);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->sync_guid = s.ColumnString(16);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->alternate_urls.clear();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::JSONReader json_reader;
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> value(json_reader.ReadToValue(s.ColumnString(17)));
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue* alternate_urls_value;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value.get() && value->GetAsList(&alternate_urls_value)) {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string alternate_url;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (alternate_urls_value->GetString(i, &alternate_url))
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data->alternate_urls.push_back(alternate_url);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data->search_terms_replacement_key = s.ColumnString(18);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
506e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool KeywordTable::AddKeyword(const TemplateURLData& data) {
507e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(data.id);
508e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::string query("INSERT INTO keywords (" + GetKeywordColumns() + ") "
509e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                    "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,"
510e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                    "        ?)");
511e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE, query.c_str()));
512e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  BindURLToStatement(data, &s, 0, 1);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
514e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return s.Run();
515e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
517e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool KeywordTable::RemoveKeyword(TemplateURLID id) {
518e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(id);
519e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  sql::Statement s(db_->GetCachedStatement(
520e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      SQL_FROM_HERE, "DELETE FROM keywords WHERE id = ?"));
521e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  s.BindInt64(0, id);
522e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
523e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return s.Run();
524e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
525e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
526e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool KeywordTable::UpdateKeyword(const TemplateURLData& data) {
527e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(data.id);
528e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  sql::Statement s(db_->GetCachedStatement(
529e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      SQL_FROM_HERE,
530e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "UPDATE keywords SET short_name=?, keyword=?, favicon_url=?, url=?, "
531e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "safe_for_autoreplace=?, originating_url=?, date_created=?, "
532e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "usage_count=?, input_encodings=?, show_in_default_list=?, "
533e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "suggest_url=?, prepopulate_id=?, created_by_policy=?, instant_url=?, "
534e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "last_modified=?, sync_guid=?, alternate_urls=?, "
535e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "search_terms_replacement_key=?, image_url=?, search_url_post_params=?, "
536e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "suggest_url_post_params=?, instant_url_post_params=?, "
537e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      "image_url_post_params=?, new_tab_url=? WHERE id=?"));
538e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  BindURLToStatement(data, &s, 24, 0);  // "24" binds id() as the last item.
539e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
540e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return s.Run();
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::GetKeywordAsString(TemplateURLID id,
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& table_name,
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string* result) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string query("SELECT " +
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) +
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " FROM " + table_name + " WHERE id=?");
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(query.c_str()));
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindInt64(0, id);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.Step()) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_IF(WARNING, s.Succeeded()) << "No keyword with id: " << id
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   << ", ignoring.";
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.Succeeded())
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = s.ColumnString(0);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool KeywordTable::MigrateKeywordsTableForVersion45(const std::string& name) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a new table without the columns we're dropping.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->Execute("CREATE TABLE keywords_temp ("
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "id INTEGER PRIMARY KEY,"
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "short_name VARCHAR NOT NULL,"
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "keyword VARCHAR NOT NULL,"
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "favicon_url VARCHAR NOT NULL,"
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "url VARCHAR NOT NULL,"
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "safe_for_autoreplace INTEGER,"
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "originating_url VARCHAR,"
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "date_created INTEGER DEFAULT 0,"
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "usage_count INTEGER DEFAULT 0,"
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "input_encodings VARCHAR,"
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "show_in_default_list INTEGER,"
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "suggest_url VARCHAR,"
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "prepopulate_id INTEGER DEFAULT 0,"
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "created_by_policy INTEGER DEFAULT 0,"
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "instant_url VARCHAR,"
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "last_modified INTEGER DEFAULT 0,"
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "sync_guid VARCHAR)"))
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sql("INSERT INTO keywords_temp SELECT " +
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ColumnsForVersion(46, false) + " FROM " + name);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->Execute(sql.c_str()))
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: The ORDER BY here ensures that the uniquing process for keywords will
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // happen identically on both the normal and backup tables.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql = "SELECT id, keyword, url, autogenerate_keyword FROM " + name +
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " ORDER BY id ASC";
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(sql.c_str()));
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::string16 placeholder_keyword(base::ASCIIToUTF16("dummy"));
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<base::string16> keywords;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step()) {
599a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 keyword(s.ColumnString16(1));
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool generate_keyword = keyword.empty() || s.ColumnBool(3);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (generate_keyword)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword = placeholder_keyword;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURLData data;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.SetKeyword(keyword);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.SetURL(s.ColumnString(2));
606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    TemplateURL turl(data);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't persist extension keywords to disk.  These will get added to the
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TemplateURLService as the extensions are loaded.
6091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    bool delete_entry = turl.GetType() == TemplateURL::OMNIBOX_API_EXTENSION;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!delete_entry && generate_keyword) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Explicitly generate keywords for all rows with the autogenerate bit set
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // or where the keyword is empty.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SearchTermsData terms_data;
6146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      GURL url(turl.GenerateSearchURL(terms_data));
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!url.is_valid()) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete_entry = true;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Ensure autogenerated keywords are unique.
6196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        keyword = TemplateURL::GenerateKeyword(url);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (keywords.count(keyword))
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          keyword.append(base::ASCIIToUTF16("_"));
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sql::Statement u(db_->GetUniqueStatement(
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "UPDATE keywords_temp SET keyword=? WHERE id=?"));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        u.BindString16(0, keyword);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        u.BindInt64(1, s.ColumnInt64(0));
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!u.Run())
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delete_entry) {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sql::Statement u(db_->GetUniqueStatement(
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "DELETE FROM keywords_temp WHERE id=?"));
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      u.BindInt64(0, s.ColumnInt64(0));
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!u.Run())
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keywords.insert(keyword);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace the old table with the new one.
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql = "DROP TABLE " + name;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->Execute(sql.c_str()))
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql = "ALTER TABLE keywords_temp RENAME TO " + name;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return db_->Execute(sql.c_str());
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
648