[M47_2526] Chromium upversion to m47_2526 branch
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / browser / favicon / favicon_commands.cc
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.
4
5 #include "browser/favicon/favicon_commands.h"
6 #include "browser/favicon/favicon_database_p.h"
7 #include "third_party/sqlite/sqlite3.h"
8 #include <iostream>
9
10 #define CHECK_RESULT(qry, var, res, st, ret) if (var != res) {\
11                                           sqlite3_finalize(st);\
12                                           if (qry) sqlite3_free(qry);\
13                                           return ret;\
14                                         }
15
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));\
21                                               return ret;\
22                                             }
23
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));\
28                                               return ret;\
29                                             }
30
31
32 std::string Command::lastError() const {
33   return std::string("[") + m_name + "] :: " + m_lastError;
34 }
35
36 std::string Command::name() const {
37   return m_name;
38 }
39
40 void Command::setError(const std::string &err) {
41   m_lastError = err;
42 }
43
44 scoped_refptr<SerializedBitmap> Command::serialize(const SkBitmap &bitmap) {
45   scoped_refptr<SerializedBitmap> res(new SerializedBitmap);
46   if (bitmap.isNull()) {
47     return res;
48   }
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())) {
55     res->free();
56   }
57   return res;
58 }
59
60 SkBitmap Command::deserialize(const void *data) {
61   if (!data) {
62     return SkBitmap();
63   }
64
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];
69   SkBitmap bitmap;
70   bitmap.setInfo(SkImageInfo::Make(width, height, colorType, alphaType), 0);
71   bitmap.setPixels(static_cast<int *>(const_cast<void *>(data)) + 4);
72
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|.
77   SkBitmap copy;
78   bitmap.copyTo(&copy, colorType);
79   return copy;
80 }
81
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",
111   };
112   rc &= 0xff;
113   if (rc>=0 && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
114     return aMsg[rc];
115   } else {
116     return "unknown error";
117   }
118 }
119
120
121 // INIT
122 InitDatabaseCommand::InitDatabaseCommand(FaviconDatabasePrivate *db)
123   : Command("InitDatabase", db) {
124 }
125
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);
130
131   sqlite3_stmt *stmt;
132   int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
133   CHECK_PREP_MSG(query, result, SQLITE_OK, false);
134
135   result = sqlite3_step(stmt);
136   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
137
138   sqlite3_finalize(stmt);
139   sqlite3_free(query);
140
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,
144                           db()->bitmapColumn);
145
146   result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
147   CHECK_PREP_MSG(query, result, SQLITE_OK, false);
148
149   result = sqlite3_step(stmt);
150   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
151
152   sqlite3_finalize(stmt);
153   sqlite3_free(query);
154   return true;
155 }
156
157 // LOAD
158 LoadDatabaseCommand::LoadDatabaseCommand(FaviconDatabasePrivate *db)
159   : Command("LoadDatabase", db) {
160 }
161
162 bool LoadDatabaseCommand::sqlExecute()
163 {
164   db()->pageToFaviconUrl.clear();
165   db()->faviconUrlToBitmap.clear();
166
167   char *query = sqlite3_mprintf("SELECT %q, %q FROM %q;", db()->pageUrlColumn,
168                                 db()->faviconUrlColumn, db()->pageUrlToFaviconUrlTable);
169
170   sqlite3_stmt *stmt;
171   int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
172   CHECK_PREP_MSG(query, result, SQLITE_OK, false);
173
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;
178   }
179
180   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
181   sqlite3_finalize(stmt);
182   sqlite3_free(query);
183
184   query = sqlite3_mprintf("SELECT %q, %q FROM %q;", db()->faviconUrlColumn,
185                           db()->bitmapColumn, db()->faviconUrlToBitmapTable);
186
187   result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
188   CHECK_PREP_MSG(query, result, SQLITE_OK, false);
189
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;
195   }
196
197   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
198   sqlite3_finalize(stmt);
199   sqlite3_free(query);
200
201   return true;
202 }
203
204 // CLEAR
205 ClearDatabaseCommand::ClearDatabaseCommand(FaviconDatabasePrivate *db)
206   : Command("ClearDatabase", db) {
207 }
208
209 bool ClearDatabaseCommand::execute() {
210   db()->pageToFaviconUrl.clear();
211   db()->faviconUrlToBitmap.clear();
212   return true;
213 }
214
215 bool ClearDatabaseCommand::sqlExecute() {
216   char *query = sqlite3_mprintf("DELETE FROM %q; DELETE FROM %q;",
217                                 db()->faviconUrlToBitmapTable, db()->pageUrlToFaviconUrlTable);
218
219   int result = sqlite3_exec(db()->sqlite, query, 0, 0, 0);
220   sqlite3_free(query);
221   if (result != SQLITE_OK) {
222     return false;
223   }
224   return true;
225 }
226
227 // INSERT FAVICON URL
228 InsertFaviconURLCommand::InsertFaviconURLCommand(FaviconDatabasePrivate *db,
229                                                  const GURL &pageUrl,
230                                                  const GURL &faviconUrl)
231   : Command("InsertFaviconURL", db),
232     m_pageUrl(pageUrl.spec()),
233     m_faviconUrl(faviconUrl.spec()) {
234 }
235
236 bool InsertFaviconURLCommand::execute() {
237   db()->pageToFaviconUrl[GURL(m_pageUrl)] = GURL(m_faviconUrl);
238   return true;
239 }
240
241 bool InsertFaviconURLCommand::sqlExecute() {
242   char *query = sqlite3_mprintf("INSERT INTO %q VALUES(?, ?);", db()->pageUrlToFaviconUrlTable);
243
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);
247
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);
252
253   result = sqlite3_step(stmt);
254   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
255
256   sqlite3_finalize(stmt);
257   sqlite3_free(query);
258   return true;
259 }
260
261 // UPDATE FAVICON URL
262 UpdateFaviconURLCommand::UpdateFaviconURLCommand(FaviconDatabasePrivate *db,
263                                                  const GURL &pageUrl,
264                                                  const GURL &faviconUrl)
265   : Command("UpdateFaviconURL", db),
266     m_pageUrl(pageUrl.spec()),
267     m_faviconUrl(faviconUrl.spec()) {
268 }
269
270 bool UpdateFaviconURLCommand::execute() {
271   db()->pageToFaviconUrl[GURL(m_pageUrl)] = GURL(m_faviconUrl);
272   return true;
273 }
274
275 bool UpdateFaviconURLCommand::sqlExecute() {
276   char *query = sqlite3_mprintf("UPDATE %q SET %q = ? WHERE %q = ? ;",
277                                 db()->pageUrlToFaviconUrlTable, db()->faviconUrlColumn,
278                                 db()->pageUrlColumn);
279
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);
283
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);
288
289   result = sqlite3_step(stmt);
290   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
291
292   sqlite3_finalize(stmt);
293   sqlite3_free(query);
294   return true;
295 }
296
297 // INSERT BITMAP
298 InsertBitmapCommand::InsertBitmapCommand(FaviconDatabasePrivate *db,
299                                          const GURL &faviconUrl,
300                                          const SkBitmap &bitmap)
301   : Command("InsertBitmap", db),
302     m_faviconUrl(faviconUrl.spec()),
303     m_bitmap(bitmap) {
304 }
305
306 bool InsertBitmapCommand::execute() {
307   db()->faviconUrlToBitmap[GURL(m_faviconUrl)] = m_bitmap;
308   return true;
309 }
310
311 bool InsertBitmapCommand::sqlExecute() {
312   char *query = sqlite3_mprintf("INSERT INTO %q VALUES (?, ?);", db()->faviconUrlToBitmapTable);
313
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);
317
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);
320
321   scoped_refptr<SerializedBitmap> serializedBitmap = serialize(m_bitmap);
322   if (!serializedBitmap->data) {
323     sqlite3_finalize(stmt);
324     sqlite3_free(query);
325     return false;
326   }
327
328   result = sqlite3_bind_blob(stmt, 2, serializedBitmap->data, serializedBitmap->size, SQLITE_TRANSIENT);
329   CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
330
331   result = sqlite3_step(stmt);
332   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
333
334   sqlite3_finalize(stmt);
335   sqlite3_free(query);
336   return true;
337 }
338
339 // UPDATE BITMAP
340 UpdateBitmapCommand::UpdateBitmapCommand(FaviconDatabasePrivate *db,
341                                          const GURL &faviconUrl,
342                                          const SkBitmap &bitmap)
343   : Command("UpdateBitmap", db),
344     m_faviconUrl(faviconUrl.spec()),
345     m_bitmap(bitmap) {
346 }
347
348 bool UpdateBitmapCommand::execute() {
349   db()->faviconUrlToBitmap[GURL(m_faviconUrl)] = m_bitmap;
350   return true;
351 }
352
353 bool UpdateBitmapCommand::sqlExecute() {
354   char *query = sqlite3_mprintf("UPDATE %q SET %q = ? WHERE %q = ? ;",
355                                 db()->faviconUrlToBitmapTable, db()->bitmapColumn,
356                                 db()->faviconUrlColumn);
357
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);
361
362   scoped_refptr<SerializedBitmap> serializedBitmap = serialize(m_bitmap);
363   if (!serializedBitmap->data) {
364     sqlite3_finalize(stmt);
365     return false;
366   }
367
368   result = sqlite3_bind_blob(stmt, 1, serializedBitmap->data, serializedBitmap->size, SQLITE_STATIC);
369   CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
370
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);
373
374   result = sqlite3_step(stmt);
375   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
376
377   sqlite3_finalize(stmt);
378   sqlite3_free(query);
379   return true;
380 }
381
382 // REMOVE BITMAP
383 RemoveBitmapCommand::RemoveBitmapCommand(FaviconDatabasePrivate *db, const GURL &faviconUrl)
384   : Command("RemoveBitmap", db),
385     m_faviconUrl(faviconUrl.spec()) {
386 }
387
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);
392   }
393   return true;
394 }
395
396 bool RemoveBitmapCommand::sqlExecute() {
397   char *query = sqlite3_mprintf("DELETE FROM %q WHERE %q = ? ;", db()->faviconUrlToBitmapTable, db()->faviconUrlColumn);
398
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);
402
403   result = sqlite3_step(stmt);
404   CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
405
406   sqlite3_finalize(stmt);
407   sqlite3_free(query);
408   return true;
409 }