thumbnail_database.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/thumbnail_database.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <algorithm>
872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <string>
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/sql/statement.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/sql/transaction.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/ref_counted_memory.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/diagnostics/sqlite_diagnostics.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_publisher.h"
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/history/top_sites.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/url_database.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/thumbnail_score.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/codec/jpeg_codec.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_MACOSX)
273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/mac/mac_util.h"
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace history {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Version number of the database.
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kCurrentVersionNumber = 3;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kCompatibleVersionNumber = 3;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochThumbnailDatabase::ThumbnailDatabase() : history_publisher_(NULL),
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         use_top_sites_(false) {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochThumbnailDatabase::~ThumbnailDatabase() {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The DBCloseScoper will delete the DB and the cache.
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::InitStatus ThumbnailDatabase::Init(
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& db_name,
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const HistoryPublisher* history_publisher) {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history_publisher_ = history_publisher;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::InitStatus status = OpenDatabase(&db_, db_name);
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (status != sql::INIT_OK)
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return status;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Scope initialization in a transaction so we can't be partially initialized.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Transaction transaction(&db_);
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  transaction.Begin();
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Exclude the thumbnails file and its journal from backups.
583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::mac::SetFileBackupExclusion(db_name, true);
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath::StringType db_name_string(db_name.value());
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_name_string += "-journal";
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath db_journal_name(db_name_string);
623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::mac::SetFileBackupExclusion(db_journal_name, true);
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create the tables.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!meta_table_.Init(&db_, kCurrentVersionNumber,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        kCompatibleVersionNumber) ||
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !InitThumbnailTable() ||
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !InitFavIconsTable(&db_, false)) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    db_.Close();
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_FAILURE;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitFavIconsIndex();
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Version check. We should not encounter a database too old for us to handle
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in the wild, so we try to continue in that case.
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(WARNING) << "Thumbnail database is too new.";
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_TOO_NEW;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int cur_version = meta_table_.GetVersionNumber();
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cur_version == 2) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!UpgradeToVersion3()) {
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(WARNING) << "Unable to update to thumbnail database to version 3.";
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      db_.Close();
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return sql::INIT_FAILURE;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ++cur_version;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Thumbnail database version " << cur_version << " is too old to handle.";
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initialization is complete.
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!transaction.Commit()) {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    db_.Close();
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_FAILURE;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sql::INIT_OK;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::InitStatus ThumbnailDatabase::OpenDatabase(sql::Connection* db,
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                const FilePath& db_name) {
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the exceptional sqlite error handler.
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->set_error_delegate(GetErrorHandlerForThumbnailDb());
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Thumbnails db now only stores favicons, so we don't need that big a page
110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // size or cache.
111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  db->set_page_size(2048);
112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  db->set_cache_size(32);
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Run the database in exclusive mode. Nobody else should be accessing the
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // database while we're running, and this will give somewhat improved perf.
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->set_exclusive_locking();
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db->Open(db_name))
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_FAILURE;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sql::INIT_OK;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::InitThumbnailTable() {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.DoesTableExist("thumbnails")) {
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    use_top_sites_ = true;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::UpgradeToVersion3() {
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_top_sites_) {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    meta_table_.SetVersionNumber(3);
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    meta_table_.SetCompatibleVersionNumber(
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::min(3, kCompatibleVersionNumber));
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;  // Not needed after migration to TopSites.
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // sqlite doesn't like the "ALTER TABLE xxx ADD (column_one, two,
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // three)" syntax, so list out the commands we need to execute:
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* alterations[] = {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD boring_score DOUBLE DEFAULT 1.0",
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD good_clipping INTEGER DEFAULT 0",
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD at_top INTEGER DEFAULT 0",
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD last_updated INTEGER DEFAULT 0",
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; alterations[i] != NULL; ++i) {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!db_.Execute(alterations[i])) {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  meta_table_.SetVersionNumber(3);
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  meta_table_.SetCompatibleVersionNumber(std::min(3, kCompatibleVersionNumber));
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::RecreateThumbnailTable() {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_top_sites_)
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;  // Not needed after migration to TopSites.
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("DROP TABLE thumbnails"))
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return InitThumbnailTable();
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::InitFavIconsTable(sql::Connection* db,
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          bool is_temporary) {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note: if you update the schema, don't forget to update
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // CopyToTemporaryFaviconTable as well.
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* name = is_temporary ? "temp_favicons" : "favicons";
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db->DoesTableExist(name)) {
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string sql;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql.append("CREATE TABLE ");
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql.append(name);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql.append("("
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "id INTEGER PRIMARY KEY,"
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "url LONGVARCHAR NOT NULL,"
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "last_updated INTEGER DEFAULT 0,"
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "image_data BLOB)");
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!db->Execute(sql.c_str()))
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::InitFavIconsIndex() {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add an index on the url column. We ignore errors. Since this is always
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // called during startup, the index will normally already exist.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.Execute("CREATE INDEX favicons_url ON favicons(url)");
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::BeginTransaction() {
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.BeginTransaction();
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::CommitTransaction() {
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.CommitTransaction();
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::Vacuum() {
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(db_.transaction_nesting() == 0) <<
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Can not have a transaction when vacuuming.";
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.Execute("VACUUM");
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::SetPageThumbnail(
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url,
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    URLID id,
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const SkBitmap& thumbnail,
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ThumbnailScore& score,
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Time time) {
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Use TopSites instead.";
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;  // Not possible after migration to TopSites.
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!thumbnail.isNull()) {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool add_thumbnail = true;
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ThumbnailScore current_score;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ThumbnailScoreForId(id, &current_score)) {
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      add_thumbnail = ShouldReplaceThumbnailWith(current_score, score);
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (add_thumbnail) {
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "INSERT OR REPLACE INTO thumbnails "
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "(url_id, boring_score, good_clipping, at_top, last_updated, data) "
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "VALUES (?,?,?,?,?,?)"));
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!statement)
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We use 90 quality (out of 100) which is pretty high, because
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // we're very sensitive to artifacts for these small sized,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // highly detailed images.
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<unsigned char> jpeg_data;
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkAutoLockPixels thumbnail_lock(thumbnail);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool encoded = gfx::JPEGCodec::Encode(
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          reinterpret_cast<unsigned char*>(thumbnail.getAddr32(0, 0)),
243731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          gfx::JPEGCodec::FORMAT_SkBitmap, thumbnail.width(),
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          thumbnail.height(),
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          static_cast<int>(thumbnail.rowBytes()), 90,
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &jpeg_data);
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (encoded) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindInt64(0, id);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindDouble(1, score.boring_score);
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindBool(2, score.good_clipping);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindBool(3, score.at_top);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindInt64(4, score.time_at_snapshot.ToTimeT());
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindBlob(5, &jpeg_data[0],
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           static_cast<int>(jpeg_data.size()));
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!statement.Run())
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NOTREACHED() << db_.GetErrorMessage();
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Publish the thumbnail to any indexers listening to us.
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The tests may send an invalid url. Hence avoid publishing those.
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (url.is_valid() && history_publisher_ != NULL)
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        history_publisher_->PublishPageThumbnail(jpeg_data, url, time);
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!DeleteThumbnail(id) )
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DLOG(WARNING) << "Unable to delete thumbnail";
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::GetPageThumbnail(URLID id,
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         std::vector<unsigned char>* data) {
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Use TopSites instead.";
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Not possible after migration to TopSites.
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT data FROM thumbnails WHERE url_id=?"));
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, id);
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Step())
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // don't have a thumbnail for this ID
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.ColumnBlobAsVector(0, data);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::DeleteThumbnail(URLID id) {
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;  // Not possible after migration to TopSites.
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "DELETE FROM thumbnails WHERE url_id = ?"));
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, id);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.Run();
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::ThumbnailScoreForId(URLID id,
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            ThumbnailScore* score) {
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Use TopSites instead.";
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Not possible after migration to TopSites.
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fetch the current thumbnail's information to make sure we
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // aren't replacing a good thumbnail with one that's worse.
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement select_statement(db_.GetCachedStatement(SQL_FROM_HERE,
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT boring_score, good_clipping, at_top, last_updated "
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "FROM thumbnails WHERE url_id=?"));
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!select_statement) {
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Couldn't build select statement!";
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    select_statement.BindInt64(0, id);
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (select_statement.Step()) {
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      double current_boring_score = select_statement.ColumnDouble(0);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool current_clipping = select_statement.ColumnBool(1);
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool current_at_top = select_statement.ColumnBool(2);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::Time last_updated =
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          base::Time::FromTimeT(select_statement.ColumnInt64(3));
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *score = ThumbnailScore(current_boring_score, current_clipping,
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              current_at_top, last_updated);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::SetFavIcon(URLID icon_id,
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   scoped_refptr<RefCountedMemory> icon_data,
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   base::Time time) {
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(icon_id);
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (icon_data->size()) {
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "UPDATE favicons SET image_data=?, last_updated=? WHERE id=?"));
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!statement)
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 0;
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindBlob(0, icon_data->front(),
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       static_cast<int>(icon_data->size()));
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(1, time.ToTimeT());
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(2, icon_id);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return statement.Run();
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "UPDATE favicons SET image_data=NULL, last_updated=? WHERE id=?"));
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!statement)
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 0;
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(0, time.ToTimeT());
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(1, icon_id);
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return statement.Run();
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::SetFavIconLastUpdateTime(FavIconID icon_id,
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 base::Time time) {
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "UPDATE favicons SET last_updated=? WHERE id=?"));
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, time.ToTimeT());
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(1, icon_id);
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.Run();
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFavIconID ThumbnailDatabase::GetFavIconIDForFavIconURL(const GURL& icon_url) {
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT id FROM favicons WHERE url=?"));
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url));
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Step())
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;  // not cached
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.ColumnInt64(0);
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::GetFavIcon(
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FavIconID icon_id,
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Time* last_updated,
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<unsigned char>* png_icon_data,
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL* icon_url) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(icon_id);
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT last_updated, image_data, url FROM favicons WHERE id=?"));
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, icon_id);
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Step())
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // No entry for the id.
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *last_updated = base::Time::FromTimeT(statement.ColumnInt64(0));
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (statement.ColumnByteLength(1) > 0)
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.ColumnBlobAsVector(1, png_icon_data);
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (icon_url)
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *icon_url = GURL(statement.ColumnString(2));
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFavIconID ThumbnailDatabase::AddFavIcon(const GURL& icon_url) {
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "INSERT INTO favicons (url) VALUES (?)"));
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url));
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Run())
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return db_.GetLastInsertRowId();
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::DeleteFavIcon(FavIconID id) {
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "DELETE FROM favicons WHERE id = ?"));
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, id);
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.Run();
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFavIconID ThumbnailDatabase::CopyToTemporaryFavIconTable(FavIconID source) {
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "INSERT INTO temp_favicons (url, last_updated, image_data)"
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT url, last_updated, image_data "
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "FROM favicons WHERE id = ?"));
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, source);
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Run())
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We return the ID of the newly inserted favicon.
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return db_.GetLastInsertRowId();
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::CommitTemporaryFavIconTable() {
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Delete the old favicons table.
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("DROP TABLE favicons"))
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Rename the temporary one.
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons"))
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The renamed table needs the index (the temporary table doesn't have one).
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitFavIconsIndex();
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::NeedsMigrationToTopSites() {
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return !use_top_sites_;
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file,
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                const FilePath& new_db_file) {
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Init favicons table - same schema as the thumbnails.
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Connection favicons;
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (OpenDatabase(&favicons, new_db_file) != sql::INIT_OK)
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!InitFavIconsTable(&favicons, false)) {
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Couldn't init favicons table.";
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    favicons.Close();
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  favicons.Close();
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Can't attach within a transaction.
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (transaction_nesting())
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CommitTransaction();
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Attach new DB.
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This block is needed because otherwise the attach statement is
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // never cleared from cache and we can't close the DB :P
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql::Statement attach(db_.GetUniqueStatement("ATTACH ? AS new_favicons"));
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!attach) {
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Unable to attach database.";
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Keep the transaction open, even though we failed.
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BeginTransaction();
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    attach.BindString(0, new_db_file.value());
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    attach.BindString(0, WideToUTF8(new_db_file.value()));
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!attach.Run()) {
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << db_.GetErrorMessage();
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BeginTransaction();
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Move favicons to the new DB.
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("INSERT OR REPLACE INTO new_favicons.favicons "
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   "SELECT * FROM favicons")) {
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Unable to copy favicons.";
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BeginTransaction();
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("DETACH new_favicons")) {
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Unable to detach database.";
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BeginTransaction();
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.Close();
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reset the DB to point to new file.
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (OpenDatabase(&db_, new_db_file) != sql::INIT_OK)
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  file_util::Delete(old_db_file, false);
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitFavIconsIndex();
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reopen the transaction.
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BeginTransaction();
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  use_top_sites_ = true;
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace history
542