1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/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
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic void FillIconMapping(const sql::Statement& statement,
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            const GURL& page_url,
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            history::IconMapping* icon_mapping) {
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  icon_mapping->mapping_id = statement.ColumnInt64(0);
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  icon_mapping->icon_id = statement.ColumnInt64(1);
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  icon_mapping->icon_type =
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      static_cast<history::IconType>(statement.ColumnInt(2));
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  icon_mapping->page_url = page_url;
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace history {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Version number of the database.
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kCurrentVersionNumber = 4;
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kCompatibleVersionNumber = 4;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenThumbnailDatabase::ThumbnailDatabase()
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : history_publisher_(NULL),
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      use_top_sites_(false) {
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochThumbnailDatabase::~ThumbnailDatabase() {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The DBCloseScoper will delete the DB and the cache.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::InitStatus ThumbnailDatabase::Init(
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& db_name,
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const HistoryPublisher* history_publisher,
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    URLDatabase* url_db) {
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history_publisher_ = history_publisher;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::InitStatus status = OpenDatabase(&db_, db_name);
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (status != sql::INIT_OK)
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return status;
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Scope initialization in a transaction so we can't be partially initialized.
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Transaction transaction(&db_);
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  transaction.Begin();
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Exclude the thumbnails file and its journal from backups.
703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::mac::SetFileBackupExclusion(db_name, true);
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath::StringType db_name_string(db_name.value());
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_name_string += "-journal";
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath db_journal_name(db_name_string);
743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::mac::SetFileBackupExclusion(db_journal_name, true);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create the tables.
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!meta_table_.Init(&db_, kCurrentVersionNumber,
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        kCompatibleVersionNumber) ||
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !InitThumbnailTable() ||
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !InitFaviconsTable(&db_, false) ||
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !InitIconMappingTable(&db_, false)) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    db_.Close();
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_FAILURE;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  InitFaviconsIndex();
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  InitIconMappingIndex();
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Version check. We should not encounter a database too old for us to handle
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // in the wild, so we try to continue in that case.
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(WARNING) << "Thumbnail database is too new.";
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_TOO_NEW;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int cur_version = meta_table_.GetVersionNumber();
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cur_version == 2) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!UpgradeToVersion3()) {
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(WARNING) << "Unable to update to thumbnail database to version 3.";
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      db_.Close();
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return sql::INIT_FAILURE;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ++cur_version;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (cur_version == 3) {
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!UpgradeToVersion4() || !MigrateIconMappingData(url_db)) {
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      LOG(WARNING) << "Unable to update to thumbnail database to version 4.";
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      db_.Close();
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return sql::INIT_FAILURE;
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ++cur_version;
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Thumbnail database version " << cur_version << " is too old to handle.";
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initialization is complete.
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!transaction.Commit()) {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    db_.Close();
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_FAILURE;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sql::INIT_OK;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsql::InitStatus ThumbnailDatabase::OpenDatabase(sql::Connection* db,
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                const FilePath& db_name) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the exceptional sqlite error handler.
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->set_error_delegate(GetErrorHandlerForThumbnailDb());
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Thumbnails db now only stores favicons, so we don't need that big a page
133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // size or cache.
134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  db->set_page_size(2048);
135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  db->set_cache_size(32);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Run the database in exclusive mode. Nobody else should be accessing the
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // database while we're running, and this will give somewhat improved perf.
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db->set_exclusive_locking();
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db->Open(db_name))
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sql::INIT_FAILURE;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sql::INIT_OK;
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::InitThumbnailTable() {
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.DoesTableExist("thumbnails")) {
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    use_top_sites_ = true;
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::UpgradeToVersion3() {
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_top_sites_) {
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    meta_table_.SetVersionNumber(3);
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    meta_table_.SetCompatibleVersionNumber(
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::min(3, kCompatibleVersionNumber));
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;  // Not needed after migration to TopSites.
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // sqlite doesn't like the "ALTER TABLE xxx ADD (column_one, two,
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // three)" syntax, so list out the commands we need to execute:
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* alterations[] = {
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD boring_score DOUBLE DEFAULT 1.0",
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD good_clipping INTEGER DEFAULT 0",
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD at_top INTEGER DEFAULT 0",
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "ALTER TABLE thumbnails ADD last_updated INTEGER DEFAULT 0",
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; alterations[i] != NULL; ++i) {
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!db_.Execute(alterations[i])) {
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  meta_table_.SetVersionNumber(3);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  meta_table_.SetCompatibleVersionNumber(std::min(3, kCompatibleVersionNumber));
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::RecreateThumbnailTable() {
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (use_top_sites_)
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;  // Not needed after migration to TopSites.
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("DROP TABLE thumbnails"))
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return InitThumbnailTable();
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::InitFaviconsTable(sql::Connection* db,
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          bool is_temporary) {
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note: if you update the schema, don't forget to update
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // CopyToTemporaryFaviconTable as well.
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* name = is_temporary ? "temp_favicons" : "favicons";
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db->DoesTableExist(name)) {
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string sql;
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql.append("CREATE TABLE ");
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql.append(name);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql.append("("
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "id INTEGER PRIMARY KEY,"
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "url LONGVARCHAR NOT NULL,"
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               "last_updated INTEGER DEFAULT 0,"
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               "image_data BLOB,"
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               "icon_type INTEGER DEFAULT 1)"); // Set the default as FAVICON
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                // to be consistent with table
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                // upgrade in
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                // UpgradeToVersion4().
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!db->Execute(sql.c_str()))
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ThumbnailDatabase::InitFaviconsIndex() {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Add an index on the url column. We ignore errors. Since this is always
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // called during startup, the index will normally already exist.
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.Execute("CREATE INDEX favicons_url ON favicons(url)");
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::BeginTransaction() {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.BeginTransaction();
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::CommitTransaction() {
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.CommitTransaction();
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::Vacuum() {
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(db_.transaction_nesting() == 0) <<
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Can not have a transaction when vacuuming.";
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.Execute("VACUUM");
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ThumbnailDatabase::SetPageThumbnail(
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& url,
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    URLID id,
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const SkBitmap& thumbnail,
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const ThumbnailScore& score,
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Time time) {
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Use TopSites instead.";
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;  // Not possible after migration to TopSites.
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!thumbnail.isNull()) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool add_thumbnail = true;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ThumbnailScore current_score;
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ThumbnailScoreForId(id, &current_score)) {
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      add_thumbnail = ShouldReplaceThumbnailWith(current_score, score);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (add_thumbnail) {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "INSERT OR REPLACE INTO thumbnails "
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "(url_id, boring_score, good_clipping, at_top, last_updated, data) "
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          "VALUES (?,?,?,?,?,?)"));
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!statement)
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We use 90 quality (out of 100) which is pretty high, because
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // we're very sensitive to artifacts for these small sized,
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // highly detailed images.
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<unsigned char> jpeg_data;
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SkAutoLockPixels thumbnail_lock(thumbnail);
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool encoded = gfx::JPEGCodec::Encode(
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          reinterpret_cast<unsigned char*>(thumbnail.getAddr32(0, 0)),
270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          gfx::JPEGCodec::FORMAT_SkBitmap, thumbnail.width(),
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          thumbnail.height(),
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          static_cast<int>(thumbnail.rowBytes()), 90,
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &jpeg_data);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (encoded) {
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindInt64(0, id);
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindDouble(1, score.boring_score);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindBool(2, score.good_clipping);
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindBool(3, score.at_top);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindInt64(4, score.time_at_snapshot.ToTimeT());
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        statement.BindBlob(5, &jpeg_data[0],
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           static_cast<int>(jpeg_data.size()));
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!statement.Run())
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NOTREACHED() << db_.GetErrorMessage();
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Publish the thumbnail to any indexers listening to us.
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The tests may send an invalid url. Hence avoid publishing those.
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (url.is_valid() && history_publisher_ != NULL)
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        history_publisher_->PublishPageThumbnail(jpeg_data, url, time);
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!DeleteThumbnail(id) )
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DLOG(WARNING) << "Unable to delete thumbnail";
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::GetPageThumbnail(URLID id,
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         std::vector<unsigned char>* data) {
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Use TopSites instead.";
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Not possible after migration to TopSites.
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT data FROM thumbnails WHERE url_id=?"));
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, id);
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Step())
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // don't have a thumbnail for this ID
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.ColumnBlobAsVector(0, data);
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::DeleteThumbnail(URLID id) {
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;  // Not possible after migration to TopSites.
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "DELETE FROM thumbnails WHERE url_id = ?"));
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, id);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.Run();
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::ThumbnailScoreForId(URLID id,
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            ThumbnailScore* score) {
3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (use_top_sites_) {
3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Use TopSites instead.";
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Not possible after migration to TopSites.
3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fetch the current thumbnail's information to make sure we
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // aren't replacing a good thumbnail with one that's worse.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement select_statement(db_.GetCachedStatement(SQL_FROM_HERE,
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT boring_score, good_clipping, at_top, last_updated "
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "FROM thumbnails WHERE url_id=?"));
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!select_statement) {
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Couldn't build select statement!";
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    select_statement.BindInt64(0, id);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (select_statement.Step()) {
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      double current_boring_score = select_statement.ColumnDouble(0);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool current_clipping = select_statement.ColumnBool(1);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool current_at_top = select_statement.ColumnBool(2);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::Time last_updated =
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          base::Time::FromTimeT(select_statement.ColumnInt64(3));
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *score = ThumbnailScore(current_boring_score, current_clipping,
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              current_at_top, last_updated);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::SetFavicon(URLID icon_id,
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   scoped_refptr<RefCountedMemory> icon_data,
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   base::Time time) {
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(icon_id);
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (icon_data->size()) {
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "UPDATE favicons SET image_data=?, last_updated=? WHERE id=?"));
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!statement)
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 0;
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindBlob(0, icon_data->front(),
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       static_cast<int>(icon_data->size()));
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(1, time.ToTimeT());
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(2, icon_id);
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return statement.Run();
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        "UPDATE favicons SET image_data=NULL, last_updated=? WHERE id=?"));
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!statement)
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 0;
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(0, time.ToTimeT());
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.BindInt64(1, icon_id);
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return statement.Run();
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::SetFaviconLastUpdateTime(FaviconID icon_id,
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 base::Time time) {
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "UPDATE favicons SET last_updated=? WHERE id=?"));
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, time.ToTimeT());
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(1, icon_id);
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.Run();
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFaviconID ThumbnailDatabase::GetFaviconIDForFaviconURL(const GURL& icon_url,
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                       int required_icon_type,
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                       IconType* icon_type) {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "SELECT id, icon_type FROM favicons WHERE url=? AND (icon_type & ? > 0) "
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "ORDER BY icon_type DESC"));
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url));
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindInt(1, required_icon_type);
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Step())
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;  // not cached
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (icon_type)
417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    *icon_type = static_cast<IconType>(statement.ColumnInt(1));
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.ColumnInt64(0);
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
421ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::GetFavicon(
422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FaviconID icon_id,
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::Time* last_updated,
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<unsigned char>* png_icon_data,
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL* icon_url) {
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(icon_id);
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "SELECT last_updated, image_data, url FROM favicons WHERE id=?"));
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, icon_id);
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Step())
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // No entry for the id.
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *last_updated = base::Time::FromTimeT(statement.ColumnInt64(0));
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (statement.ColumnByteLength(1) > 0)
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    statement.ColumnBlobAsVector(1, png_icon_data);
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (icon_url)
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *icon_url = GURL(statement.ColumnString(2));
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFaviconID ThumbnailDatabase::AddFavicon(const GURL& icon_url,
448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        IconType icon_type) {
449ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "INSERT INTO favicons (url, icon_type) VALUES (?, ?)"));
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url));
456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindInt(1, icon_type);
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Run())
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return db_.GetLastInsertRowId();
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::DeleteFavicon(FaviconID id) {
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "DELETE FROM favicons WHERE id = ?"));
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
467ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, id);
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return statement.Run();
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
472ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::GetIconMappingForPageURL(const GURL& page_url,
473ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                 IconType required_icon_type,
474ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                 IconMapping* icon_mapping) {
475ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<IconMapping> icon_mappings;
476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!GetIconMappingsForPageURL(page_url, &icon_mappings))
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
478ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
479ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
480ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      m != icon_mappings.end(); ++m) {
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (m->icon_type == required_icon_type) {
482ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (icon_mapping != NULL)
483ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *icon_mapping = *m;
484ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return true;
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
486ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
488ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return false;
489ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
490ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
491ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::GetIconMappingsForPageURL(
492ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& page_url,
493ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::vector<IconMapping>* mapping_data) {
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
495ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "SELECT icon_mapping.id, icon_mapping.icon_id, favicons.icon_type "
496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "FROM icon_mapping "
497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "INNER JOIN favicons "
498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "ON icon_mapping.icon_id = favicons.id "
499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "WHERE icon_mapping.page_url=? "
500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "ORDER BY favicons.icon_type DESC"));
501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!statement)
502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
504ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindString(0, URLDatabase::GURLToDatabaseURL(page_url));
505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool result = false;
507ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (statement.Step()) {
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result = true;
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!mapping_data)
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return result;
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    IconMapping icon_mapping;
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FillIconMapping(statement, page_url, &icon_mapping);
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    mapping_data->push_back(icon_mapping);
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result;
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIconMappingID ThumbnailDatabase::AddIconMapping(const GURL& page_url,
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                FaviconID icon_id) {
521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return AddIconMapping(page_url, icon_id, false);
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
523ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::UpdateIconMapping(IconMappingID mapping_id,
525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          FaviconID icon_id) {
526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "UPDATE icon_mapping SET icon_id=? WHERE id=?"));
528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!statement)
529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return 0;
530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindInt64(0, icon_id);
532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindInt64(1, mapping_id);
533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return statement.Run();
534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::DeleteIconMappings(const GURL& page_url) {
537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
538ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "DELETE FROM icon_mapping WHERE page_url = ?"));
539ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!statement)
540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
541ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
542ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindString(0, URLDatabase::GURLToDatabaseURL(page_url));
543ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return statement.Run();
544ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
546ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::HasMappingFor(FaviconID id) {
547ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
548ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "SELECT id FROM icon_mapping "
549ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "WHERE icon_id=?"));
550ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!statement)
551ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
552ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
553ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindInt64(0, id);
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return statement.Step();
555ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::MigrateIconMappingData(URLDatabase* url_db) {
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  URLDatabase::IconMappingEnumerator e;
559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!url_db->InitIconMappingEnumeratorForEverything(&e))
560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  IconMapping info;
563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (e.GetNextIconMapping(&info)) {
564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO: Using bulk insert to improve the performance.
565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!AddIconMapping(info.page_url, info.icon_id))
566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIconMappingID ThumbnailDatabase::AddToTemporaryIconMappingTable(
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& page_url, const FaviconID icon_id) {
573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return AddIconMapping(page_url, icon_id, true);
574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::CommitTemporaryIconMappingTable() {
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Delete the old icon_mapping table.
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!db_.Execute("DROP TABLE icon_mapping"))
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Rename the temporary one.
582ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!db_.Execute("ALTER TABLE temp_icon_mapping RENAME TO icon_mapping"))
583ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
584ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
585ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // The renamed table needs the index (the temporary table doesn't have one).
586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  InitIconMappingIndex();
587ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
589ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
590ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFaviconID ThumbnailDatabase::CopyToTemporaryFaviconTable(FaviconID source) {
592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "INSERT INTO temp_favicons (url, last_updated, image_data, icon_type)"
594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "SELECT url, last_updated, image_data, icon_type "
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "FROM favicons WHERE id = ?"));
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement)
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  statement.BindInt64(0, source);
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!statement.Run())
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We return the ID of the newly inserted favicon.
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return db_.GetLastInsertRowId();
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
606ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::CommitTemporaryFaviconTable() {
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Delete the old favicons table.
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("DROP TABLE favicons"))
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Rename the temporary one.
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("ALTER TABLE temp_favicons RENAME TO favicons"))
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The renamed table needs the index (the temporary table doesn't have one).
616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  InitFaviconsIndex();
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::NeedsMigrationToTopSites() {
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return !use_top_sites_;
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ThumbnailDatabase::RenameAndDropThumbnails(const FilePath& old_db_file,
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                const FilePath& new_db_file) {
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Init favicons table - same schema as the thumbnails.
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sql::Connection favicons;
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (OpenDatabase(&favicons, new_db_file) != sql::INIT_OK)
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!InitFaviconsTable(&favicons, false) ||
632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !InitIconMappingTable(&favicons, false)) {
633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED() << "Couldn't init favicons and icon-mapping table.";
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    favicons.Close();
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  favicons.Close();
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Can't attach within a transaction.
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (transaction_nesting())
6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    CommitTransaction();
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Attach new DB.
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  {
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This block is needed because otherwise the attach statement is
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // never cleared from cache and we can't close the DB :P
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sql::Statement attach(db_.GetUniqueStatement("ATTACH ? AS new_favicons"));
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!attach) {
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << "Unable to attach database.";
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Keep the transaction open, even though we failed.
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BeginTransaction();
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    attach.BindString(0, new_db_file.value());
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    attach.BindString(0, WideToUTF8(new_db_file.value()));
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!attach.Run()) {
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED() << db_.GetErrorMessage();
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BeginTransaction();
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Move favicons to the new DB.
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("INSERT OR REPLACE INTO new_favicons.favicons "
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   "SELECT * FROM favicons")) {
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Unable to copy favicons.";
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BeginTransaction();
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!db_.Execute("DETACH new_favicons")) {
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Unable to detach database.";
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BeginTransaction();
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  db_.Close();
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reset the DB to point to new file.
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (OpenDatabase(&db_, new_db_file) != sql::INIT_OK)
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  file_util::Delete(old_db_file, false);
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  InitFaviconsIndex();
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reopen the transaction.
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BeginTransaction();
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  use_top_sites_ = true;
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
698ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::InitIconMappingTable(sql::Connection* db,
699ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                             bool is_temporary) {
700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char* name = is_temporary ? "temp_icon_mapping" : "icon_mapping";
701ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!db->DoesTableExist(name)) {
702ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string sql;
703ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sql.append("CREATE TABLE ");
704ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sql.append(name);
705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sql.append("("
706ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               "id INTEGER PRIMARY KEY,"
707ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               "page_url LONGVARCHAR NOT NULL,"
708ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               "icon_id INTEGER)");
709ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!db->Execute(sql.c_str()))
710ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return false;
711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ThumbnailDatabase::InitIconMappingIndex() {
716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Add an index on the url column. We ignore errors. Since this is always
717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // called during startup, the index will normally already exist.
718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  db_.Execute("CREATE INDEX icon_mapping_page_url_idx"
719ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              " ON icon_mapping(page_url)");
720ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  db_.Execute("CREATE INDEX icon_mapping_icon_id_idx ON icon_mapping(icon_id)");
721ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenIconMappingID ThumbnailDatabase::AddIconMapping(const GURL& page_url,
724ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                FaviconID icon_id,
725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                bool is_temporary) {
726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char* name = is_temporary ? "temp_icon_mapping" : "icon_mapping";
727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const char* statement_name =
728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      is_temporary ? "add_temp_icon_mapping" : "add_icon_mapping";
729ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
730ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string sql;
731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql.append("INSERT INTO ");
732ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql.append(name);
733ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql.append("(page_url, icon_id) VALUES (?, ?)");
734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
735ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  sql::Statement statement(
736ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      db_.GetCachedStatement(sql::StatementID(statement_name), sql.c_str()));
737ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!statement)
738ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return 0;
739ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindString(0, URLDatabase::GURLToDatabaseURL(page_url));
741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  statement.BindInt64(1, icon_id);
742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!statement.Run())
744ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return 0;
745ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
746ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return db_.GetLastInsertRowId();
747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
748ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
749ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ThumbnailDatabase::UpgradeToVersion4() {
750ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Set the default icon type as favicon, so the current data are set
751ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // correctly.
752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!db_.Execute("ALTER TABLE favicons ADD icon_type INTEGER DEFAULT 1")) {
753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NOTREACHED();
754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  meta_table_.SetVersionNumber(4);
757ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  meta_table_.SetCompatibleVersionNumber(std::min(4, kCompatibleVersionNumber));
758ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
760ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace history
762