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/history/shortcuts_database.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/guid.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match_type.h"
144ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch#include "sql/meta_table.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "sql/transaction.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/page_transition_types.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Helpers --------------------------------------------------------------------
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch// Current version number. We write databases at the "current" version number,
254ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch// but any previous version that can read the "compatible" one can make do with
264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch// our database without *too* many bad effects.
274ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochconst int kCurrentVersionNumber = 1;
284ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochconst int kCompatibleVersionNumber = 1;
294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BindShortcutToStatement(
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const history::ShortcutsDatabase::Shortcut& shortcut,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sql::Statement* s) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(base::IsValidGUID(shortcut.id));
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString(0, shortcut.id);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s->BindString16(1, shortcut.text);
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindString16(2, shortcut.match_core.fill_into_edit);
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindString(3, shortcut.match_core.destination_url.spec());
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindString16(4, shortcut.match_core.contents);
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  s->BindString(5, shortcut.match_core.contents_class);
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindString16(6, shortcut.match_core.description);
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  s->BindString(7, shortcut.match_core.description_class);
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindInt(8, shortcut.match_core.transition);
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindInt(9, shortcut.match_core.type);
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindString16(10, shortcut.match_core.keyword);
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindInt64(11, shortcut.last_access_time.ToInternalValue());
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s->BindInt(12, shortcut.number_of_hits);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DeleteShortcut(const char* field_name,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& id,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    sql::Connection& db) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db.GetUniqueStatement(
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::StringPrintf("DELETE FROM omni_box_shortcuts WHERE %s = ?",
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         field_name).c_str()));
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindString(0, id);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s.Run();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// ShortcutsDatabase::Shortcut::MatchCore -------------------------------------
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ShortcutsDatabase::Shortcut::MatchCore::MatchCore(
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& fill_into_edit,
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const GURL& destination_url,
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& contents,
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const std::string& contents_class,
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& description,
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const std::string& description_class,
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    int transition,
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    int type,
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& keyword)
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : fill_into_edit(fill_into_edit),
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      destination_url(destination_url),
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      contents(contents),
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      contents_class(contents_class),
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      description(description),
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      description_class(description_class),
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      transition(transition),
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      type(type),
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      keyword(keyword) {
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ShortcutsDatabase::Shortcut::MatchCore::~MatchCore() {
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// ShortcutsDatabase::Shortcut ------------------------------------------------
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ShortcutsDatabase::Shortcut::Shortcut(
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const std::string& id,
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::string16& text,
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const MatchCore& match_core,
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const base::Time& last_access_time,
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    int number_of_hits)
9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : id(id),
9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      text(text),
10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      match_core(match_core),
10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      last_access_time(last_access_time),
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      number_of_hits(number_of_hits) {
10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ShortcutsDatabase::Shortcut::Shortcut()
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : match_core(base::string16(), GURL(), base::string16(), std::string(),
10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 base::string16(), std::string(), 0, 0, base::string16()),
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      last_access_time(base::Time::Now()),
10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      number_of_hits(0) {
11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ShortcutsDatabase::Shortcut::~Shortcut() {
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// ShortcutsDatabase ----------------------------------------------------------
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ShortcutsDatabase::ShortcutsDatabase(const base::FilePath& database_path)
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : database_path_(database_path) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShortcutsDatabase::Init() {
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  db_.set_histogram_tag("Shortcuts");
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the database page size to something a little larger to give us
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // better performance (we're typically seek rather than bandwidth limited).
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This only has an effect before any tables have been created, otherwise
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is a NOP. Must be a power of 2 and a max of 8192.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.set_page_size(4096);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run the database in exclusive mode. Nobody else should be accessing the
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // database while we're running, and this will give somewhat improved perf.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.set_exclusive_locking();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attach the database to our index file.
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return db_.Open(database_path_) && EnsureTable();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsDatabase::AddShortcut(const Shortcut& shortcut) {
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Statement s(db_.GetCachedStatement(
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SQL_FROM_HERE,
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "INSERT INTO omni_box_shortcuts (id, text, fill_into_edit, url, "
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "contents, contents_class, description, description_class, "
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "transition, type, keyword, last_access_time, number_of_hits) "
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BindShortcutToStatement(shortcut, &s);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s.Run();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsDatabase::UpdateShortcut(const Shortcut& shortcut) {
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Statement s(db_.GetCachedStatement(
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SQL_FROM_HERE,
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "UPDATE omni_box_shortcuts SET id=?, text=?, fill_into_edit=?, url=?, "
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "contents=?, contents_class=?, description=?, description_class=?, "
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "transition=?, type=?, keyword=?, last_access_time=?, "
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "number_of_hits=? WHERE id=?"));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BindShortcutToStatement(shortcut, &s);
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  s.BindString(13, shortcut.id);
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return s.Run();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsDatabase::DeleteShortcutsWithIDs(
16323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const ShortcutIDs& shortcut_ids) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = true;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.BeginTransaction();
16623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (ShortcutIDs::const_iterator it(shortcut_ids.begin());
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != shortcut_ids.end(); ++it) {
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    success &= DeleteShortcut("id", *it, db_);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_.CommitTransaction();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ShortcutsDatabase::DeleteShortcutsWithURL(
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& shortcut_url_spec) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DeleteShortcut("url", shortcut_url_spec, db_);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShortcutsDatabase::DeleteAllShortcuts() {
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!db_.Execute("DELETE FROM omni_box_shortcuts"))
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ignore_result(db_.Execute("VACUUM"));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ShortcutsDatabase::LoadShortcuts(GuidToShortcutMap* shortcuts) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(shortcuts);
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sql::Statement s(db_.GetCachedStatement(
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      SQL_FROM_HERE,
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      "SELECT id, text, fill_into_edit, url, contents, contents_class, "
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "description, description_class, transition, type, keyword, "
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "last_access_time, number_of_hits FROM omni_box_shortcuts"));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shortcuts->clear();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step()) {
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    shortcuts->insert(std::make_pair(
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        s.ColumnString(0),
19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        Shortcut(
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            s.ColumnString(0),            // id
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            s.ColumnString16(1),          // text
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)            Shortcut::MatchCore(
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                s.ColumnString16(2),      // fill_into_edit
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                GURL(s.ColumnString(3)),  // destination_url
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                s.ColumnString16(4),      // contents
20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                s.ColumnString(5),        // contents_class
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                s.ColumnString16(6),      // description
20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                s.ColumnString(7),        // description_class
20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                s.ColumnInt(8),           // transition
21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                s.ColumnInt(9),           // type
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                s.ColumnString16(10)),    // keyword
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            base::Time::FromInternalValue(s.ColumnInt64(11)),
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          // last_access_time
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            s.ColumnInt(12))));           // number_of_hits
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ShortcutsDatabase::~ShortcutsDatabase() {
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShortcutsDatabase::EnsureTable() {
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!db_.DoesTableExist("omni_box_shortcuts")) {
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return db_.Execute(
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        "CREATE TABLE omni_box_shortcuts (id VARCHAR PRIMARY KEY, "
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "text VARCHAR, fill_into_edit VARCHAR, url VARCHAR, "
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "contents VARCHAR, contents_class VARCHAR, description VARCHAR, "
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "description_class VARCHAR, transition INTEGER, type INTEGER, "
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "keyword VARCHAR, last_access_time INTEGER, "
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "number_of_hits INTEGER)");
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The first version of the shortcuts table lacked the fill_into_edit,
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // transition, type, and keyword columns.
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!db_.DoesColumnExist("omni_box_shortcuts", "fill_into_edit")) {
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Perform the upgrade in a transaction to ensure it doesn't happen
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // incompletely.
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    sql::Transaction transaction(&db_);
2384ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (!(transaction.Begin() &&
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute("ALTER TABLE omni_box_shortcuts "
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "ADD COLUMN fill_into_edit VARCHAR") &&
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute("UPDATE omni_box_shortcuts SET fill_into_edit = url") &&
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute("ALTER TABLE omni_box_shortcuts "
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "ADD COLUMN transition INTEGER") &&
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute(base::StringPrintf(
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "UPDATE omni_box_shortcuts SET transition = %d",
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            static_cast<int>(ui::PAGE_TRANSITION_TYPED)).c_str()) &&
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute("ALTER TABLE omni_box_shortcuts ADD COLUMN type INTEGER") &&
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute(base::StringPrintf(
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "UPDATE omni_box_shortcuts SET type = %d",
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            static_cast<int>(AutocompleteMatchType::HISTORY_TITLE)).c_str()) &&
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        db_.Execute("ALTER TABLE omni_box_shortcuts "
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            "ADD COLUMN keyword VARCHAR") &&
2534ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch        transaction.Commit())) {
2544ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return false;
2554ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2584ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  if (!sql::MetaTable::DoesTableExist(&db_)) {
2594ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber);
2604ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    sql::Transaction transaction(&db_);
2614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    if (!(transaction.Begin() &&
2624ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      // Migrate old SEARCH_OTHER_ENGINE values to the new type value.
2634ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
2644ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch          "SET type = 13 WHERE type = 9").c_str()) &&
2654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      // Migrate old EXTENSION_APP values to the new type value.
2664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
2674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch           "SET type = 14 WHERE type = 10").c_str()) &&
2684ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      // Migrate old CONTACT values to the new type value.
2694ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
2704ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch           "SET type = 15 WHERE type = 11").c_str()) &&
2714ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      // Migrate old BOOKMARK_TITLE values to the new type value.
2724ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
2734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch           "SET type = 16 WHERE type = 12").c_str()) &&
2744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      transaction.Commit())) {
2754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch      return false;
2764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    }
2774ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace history
282