1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/enhanced_bookmarks/persistent_image_store.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/files/file.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/enhanced_bookmarks/image_store_util.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "sql/statement.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "sql/transaction.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/geometry/size.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/gurl.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool InitTables(sql::Connection& db) {
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const char kTableSql[] =
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "CREATE TABLE IF NOT EXISTS images_by_url ("
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "page_url LONGVARCHAR NOT NULL,"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "image_url LONGVARCHAR NOT NULL,"
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "image_data BLOB,"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "width INTEGER,"
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "height INTEGER"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ")";
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!db.Execute(kTableSql))
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool InitIndices(sql::Connection& db) {
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const char kIndexSql[] =
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "CREATE INDEX IF NOT EXISTS images_by_url_idx ON images_by_url(page_url)";
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!db.Execute(kIndexSql))
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)sql::InitStatus OpenDatabaseImpl(sql::Connection& db,
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const base::FilePath& db_path) {
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!db.is_open());
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  db.set_histogram_tag("BookmarkImages");
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(noyau): Set page and cache sizes?
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(noyau): Set error callback?
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Run the database in exclusive mode. Nobody else should be accessing the
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // database while we're running, and this will give somewhat improved perf.
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  db.set_exclusive_locking();
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!db.Open(db_path))
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return sql::INIT_FAILURE;
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Scope initialization in a transaction so we can't be partially initialized.
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Transaction transaction(&db);
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction.Begin())
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return sql::INIT_FAILURE;
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create the tables.
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!InitTables(db) ||
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      !InitIndices(db)) {
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return sql::INIT_FAILURE;
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Initialization is complete.
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transaction.Commit())
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return sql::INIT_FAILURE;
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return sql::INIT_OK;
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PersistentImageStore::PersistentImageStore(const base::FilePath& path)
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : ImageStore(),
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      path_(path.Append(
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::FilePath::FromUTF8Unsafe("BookmarkImageAndUrlStore.db"))) {
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PersistentImageStore::HasKey(const GURL& page_url) {
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "SELECT COUNT(*) FROM images_by_url WHERE page_url = ?"));
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindString(0, page_url.possibly_invalid_spec());
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int count = statement.Step() ? statement.ColumnInt(0) : 0;
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return !!count;
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PersistentImageStore::Insert(const GURL& page_url,
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  const GURL& image_url,
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  const gfx::Image& image) {
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Erase(page_url);  // Remove previous image for this url, if any.
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "INSERT INTO images_by_url "
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "(page_url, image_url, image_data, width, height)"
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "VALUES (?, ?, ?, ?, ?)"));
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindString(0, page_url.possibly_invalid_spec());
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindString(1, image_url.possibly_invalid_spec());
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_refptr<base::RefCountedMemory> image_bytes =
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        enhanced_bookmarks::BytesForImage(image);
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Insert an empty image in case encoding fails.
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!image_bytes.get())
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    image_bytes = enhanced_bookmarks::BytesForImage(gfx::Image());
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(image_bytes.get());
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindBlob(2, image_bytes->front(), (int)image_bytes->size());
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindInt(3, image.Size().width());
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindInt(4, image.Size().height());
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.Run();
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PersistentImageStore::Erase(const GURL& page_url) {
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "DELETE FROM images_by_url WHERE page_url = ?"));
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindString(0, page_url.possibly_invalid_spec());
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.Run();
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::pair<gfx::Image, GURL> PersistentImageStore::Get(const GURL& page_url) {
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return std::make_pair(gfx::Image(), GURL());
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "SELECT image_data, image_url FROM images_by_url WHERE page_url = ?"));
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindString(0, page_url.possibly_invalid_spec());
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (statement.Step()) {
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (statement.ColumnByteLength(0) > 0) {
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      statement.ColumnBlobAsVector(0, &data->data());
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return std::make_pair(enhanced_bookmarks::ImageForBytes(data),
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            GURL(statement.ColumnString(1)));
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return std::make_pair(gfx::Image(), GURL());
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size PersistentImageStore::GetSize(const GURL& page_url) {
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return gfx::Size();
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "SELECT width, height FROM images_by_url WHERE page_url = ?"));
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.BindString(0, page_url.possibly_invalid_spec());
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (statement.Step()) {
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (statement.ColumnByteLength(0) > 0) {
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int width = statement.ColumnInt(0);
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int height = statement.ColumnInt(1);
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return gfx::Size(width, height);
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return gfx::Size();
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PersistentImageStore::GetAllPageUrls(std::set<GURL>* urls) {
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(urls->empty());
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE,
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "SELECT page_url FROM images_by_url"));
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (statement.Step())
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    urls->insert(GURL(statement.ColumnString(0)));
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PersistentImageStore::ClearAll() {
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (OpenDatabase() != sql::INIT_OK)
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::Statement statement(db_.GetCachedStatement(
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SQL_FROM_HERE, "DELETE FROM images_by_url"));
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  statement.Run();
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int64 PersistentImageStore::GetStoreSizeInBytes() {
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::File file(path_, base::File::FLAG_OPEN | base::File::FLAG_READ);
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return file.IsValid() ? file.GetLength() : -1;
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PersistentImageStore::~PersistentImageStore() {
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)sql::InitStatus PersistentImageStore::OpenDatabase() {
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (db_.is_open())
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return sql::INIT_OK;
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const size_t kAttempts = 2;
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  sql::InitStatus status = sql::INIT_FAILURE;
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < kAttempts; ++i) {
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    status = OpenDatabaseImpl(db_, path_);
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (status == sql::INIT_OK)
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return status;
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Can't open, raze().
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (db_.is_open())
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      db_.Raze();
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    db_.Close();
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(false) << "Can't open image DB";
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return sql::INIT_FAILURE;
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
233