1 // Copyright 2014 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "browser/favicon/favicon_commands.h"
6 #include "browser/favicon/favicon_database_p.h"
7 #include "third_party/sqlite/sqlite3.h"
10 #define CHECK_RESULT(qry, var, res, st, ret) if (var != res) {\
11 sqlite3_finalize(st);\
12 if (qry) sqlite3_free(qry);\
16 #define CHECK_RESULT_MSG(qry, var, res, st, ret) if (var != res) {\
17 std::cerr << "ERROR! " << name() << " : " << sqlite3ErrStr(result) << std::endl;\
18 sqlite3_finalize(st);\
19 if (qry) sqlite3_free(qry);\
20 setError(sqlite3ErrStr(result));\
24 #define CHECK_PREP_MSG(qry, var, res, ret) if (var != res) {\
25 std::cerr << "ERROR! " << name() << " : " << sqlite3ErrStr(result) << std::endl;\
26 if (qry) sqlite3_free(qry);\
27 setError(sqlite3ErrStr(result));\
32 std::string Command::lastError() const {
33 return std::string("[") + m_name + "] :: " + m_lastError;
36 std::string Command::name() const {
40 void Command::setError(const std::string &err) {
44 scoped_refptr<SerializedBitmap> Command::serialize(const SkBitmap &bitmap) {
45 scoped_refptr<SerializedBitmap> res(new SerializedBitmap);
46 if (bitmap.isNull()) {
49 res->alloc(bitmap.getSize() + 4 * sizeof(int));
50 static_cast<int *>(res->data)[0] = static_cast<int>(bitmap.colorType());
51 static_cast<int *>(res->data)[1] = static_cast<int>(bitmap.alphaType());
52 static_cast<int *>(res->data)[2] = bitmap.width();
53 static_cast<int *>(res->data)[3] = bitmap.height();
54 if (!bitmap.copyPixelsTo(static_cast<int *>(res->data) + 4, bitmap.getSize())) {
60 SkBitmap Command::deserialize(const void *data) {
65 SkColorType colorType = static_cast<SkColorType>(static_cast<const int *>(data)[0]);
66 SkAlphaType alphaType = static_cast<SkAlphaType>(static_cast<const int *>(data)[1]);
67 int width = static_cast<const int *>(data)[2];
68 int height = static_cast<const int *>(data)[3];
70 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, alphaType), 0);
71 bitmap.setPixels(static_cast<int *>(const_cast<void *>(data)) + 4);
73 // as the |data| set to the |bitmap| are retrieved from sqlite blob,
74 // this |data| would be freed by sqlite on finalize, so to be sure that
75 // the deserialized SkBitmap owns and holds it's internal image data
76 // for it's whole lifetime, we create a deep copy of the |bitmap|.
78 bitmap.copyTo(©, colorType);
82 const char *Command::sqlite3ErrStr(int rc) {
83 static const char* const aMsg[] = {
84 /* SQLITE_OK */ "not an error",
85 /* SQLITE_ERROR */ "SQL logic error or missing database",
86 /* SQLITE_INTERNAL */ 0,
87 /* SQLITE_PERM */ "access permission denied",
88 /* SQLITE_ABORT */ "callback requested query abort",
89 /* SQLITE_BUSY */ "database is locked",
90 /* SQLITE_LOCKED */ "database table is locked",
91 /* SQLITE_NOMEM */ "out of memory",
92 /* SQLITE_READONLY */ "attempt to write a readonly database",
93 /* SQLITE_INTERRUPT */ "interrupted",
94 /* SQLITE_IOERR */ "disk I/O error",
95 /* SQLITE_CORRUPT */ "database disk image is malformed",
96 /* SQLITE_NOTFOUND */ "unknown operation",
97 /* SQLITE_FULL */ "database or disk is full",
98 /* SQLITE_CANTOPEN */ "unable to open database file",
99 /* SQLITE_PROTOCOL */ "locking protocol",
100 /* SQLITE_EMPTY */ "table contains no data",
101 /* SQLITE_SCHEMA */ "database schema has changed",
102 /* SQLITE_TOOBIG */ "string or blob too big",
103 /* SQLITE_CONSTRAINT */ "constraint failed",
104 /* SQLITE_MISMATCH */ "datatype mismatch",
105 /* SQLITE_MISUSE */ "library routine called out of sequence",
106 /* SQLITE_NOLFS */ "large file support is disabled",
107 /* SQLITE_AUTH */ "authorization denied",
108 /* SQLITE_FORMAT */ "auxiliary database format error",
109 /* SQLITE_RANGE */ "bind or column index out of range",
110 /* SQLITE_NOTADB */ "file is encrypted or is not a database",
113 if (rc>=0 && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
116 return "unknown error";
122 InitDatabaseCommand::InitDatabaseCommand(FaviconDatabasePrivate *db)
123 : Command("InitDatabase", db) {
126 bool InitDatabaseCommand::sqlExecute() {
127 char *query = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (%q TEXT PRIMARY KEY, %q TEXT);",
128 db()->pageUrlToFaviconUrlTable,
129 db()->pageUrlColumn, db()->faviconUrlColumn);
132 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
133 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
135 result = sqlite3_step(stmt);
136 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
138 sqlite3_finalize(stmt);
141 query = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (%q TEXT PRIMARY KEY REFERENCES %q (%q), %q BLOB);",
142 db()->faviconUrlToBitmapTable, db()->faviconUrlColumn,
143 db()->pageUrlToFaviconUrlTable, db()->faviconUrlColumn,
146 result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
147 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
149 result = sqlite3_step(stmt);
150 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
152 sqlite3_finalize(stmt);
158 LoadDatabaseCommand::LoadDatabaseCommand(FaviconDatabasePrivate *db)
159 : Command("LoadDatabase", db) {
162 bool LoadDatabaseCommand::sqlExecute()
164 db()->pageToFaviconUrl.clear();
165 db()->faviconUrlToBitmap.clear();
167 char *query = sqlite3_mprintf("SELECT %q, %q FROM %q;", db()->pageUrlColumn,
168 db()->faviconUrlColumn, db()->pageUrlToFaviconUrlTable);
171 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
172 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
174 while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
175 GURL pageUrl(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
176 GURL faviconUrl(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)));
177 db()->pageToFaviconUrl[pageUrl] = faviconUrl;
180 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
181 sqlite3_finalize(stmt);
184 query = sqlite3_mprintf("SELECT %q, %q FROM %q;", db()->faviconUrlColumn,
185 db()->bitmapColumn, db()->faviconUrlToBitmapTable);
187 result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
188 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
190 while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
191 GURL faviconUrl(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
192 const void *data = sqlite3_column_blob(stmt, 1);
193 SkBitmap bitmap = deserialize(data);
194 db()->faviconUrlToBitmap[faviconUrl] = bitmap;
197 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
198 sqlite3_finalize(stmt);
205 ClearDatabaseCommand::ClearDatabaseCommand(FaviconDatabasePrivate *db)
206 : Command("ClearDatabase", db) {
209 bool ClearDatabaseCommand::execute() {
210 db()->pageToFaviconUrl.clear();
211 db()->faviconUrlToBitmap.clear();
215 bool ClearDatabaseCommand::sqlExecute() {
216 char *query = sqlite3_mprintf("DELETE FROM %q; DELETE FROM %q;",
217 db()->faviconUrlToBitmapTable, db()->pageUrlToFaviconUrlTable);
219 int result = sqlite3_exec(db()->sqlite, query, 0, 0, 0);
221 if (result != SQLITE_OK) {
227 // INSERT FAVICON URL
228 InsertFaviconURLCommand::InsertFaviconURLCommand(FaviconDatabasePrivate *db,
230 const GURL &faviconUrl)
231 : Command("InsertFaviconURL", db),
232 m_pageUrl(pageUrl.spec()),
233 m_faviconUrl(faviconUrl.spec()) {
236 bool InsertFaviconURLCommand::execute() {
237 db()->pageToFaviconUrl[GURL(m_pageUrl)] = GURL(m_faviconUrl);
241 bool InsertFaviconURLCommand::sqlExecute() {
242 char *query = sqlite3_mprintf("INSERT INTO %q VALUES(?, ?);", db()->pageUrlToFaviconUrlTable);
244 sqlite3_stmt *stmt = 0;
245 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
246 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
248 result = sqlite3_bind_text(stmt, 1, m_pageUrl.c_str(), m_pageUrl.size(), SQLITE_STATIC);
249 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
250 result = sqlite3_bind_text(stmt, 2, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
251 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
253 result = sqlite3_step(stmt);
254 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
256 sqlite3_finalize(stmt);
261 // UPDATE FAVICON URL
262 UpdateFaviconURLCommand::UpdateFaviconURLCommand(FaviconDatabasePrivate *db,
264 const GURL &faviconUrl)
265 : Command("UpdateFaviconURL", db),
266 m_pageUrl(pageUrl.spec()),
267 m_faviconUrl(faviconUrl.spec()) {
270 bool UpdateFaviconURLCommand::execute() {
271 db()->pageToFaviconUrl[GURL(m_pageUrl)] = GURL(m_faviconUrl);
275 bool UpdateFaviconURLCommand::sqlExecute() {
276 char *query = sqlite3_mprintf("UPDATE %q SET %q = ? WHERE %q = ? ;",
277 db()->pageUrlToFaviconUrlTable, db()->faviconUrlColumn,
278 db()->pageUrlColumn);
280 sqlite3_stmt *stmt = 0;
281 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
282 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
284 result = sqlite3_bind_text(stmt, 1, m_pageUrl.c_str(), m_pageUrl.size(), SQLITE_STATIC);
285 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
286 result = sqlite3_bind_text(stmt, 2, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
287 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
289 result = sqlite3_step(stmt);
290 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
292 sqlite3_finalize(stmt);
298 InsertBitmapCommand::InsertBitmapCommand(FaviconDatabasePrivate *db,
299 const GURL &faviconUrl,
300 const SkBitmap &bitmap)
301 : Command("InsertBitmap", db),
302 m_faviconUrl(faviconUrl.spec()),
306 bool InsertBitmapCommand::execute() {
307 db()->faviconUrlToBitmap[GURL(m_faviconUrl)] = m_bitmap;
311 bool InsertBitmapCommand::sqlExecute() {
312 char *query = sqlite3_mprintf("INSERT INTO %q VALUES (?, ?);", db()->faviconUrlToBitmapTable);
314 sqlite3_stmt *stmt = 0;
315 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
316 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
318 result = sqlite3_bind_text(stmt, 1, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
319 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
321 scoped_refptr<SerializedBitmap> serializedBitmap = serialize(m_bitmap);
322 if (!serializedBitmap->data) {
323 sqlite3_finalize(stmt);
328 result = sqlite3_bind_blob(stmt, 2, serializedBitmap->data, serializedBitmap->size, SQLITE_TRANSIENT);
329 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
331 result = sqlite3_step(stmt);
332 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
334 sqlite3_finalize(stmt);
340 UpdateBitmapCommand::UpdateBitmapCommand(FaviconDatabasePrivate *db,
341 const GURL &faviconUrl,
342 const SkBitmap &bitmap)
343 : Command("UpdateBitmap", db),
344 m_faviconUrl(faviconUrl.spec()),
348 bool UpdateBitmapCommand::execute() {
349 db()->faviconUrlToBitmap[GURL(m_faviconUrl)] = m_bitmap;
353 bool UpdateBitmapCommand::sqlExecute() {
354 char *query = sqlite3_mprintf("UPDATE %q SET %q = ? WHERE %q = ? ;",
355 db()->faviconUrlToBitmapTable, db()->bitmapColumn,
356 db()->faviconUrlColumn);
358 sqlite3_stmt *stmt = 0;
359 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
360 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
362 scoped_refptr<SerializedBitmap> serializedBitmap = serialize(m_bitmap);
363 if (!serializedBitmap->data) {
364 sqlite3_finalize(stmt);
368 result = sqlite3_bind_blob(stmt, 1, serializedBitmap->data, serializedBitmap->size, SQLITE_STATIC);
369 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
371 result = sqlite3_bind_text(stmt, 2, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
372 CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
374 result = sqlite3_step(stmt);
375 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
377 sqlite3_finalize(stmt);
383 RemoveBitmapCommand::RemoveBitmapCommand(FaviconDatabasePrivate *db, const GURL &faviconUrl)
384 : Command("RemoveBitmap", db),
385 m_faviconUrl(faviconUrl.spec()) {
388 bool RemoveBitmapCommand::execute() {
389 std::map<GURL, SkBitmap>::iterator it = db()->faviconUrlToBitmap.find(GURL(m_faviconUrl));
390 if (it != db()->faviconUrlToBitmap.end()) {
391 db()->faviconUrlToBitmap.erase(it);
396 bool RemoveBitmapCommand::sqlExecute() {
397 char *query = sqlite3_mprintf("DELETE FROM %q WHERE %q = ? ;", db()->faviconUrlToBitmapTable, db()->faviconUrlColumn);
399 sqlite3_stmt *stmt = 0;
400 int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
401 CHECK_PREP_MSG(query, result, SQLITE_OK, false);
403 result = sqlite3_step(stmt);
404 CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
406 sqlite3_finalize(stmt);