Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: components/bookmarks_enhanced/persistent_image_store.cc

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

Powered by Google App Engine
This is Rietveld 408576698