Roll src/third_party/skia 5a9e299:00b621c
[chromium-blink-merge.git] / chrome / browser / autocomplete / shortcuts_database.cc
blob94bbe89153dda82acb2c049eeb4456a25885ace2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/autocomplete/shortcuts_database.h"
7 #include <string>
9 #include "base/guid.h"
10 #include "base/logging.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h"
13 #include "components/omnibox/autocomplete_match_type.h"
14 #include "sql/meta_table.h"
15 #include "sql/statement.h"
16 #include "sql/transaction.h"
17 #include "ui/base/page_transition_types.h"
20 // Helpers --------------------------------------------------------------------
22 namespace {
24 // Current version number. We write databases at the "current" version number,
25 // but any previous version that can read the "compatible" one can make do with
26 // our database without *too* many bad effects.
27 const int kCurrentVersionNumber = 1;
28 const int kCompatibleVersionNumber = 1;
30 void BindShortcutToStatement(const ShortcutsDatabase::Shortcut& shortcut,
31 sql::Statement* s) {
32 DCHECK(base::IsValidGUID(shortcut.id));
33 s->BindString(0, shortcut.id);
34 s->BindString16(1, shortcut.text);
35 s->BindString16(2, shortcut.match_core.fill_into_edit);
36 s->BindString(3, shortcut.match_core.destination_url.spec());
37 s->BindString16(4, shortcut.match_core.contents);
38 s->BindString(5, shortcut.match_core.contents_class);
39 s->BindString16(6, shortcut.match_core.description);
40 s->BindString(7, shortcut.match_core.description_class);
41 s->BindInt(8, shortcut.match_core.transition);
42 s->BindInt(9, shortcut.match_core.type);
43 s->BindString16(10, shortcut.match_core.keyword);
44 s->BindInt64(11, shortcut.last_access_time.ToInternalValue());
45 s->BindInt(12, shortcut.number_of_hits);
48 bool DeleteShortcut(const char* field_name,
49 const std::string& id,
50 sql::Connection& db) {
51 sql::Statement s(db.GetUniqueStatement(
52 base::StringPrintf("DELETE FROM omni_box_shortcuts WHERE %s = ?",
53 field_name).c_str()));
54 s.BindString(0, id);
55 return s.Run();
58 } // namespace
60 // ShortcutsDatabase::Shortcut::MatchCore -------------------------------------
62 ShortcutsDatabase::Shortcut::MatchCore::MatchCore(
63 const base::string16& fill_into_edit,
64 const GURL& destination_url,
65 const base::string16& contents,
66 const std::string& contents_class,
67 const base::string16& description,
68 const std::string& description_class,
69 int transition,
70 int type,
71 const base::string16& keyword)
72 : fill_into_edit(fill_into_edit),
73 destination_url(destination_url),
74 contents(contents),
75 contents_class(contents_class),
76 description(description),
77 description_class(description_class),
78 transition(transition),
79 type(type),
80 keyword(keyword) {
83 ShortcutsDatabase::Shortcut::MatchCore::~MatchCore() {
86 // ShortcutsDatabase::Shortcut ------------------------------------------------
88 ShortcutsDatabase::Shortcut::Shortcut(
89 const std::string& id,
90 const base::string16& text,
91 const MatchCore& match_core,
92 const base::Time& last_access_time,
93 int number_of_hits)
94 : id(id),
95 text(text),
96 match_core(match_core),
97 last_access_time(last_access_time),
98 number_of_hits(number_of_hits) {
101 ShortcutsDatabase::Shortcut::Shortcut()
102 : match_core(base::string16(), GURL(), base::string16(), std::string(),
103 base::string16(), std::string(), 0, 0, base::string16()),
104 last_access_time(base::Time::Now()),
105 number_of_hits(0) {
108 ShortcutsDatabase::Shortcut::~Shortcut() {
112 // ShortcutsDatabase ----------------------------------------------------------
114 ShortcutsDatabase::ShortcutsDatabase(const base::FilePath& database_path)
115 : database_path_(database_path) {
118 bool ShortcutsDatabase::Init() {
119 db_.set_histogram_tag("Shortcuts");
121 // Set the database page size to something a little larger to give us
122 // better performance (we're typically seek rather than bandwidth limited).
123 // This only has an effect before any tables have been created, otherwise
124 // this is a NOP. Must be a power of 2 and a max of 8192.
125 db_.set_page_size(4096);
127 // Run the database in exclusive mode. Nobody else should be accessing the
128 // database while we're running, and this will give somewhat improved perf.
129 db_.set_exclusive_locking();
131 // Attach the database to our index file.
132 return db_.Open(database_path_) && EnsureTable();
135 bool ShortcutsDatabase::AddShortcut(const Shortcut& shortcut) {
136 sql::Statement s(db_.GetCachedStatement(
137 SQL_FROM_HERE,
138 "INSERT INTO omni_box_shortcuts (id, text, fill_into_edit, url, "
139 "contents, contents_class, description, description_class, "
140 "transition, type, keyword, last_access_time, number_of_hits) "
141 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
142 BindShortcutToStatement(shortcut, &s);
143 return s.Run();
146 bool ShortcutsDatabase::UpdateShortcut(const Shortcut& shortcut) {
147 sql::Statement s(db_.GetCachedStatement(
148 SQL_FROM_HERE,
149 "UPDATE omni_box_shortcuts SET id=?, text=?, fill_into_edit=?, url=?, "
150 "contents=?, contents_class=?, description=?, description_class=?, "
151 "transition=?, type=?, keyword=?, last_access_time=?, "
152 "number_of_hits=? WHERE id=?"));
153 BindShortcutToStatement(shortcut, &s);
154 s.BindString(13, shortcut.id);
155 return s.Run();
158 bool ShortcutsDatabase::DeleteShortcutsWithIDs(
159 const ShortcutIDs& shortcut_ids) {
160 bool success = true;
161 db_.BeginTransaction();
162 for (ShortcutIDs::const_iterator it(shortcut_ids.begin());
163 it != shortcut_ids.end(); ++it) {
164 success &= DeleteShortcut("id", *it, db_);
166 db_.CommitTransaction();
167 return success;
170 bool ShortcutsDatabase::DeleteShortcutsWithURL(
171 const std::string& shortcut_url_spec) {
172 return DeleteShortcut("url", shortcut_url_spec, db_);
175 bool ShortcutsDatabase::DeleteAllShortcuts() {
176 if (!db_.Execute("DELETE FROM omni_box_shortcuts"))
177 return false;
179 ignore_result(db_.Execute("VACUUM"));
180 return true;
183 void ShortcutsDatabase::LoadShortcuts(GuidToShortcutMap* shortcuts) {
184 DCHECK(shortcuts);
185 sql::Statement s(db_.GetCachedStatement(
186 SQL_FROM_HERE,
187 "SELECT id, text, fill_into_edit, url, contents, contents_class, "
188 "description, description_class, transition, type, keyword, "
189 "last_access_time, number_of_hits FROM omni_box_shortcuts"));
191 shortcuts->clear();
192 while (s.Step()) {
193 shortcuts->insert(std::make_pair(
194 s.ColumnString(0),
195 Shortcut(
196 s.ColumnString(0), // id
197 s.ColumnString16(1), // text
198 Shortcut::MatchCore(
199 s.ColumnString16(2), // fill_into_edit
200 GURL(s.ColumnString(3)), // destination_url
201 s.ColumnString16(4), // contents
202 s.ColumnString(5), // contents_class
203 s.ColumnString16(6), // description
204 s.ColumnString(7), // description_class
205 s.ColumnInt(8), // transition
206 s.ColumnInt(9), // type
207 s.ColumnString16(10)), // keyword
208 base::Time::FromInternalValue(s.ColumnInt64(11)),
209 // last_access_time
210 s.ColumnInt(12)))); // number_of_hits
214 ShortcutsDatabase::~ShortcutsDatabase() {
217 bool ShortcutsDatabase::EnsureTable() {
218 if (!db_.DoesTableExist("omni_box_shortcuts")) {
219 return db_.Execute(
220 "CREATE TABLE omni_box_shortcuts (id VARCHAR PRIMARY KEY, "
221 "text VARCHAR, fill_into_edit VARCHAR, url VARCHAR, "
222 "contents VARCHAR, contents_class VARCHAR, description VARCHAR, "
223 "description_class VARCHAR, transition INTEGER, type INTEGER, "
224 "keyword VARCHAR, last_access_time INTEGER, "
225 "number_of_hits INTEGER)");
228 // The first version of the shortcuts table lacked the fill_into_edit,
229 // transition, type, and keyword columns.
230 if (!db_.DoesColumnExist("omni_box_shortcuts", "fill_into_edit")) {
231 // Perform the upgrade in a transaction to ensure it doesn't happen
232 // incompletely.
233 sql::Transaction transaction(&db_);
234 if (!(transaction.Begin() &&
235 db_.Execute("ALTER TABLE omni_box_shortcuts "
236 "ADD COLUMN fill_into_edit VARCHAR") &&
237 db_.Execute("UPDATE omni_box_shortcuts SET fill_into_edit = url") &&
238 db_.Execute("ALTER TABLE omni_box_shortcuts "
239 "ADD COLUMN transition INTEGER") &&
240 db_.Execute(base::StringPrintf(
241 "UPDATE omni_box_shortcuts SET transition = %d",
242 static_cast<int>(ui::PAGE_TRANSITION_TYPED)).c_str()) &&
243 db_.Execute("ALTER TABLE omni_box_shortcuts ADD COLUMN type INTEGER") &&
244 db_.Execute(base::StringPrintf(
245 "UPDATE omni_box_shortcuts SET type = %d",
246 static_cast<int>(AutocompleteMatchType::HISTORY_TITLE)).c_str()) &&
247 db_.Execute("ALTER TABLE omni_box_shortcuts "
248 "ADD COLUMN keyword VARCHAR") &&
249 transaction.Commit())) {
250 return false;
254 if (!sql::MetaTable::DoesTableExist(&db_)) {
255 meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber);
256 sql::Transaction transaction(&db_);
257 if (!(transaction.Begin() &&
258 // Migrate old SEARCH_OTHER_ENGINE values to the new type value.
259 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
260 "SET type = 13 WHERE type = 9").c_str()) &&
261 // Migrate old EXTENSION_APP values to the new type value.
262 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
263 "SET type = 14 WHERE type = 10").c_str()) &&
264 // Migrate old CONTACT values to the new type value.
265 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
266 "SET type = 15 WHERE type = 11").c_str()) &&
267 // Migrate old BOOKMARK_TITLE values to the new type value.
268 db_.Execute(base::StringPrintf("UPDATE omni_box_shortcuts "
269 "SET type = 16 WHERE type = 12").c_str()) &&
270 transaction.Commit())) {
271 return false;
274 return true;