Implementn FaviconDatabase.
authorFilip Piechocki <f.piechocki@samsung.com>
Fri, 16 May 2014 10:56:49 +0000 (12:56 +0200)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
The following functions were implemented:

ewk_context_icon_database_path_set
ewk_context_icon_database_icon_object_add
"icon,received"

Issue: CBWEBVIEW-313, CBWEBVIEW-312
Change-Id: I15862b51ce0af42ebb4424abcebd5d2aa9d82285

16 files changed:
tizen_src/impl/browser/favicon/favicon_commands.cc [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_commands.h [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_database.cc [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_database.h [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_database_p.cc [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_database_p.h [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_downloader.cc [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_downloader.h [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_service.cc [new file with mode: 0644]
tizen_src/impl/browser/favicon/favicon_service.h [new file with mode: 0644]
tizen_src/impl/chromium-efl.gyp
tizen_src/impl/eweb_context.cc
tizen_src/impl/eweb_context.h
tizen_src/impl/eweb_view_callbacks.h
tizen_src/impl/web_contents_delegate_efl.cc
tizen_src/impl/web_contents_delegate_efl.h

diff --git a/tizen_src/impl/browser/favicon/favicon_commands.cc b/tizen_src/impl/browser/favicon/favicon_commands.cc
new file mode 100644 (file)
index 0000000..4c975c7
--- /dev/null
@@ -0,0 +1,404 @@
+#include "browser/favicon/favicon_commands.h"
+#include "browser/favicon/favicon_database_p.h"
+#include "third_party/sqlite/sqlite3.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include <iostream>
+
+#define CHECK_RESULT(qry, var, res, st, ret) if (var != res) {\
+                                          sqlite3_finalize(st);\
+                                          if (qry) sqlite3_free(qry);\
+                                          return ret;\
+                                        }
+
+#define CHECK_RESULT_MSG(qry, var, res, st, ret) if (var != res) {\
+                                              std::cerr << "ERROR! " << name() << " : " << sqlite3ErrStr(result) << std::endl;\
+                                              sqlite3_finalize(st);\
+                                              if (qry) sqlite3_free(qry);\
+                                              setError(sqlite3ErrStr(result));\
+                                              return ret;\
+                                            }
+
+#define CHECK_PREP_MSG(qry, var, res, ret) if (var != res) {\
+                                              std::cerr << "ERROR! " << name() << " : " << sqlite3ErrStr(result) << std::endl;\
+                                              if (qry) sqlite3_free(qry);\
+                                              setError(sqlite3ErrStr(result));\
+                                              return ret;\
+                                            }
+
+
+std::string Command::lastError() const {
+  return std::string("[") + m_name + "] :: " + m_lastError;
+}
+
+std::string Command::name() const {
+  return m_name;
+}
+
+void Command::setError(const std::string &err) {
+  m_lastError = err;
+}
+
+scoped_refptr<SerializedBitmap> Command::serialize(const SkBitmap &bitmap) {
+  scoped_refptr<SerializedBitmap> res(new SerializedBitmap);
+  if (bitmap.isNull()) {
+    return res;
+  }
+  res->alloc(bitmap.getSize() + 3 * sizeof(int));
+  static_cast<int *>(res->data)[0] = static_cast<int>(bitmap.config());
+  static_cast<int *>(res->data)[1] = bitmap.width();
+  static_cast<int *>(res->data)[2] = bitmap.height();
+  if (!bitmap.copyPixelsTo(static_cast<int *>(res->data) + 3, bitmap.getSize())) {
+    res->free();
+  }
+  return res;
+}
+
+SkBitmap Command::deserialize(const void *data) {
+  if (!data) {
+    return SkBitmap();
+  }
+
+  SkBitmap::Config config = static_cast<SkBitmap::Config>(static_cast<const int *>(data)[0]);
+  int width = static_cast<const int *>(data)[1];
+  int height = static_cast<const int *>(data)[2];
+  SkBitmap bitmap;
+  bitmap.setConfig(config, width, height);
+  bitmap.setPixels(static_cast<int *>(const_cast<void *>(data)) + 3);
+
+  // as the |data| set to the |bitmap| are retrieved from sqlite blob,
+  // this |data| would be freed by sqlite on finalize, so to be sure that
+  // the deserialized SkBitmap owns and holds it's internal image data
+  // for it's whole lifetime, we create a deep copy of the |bitmap|.
+  SkBitmap copy;
+  bitmap.copyTo(&copy, SkBitmapConfigToColorType(bitmap.config()));
+  return copy;
+}
+
+const char *Command::sqlite3ErrStr(int rc) {
+  static const char* const aMsg[] = {
+    /* SQLITE_OK          */ "not an error",
+    /* SQLITE_ERROR       */ "SQL logic error or missing database",
+    /* SQLITE_INTERNAL    */ 0,
+    /* SQLITE_PERM        */ "access permission denied",
+    /* SQLITE_ABORT       */ "callback requested query abort",
+    /* SQLITE_BUSY        */ "database is locked",
+    /* SQLITE_LOCKED      */ "database table is locked",
+    /* SQLITE_NOMEM       */ "out of memory",
+    /* SQLITE_READONLY    */ "attempt to write a readonly database",
+    /* SQLITE_INTERRUPT   */ "interrupted",
+    /* SQLITE_IOERR       */ "disk I/O error",
+    /* SQLITE_CORRUPT     */ "database disk image is malformed",
+    /* SQLITE_NOTFOUND    */ "unknown operation",
+    /* SQLITE_FULL        */ "database or disk is full",
+    /* SQLITE_CANTOPEN    */ "unable to open database file",
+    /* SQLITE_PROTOCOL    */ "locking protocol",
+    /* SQLITE_EMPTY       */ "table contains no data",
+    /* SQLITE_SCHEMA      */ "database schema has changed",
+    /* SQLITE_TOOBIG      */ "string or blob too big",
+    /* SQLITE_CONSTRAINT  */ "constraint failed",
+    /* SQLITE_MISMATCH    */ "datatype mismatch",
+    /* SQLITE_MISUSE      */ "library routine called out of sequence",
+    /* SQLITE_NOLFS       */ "large file support is disabled",
+    /* SQLITE_AUTH        */ "authorization denied",
+    /* SQLITE_FORMAT      */ "auxiliary database format error",
+    /* SQLITE_RANGE       */ "bind or column index out of range",
+    /* SQLITE_NOTADB      */ "file is encrypted or is not a database",
+  };
+  rc &= 0xff;
+  if (rc>=0 && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
+    return aMsg[rc];
+  } else {
+    return "unknown error";
+  }
+}
+
+
+// INIT
+InitDatabaseCommand::InitDatabaseCommand(FaviconDatabasePrivate *db)
+  : Command("InitDatabase", db) {
+}
+
+bool InitDatabaseCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (%q TEXT PRIMARY KEY, %q TEXT);",
+                                db()->pageUrlToFaviconUrlTable,
+                                db()->pageUrlColumn, db()->faviconUrlColumn);
+
+  sqlite3_stmt *stmt;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+
+  query = sqlite3_mprintf("CREATE TABLE IF NOT EXISTS %q (%q TEXT PRIMARY KEY REFERENCES %q (%q), %q BLOB);",
+                          db()->faviconUrlToBitmapTable, db()->faviconUrlColumn,
+                          db()->pageUrlToFaviconUrlTable, db()->faviconUrlColumn,
+                          db()->bitmapColumn);
+
+  result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+  return true;
+}
+
+// LOAD
+LoadDatabaseCommand::LoadDatabaseCommand(FaviconDatabasePrivate *db)
+  : Command("LoadDatabase", db) {
+}
+
+bool LoadDatabaseCommand::sqlExecute()
+{
+  db()->pageToFaviconUrl.clear();
+  db()->faviconUrlToBitmap.clear();
+
+  char *query = sqlite3_mprintf("SELECT %q, %q FROM %q;", db()->pageUrlColumn,
+                                db()->faviconUrlColumn, db()->pageUrlToFaviconUrlTable);
+
+  sqlite3_stmt *stmt;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
+    GURL pageUrl(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
+    GURL faviconUrl(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)));
+    db()->pageToFaviconUrl[pageUrl] = faviconUrl;
+  }
+
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+
+  query = sqlite3_mprintf("SELECT %q, %q FROM %q;", db()->faviconUrlColumn,
+                          db()->bitmapColumn, db()->faviconUrlToBitmapTable);
+
+  result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
+    GURL faviconUrl(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
+    const void *data = sqlite3_column_blob(stmt, 1);
+    SkBitmap bitmap = deserialize(data);
+    db()->faviconUrlToBitmap[faviconUrl] = bitmap;
+  }
+
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+
+  return true;
+}
+
+// CLEAR
+ClearDatabaseCommand::ClearDatabaseCommand(FaviconDatabasePrivate *db)
+  : Command("ClearDatabase", db) {
+}
+
+bool ClearDatabaseCommand::execute() {
+  db()->pageToFaviconUrl.clear();
+  db()->faviconUrlToBitmap.clear();
+  return true;
+}
+
+bool ClearDatabaseCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("DELETE FROM %q; DELETE FROM %q;",
+                                db()->faviconUrlToBitmapTable, db()->pageUrlToFaviconUrlTable);
+
+  int result = sqlite3_exec(db()->sqlite, query, 0, 0, 0);
+  sqlite3_free(query);
+  if (result != SQLITE_OK) {
+    return false;
+  }
+  return true;
+}
+
+// INSERT FAVICON URL
+InsertFaviconURLCommand::InsertFaviconURLCommand(FaviconDatabasePrivate *db,
+                                                 const GURL &pageUrl,
+                                                 const GURL &faviconUrl)
+  : Command("InsertFaviconURL", db),
+    m_pageUrl(pageUrl.spec()),
+    m_faviconUrl(faviconUrl.spec()) {
+}
+
+bool InsertFaviconURLCommand::execute() {
+  db()->pageToFaviconUrl[GURL(m_pageUrl)] = GURL(m_faviconUrl);
+  return true;
+}
+
+bool InsertFaviconURLCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("INSERT INTO %q VALUES(?, ?);", db()->pageUrlToFaviconUrlTable);
+
+  sqlite3_stmt *stmt = 0;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  result = sqlite3_bind_text(stmt, 1, m_pageUrl.c_str(), m_pageUrl.size(), SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+  result = sqlite3_bind_text(stmt, 2, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+  return true;
+}
+
+// UPDATE FAVICON URL
+UpdateFaviconURLCommand::UpdateFaviconURLCommand(FaviconDatabasePrivate *db,
+                                                 const GURL &pageUrl,
+                                                 const GURL &faviconUrl)
+  : Command("UpdateFaviconURL", db),
+    m_pageUrl(pageUrl.spec()),
+    m_faviconUrl(faviconUrl.spec()) {
+}
+
+bool UpdateFaviconURLCommand::execute() {
+  db()->pageToFaviconUrl[GURL(m_pageUrl)] = GURL(m_faviconUrl);
+  return true;
+}
+
+bool UpdateFaviconURLCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("UPDATE %q SET %q = ? WHERE %q = ? ;",
+                                db()->pageUrlToFaviconUrlTable, db()->faviconUrlColumn,
+                                db()->pageUrlColumn);
+
+  sqlite3_stmt *stmt = 0;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  result = sqlite3_bind_text(stmt, 1, m_pageUrl.c_str(), m_pageUrl.size(), SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+  result = sqlite3_bind_text(stmt, 2, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+  return true;
+}
+
+// INSERT BITMAP
+InsertBitmapCommand::InsertBitmapCommand(FaviconDatabasePrivate *db,
+                                         const GURL &faviconUrl,
+                                         const SkBitmap &bitmap)
+  : Command("InsertBitmap", db),
+    m_faviconUrl(faviconUrl.spec()),
+    m_bitmap(bitmap) {
+}
+
+bool InsertBitmapCommand::execute() {
+  db()->faviconUrlToBitmap[GURL(m_faviconUrl)] = m_bitmap;
+  return true;
+}
+
+bool InsertBitmapCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("INSERT INTO %q VALUES (?, ?);", db()->faviconUrlToBitmapTable);
+
+  sqlite3_stmt *stmt = 0;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  result = sqlite3_bind_text(stmt, 1, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+
+  scoped_refptr<SerializedBitmap> serializedBitmap = serialize(m_bitmap);
+  if (!serializedBitmap->data) {
+    sqlite3_finalize(stmt);
+    sqlite3_free(query);
+    return false;
+  }
+
+  result = sqlite3_bind_blob(stmt, 2, serializedBitmap->data, serializedBitmap->size, SQLITE_TRANSIENT);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+  return true;
+}
+
+// UPDATE BITMAP
+UpdateBitmapCommand::UpdateBitmapCommand(FaviconDatabasePrivate *db,
+                                         const GURL &faviconUrl,
+                                         const SkBitmap &bitmap)
+  : Command("UpdateBitmap", db),
+    m_faviconUrl(faviconUrl.spec()),
+    m_bitmap(bitmap) {
+}
+
+bool UpdateBitmapCommand::execute() {
+  db()->faviconUrlToBitmap[GURL(m_faviconUrl)] = m_bitmap;
+  return true;
+}
+
+bool UpdateBitmapCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("UPDATE %q SET %q = ? WHERE %q = ? ;",
+                                db()->faviconUrlToBitmapTable, db()->bitmapColumn,
+                                db()->faviconUrlColumn);
+
+  sqlite3_stmt *stmt = 0;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  scoped_refptr<SerializedBitmap> serializedBitmap = serialize(m_bitmap);
+  if (!serializedBitmap->data) {
+    sqlite3_finalize(stmt);
+    return false;
+  }
+
+  result = sqlite3_bind_blob(stmt, 1, serializedBitmap->data, serializedBitmap->size, SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+
+  result = sqlite3_bind_text(stmt, 2, m_faviconUrl.c_str(), m_faviconUrl.size(), SQLITE_STATIC);
+  CHECK_RESULT_MSG(query, result, SQLITE_OK, stmt, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+  return true;
+}
+
+// REMOVE BITMAP
+RemoveBitmapCommand::RemoveBitmapCommand(FaviconDatabasePrivate *db, const GURL &faviconUrl)
+  : Command("RemoveBitmap", db),
+    m_faviconUrl(faviconUrl.spec()) {
+}
+
+bool RemoveBitmapCommand::execute() {
+  std::map<GURL, SkBitmap>::iterator it = db()->faviconUrlToBitmap.find(GURL(m_faviconUrl));
+  if (it != db()->faviconUrlToBitmap.end()) {
+    db()->faviconUrlToBitmap.erase(it);
+  }
+  return true;
+}
+
+bool RemoveBitmapCommand::sqlExecute() {
+  char *query = sqlite3_mprintf("DELETE FROM %q WHERE %q = ? ;", db()->faviconUrlToBitmapTable, db()->faviconUrlColumn);
+
+  sqlite3_stmt *stmt = 0;
+  int result = sqlite3_prepare_v2(db()->sqlite, query, -1, &stmt, 0);
+  CHECK_PREP_MSG(query, result, SQLITE_OK, false);
+
+  result = sqlite3_step(stmt);
+  CHECK_RESULT_MSG(query, result, SQLITE_DONE, stmt, false);
+
+  sqlite3_finalize(stmt);
+  sqlite3_free(query);
+  return true;
+}
diff --git a/tizen_src/impl/browser/favicon/favicon_commands.h b/tizen_src/impl/browser/favicon/favicon_commands.h
new file mode 100644 (file)
index 0000000..e8cda90
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef FAVICON_COMMANDS_H
+#define FAVICON_COMMANDS_H
+
+#include "url/gurl.h"
+#include "base/memory/ref_counted.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+class FaviconDatabasePrivate;
+
+struct SerializedBitmap : public base::RefCounted<SerializedBitmap> {
+  SerializedBitmap() : data(0), size(0) {}
+  ~SerializedBitmap() {
+    free();
+  }
+
+  void alloc(size_t n) {
+    free();
+    data = ::operator new(n);
+    size = n;
+  }
+
+  void free() {
+    if (data) {
+      ::operator delete(data);
+      data = 0;
+      size = 0;
+    }
+  }
+
+  void *data;
+  size_t size;
+};
+
+class Command {
+ public:
+  Command(const std::string &cmdName, FaviconDatabasePrivate *db)
+    : m_db(db), m_name(cmdName)
+  {}
+  virtual ~Command() {}
+  virtual bool execute() = 0;
+  virtual bool sqlExecute() = 0;
+  virtual std::string lastError() const;
+  std::string name() const;
+
+ protected:
+  static scoped_refptr<SerializedBitmap> serialize(const SkBitmap &bitmap);
+  static SkBitmap deserialize(const void *data);
+  static const char *sqlite3ErrStr(int rc);
+
+  FaviconDatabasePrivate *db() const {
+    return m_db;
+  }
+
+  void setError(const std::string &err);
+
+ private:
+  FaviconDatabasePrivate *m_db;
+  std::string m_name;
+  std::string m_lastError;
+};
+
+class InitDatabaseCommand : public Command {
+ public:
+  InitDatabaseCommand(FaviconDatabasePrivate *db);
+  bool execute() { return sqlExecute(); }
+  bool sqlExecute();
+};
+
+class LoadDatabaseCommand : public Command {
+ public:
+  LoadDatabaseCommand(FaviconDatabasePrivate *db);
+  bool execute() { return sqlExecute(); }
+  bool sqlExecute();
+};
+
+class ClearDatabaseCommand : public Command {
+ public:
+  ClearDatabaseCommand(FaviconDatabasePrivate *db);
+  bool execute();
+  bool sqlExecute();
+};
+
+class InsertFaviconURLCommand : public Command {
+ public:
+  InsertFaviconURLCommand(FaviconDatabasePrivate *db, const GURL &pageUrl, const GURL &faviconUrl);
+  bool execute();
+  bool sqlExecute();
+ private:
+  std::string m_pageUrl;
+  std::string m_faviconUrl;
+};
+
+class UpdateFaviconURLCommand : public Command {
+ public:
+  UpdateFaviconURLCommand(FaviconDatabasePrivate *db, const GURL &pageUrl, const GURL &faviconUrl);
+  bool execute();
+  bool sqlExecute();
+ private:
+  std::string m_pageUrl;
+  std::string m_faviconUrl;
+};
+
+class InsertBitmapCommand : public Command {
+ public:
+  InsertBitmapCommand(FaviconDatabasePrivate *db, const GURL &faviconUrl, const SkBitmap &bitmap);
+  bool execute();
+  bool sqlExecute();
+ private:
+  std::string m_faviconUrl;
+  SkBitmap m_bitmap;
+};
+
+class UpdateBitmapCommand : public Command {
+ public:
+  UpdateBitmapCommand(FaviconDatabasePrivate *db, const GURL &faviconUrl, const SkBitmap &bitmap);
+  bool execute();
+  bool sqlExecute();
+ private:
+  std::string m_faviconUrl;
+  SkBitmap m_bitmap;
+};
+
+class RemoveBitmapCommand : public Command {
+ public:
+  RemoveBitmapCommand(FaviconDatabasePrivate *db, const GURL &faviconUrl);
+  bool execute();
+  bool sqlExecute();
+ private:
+  std::string m_faviconUrl;
+};
+
+#endif // FAVICON_COMMANDS_H
diff --git a/tizen_src/impl/browser/favicon/favicon_database.cc b/tizen_src/impl/browser/favicon/favicon_database.cc
new file mode 100644 (file)
index 0000000..a70aeed
--- /dev/null
@@ -0,0 +1,223 @@
+#include "favicon_database.h"
+#include "favicon_database_p.h"
+#include "favicon_commands.h"
+#include <iostream>
+#include <cstdio>
+
+const int FaviconDatabase::SYNC_DELAY = 3;
+
+FaviconDatabase *FaviconDatabase::Instance() {
+  static FaviconDatabase database;
+  return &database;
+}
+
+FaviconDatabase::~FaviconDatabase() {
+  if (IsOpen()) {
+    Close();
+  }
+}
+
+FaviconDatabase::FaviconDatabase()
+  : d(new FaviconDatabasePrivate) {
+}
+
+bool FaviconDatabase::SetPath(const std::string &path) {
+  base::AutoLock locker(d->mutex);
+  if (d->sqlite) {
+    return false;
+  }
+  d->path = path;
+  return true;
+}
+
+bool FaviconDatabase::Open() {
+  base::AutoLock locker(d->mutex);
+  if (d->sqlite) {
+    return true;
+  }
+  int result = sqlite3_open(d->path.c_str(), &d->sqlite);
+  if (result != SQLITE_OK) {
+    fprintf(stderr, "[FaviconDatabase] :: Error opening SQLite database (%d)!\n", result);
+    return false;
+  }
+  if (!IsDatabaseInitialized()) {
+    if (!InitDatabase())
+      return false;
+  }
+  if (!LoadDatabase()) {
+    return false;
+  }
+  return true;
+}
+
+void FaviconDatabase::Close() {
+  base::AutoLock locker(d->mutex);
+  if (d->sqlite) {
+    sqlite3_close(d->sqlite);
+    d->sqlite = 0;
+  }
+}
+
+bool FaviconDatabase::IsOpen() const {
+  base::AutoLock locker(d->mutex);
+  return d->sqlite != 0;
+}
+
+void FaviconDatabase::SetPrivateBrowsingEnabled(bool enabled) {
+  base::AutoLock locker(d->mutex);
+  d->privateBrowsing = enabled;
+}
+
+bool FaviconDatabase::IsPrivateBrowsingEnabled() const {
+  base::AutoLock locker(d->mutex);
+  return d->privateBrowsing;
+}
+
+GURL FaviconDatabase::GetFaviconURLForPageURL(const GURL &pageUrl) const {
+  base::AutoLock locker(d->mutex);
+  return d->faviconUrlForPageUrl(pageUrl);
+}
+
+SkBitmap FaviconDatabase::GetBitmapForPageURL(const GURL &pageUrl) const {
+  base::AutoLock locker(d->mutex);
+  GURL faviconUrl = d->faviconUrlForPageUrl(pageUrl);
+  if (!faviconUrl.is_valid()) {
+    return SkBitmap();
+  }
+
+  return d->bitmapForFaviconUrl(faviconUrl);
+}
+
+SkBitmap FaviconDatabase::GetBitmapForFaviconURL(const GURL &iconUrl) const {
+  base::AutoLock locker(d->mutex);
+  return d->bitmapForFaviconUrl(iconUrl);
+}
+
+void FaviconDatabase::SetFaviconURLForPageURL(const GURL &iconUrl, const GURL &pageUrl) {
+  base::AutoLock locker(d->mutex);
+  if (d->privateBrowsing) {
+    return;
+  }
+  GURL &old = d->pageToFaviconUrl[pageUrl];
+  if (old == iconUrl) {
+    // nothing's gonna change, so just return
+    return;
+  }
+  if (old.is_empty()) {
+    // |old| is empty when it was just inserted by operator []
+    // so we just assign new value to it and return
+    Command *cmd = new InsertFaviconURLCommand(d, pageUrl, iconUrl);
+    cmd->execute();
+    d->commands.push(cmd);
+    ScheduleSync();
+    return;
+  }
+
+  // |old| is not empty, so we have to remove it and its bitmap
+  // from 'favicon url to bitmap'
+  Command *cmd = new RemoveBitmapCommand(d, iconUrl);
+  cmd->execute();
+  d->commands.push(cmd);
+  // and update it in 'page url to favicon url'
+  cmd = new UpdateFaviconURLCommand(d, pageUrl, iconUrl);
+  cmd->execute();
+  d->commands.push(cmd);
+
+  ScheduleSync();
+}
+
+void FaviconDatabase::SetBitmapForFaviconURL(const SkBitmap &bitmap, const GURL &iconUrl) {
+  base::AutoLock locker(d->mutex);
+  if (d->privateBrowsing) {
+    return;
+  }
+  if (d->faviconUrlToBitmap.find(iconUrl) != d->faviconUrlToBitmap.end()) {
+    Command *cmd = new UpdateBitmapCommand(d, iconUrl, bitmap);
+    cmd->execute();
+    d->commands.push(cmd);
+    ScheduleSync();
+    return;
+  }
+  Command *cmd = new InsertBitmapCommand(d, iconUrl, bitmap);
+  cmd->execute();
+  d->commands.push(cmd);
+
+  ScheduleSync();
+}
+
+bool FaviconDatabase::ExistsForPageURL(const GURL &pageUrl) const {
+  base::AutoLock locker(d->mutex);
+  std::map<GURL, GURL>::const_iterator it = d->pageToFaviconUrl.find(pageUrl);
+  if (it == d->pageToFaviconUrl.end()) {
+    return false;
+  }
+  return d->existsForFaviconURL(it->second);
+}
+
+bool FaviconDatabase::ExistsForFaviconURL(const GURL &iconUrl) const {
+  base::AutoLock locker(d->mutex);
+  return d->existsForFaviconURL(iconUrl);
+}
+
+void FaviconDatabase::Clear() {
+  Command *cmd = new ClearDatabaseCommand(d);
+  cmd->execute();
+  d->commands.push(cmd);
+
+  ScheduleSync();
+}
+
+void FaviconDatabase::SyncSQLite() {
+  scoped_refptr<base::SingleThreadTaskRunner> ptr = content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::DB);
+  ptr->PostTask(FROM_HERE, base::Bind(&FaviconDatabasePrivate::performSync, d->weakPtrFactory.GetWeakPtr()));
+}
+
+void FaviconDatabase::ScheduleSync() {
+  if (!d->timer.IsRunning()) {
+    d->timer.Start(FROM_HERE, base::TimeDelta::FromSeconds(SYNC_DELAY), this, &FaviconDatabase::SyncSQLite);
+  }
+}
+
+bool FaviconDatabase::IsDatabaseInitialized() {
+  std::string query("SELECT name FROM sqlite_master WHERE type='table' AND (name = ? OR name = ?);");
+
+  sqlite3_stmt *stmt;
+  int result = sqlite3_prepare_v2(d->sqlite, query.c_str(), query.size(), &stmt, 0);
+  if (result != SQLITE_OK) {
+    return false;
+  }
+
+  result = sqlite3_bind_text(stmt, 1, d->pageUrlToFaviconUrlTable, strlen(d->pageUrlToFaviconUrlTable), SQLITE_STATIC);
+  if (result != SQLITE_OK) {
+    sqlite3_finalize(stmt);
+    return false;
+  }
+  result = sqlite3_bind_text(stmt, 2, d->faviconUrlToBitmapTable, strlen(d->faviconUrlColumn), SQLITE_STATIC);
+  if (result != SQLITE_OK) {
+    sqlite3_finalize(stmt);
+    return false;
+  }
+
+  int count = 0;
+  while ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
+    ++count;
+  }
+
+  if (result != SQLITE_DONE || count != 2) {
+    sqlite3_finalize(stmt);
+    return false;
+  }
+
+  sqlite3_finalize(stmt);
+  return true;
+}
+
+bool FaviconDatabase::InitDatabase() {
+  InitDatabaseCommand initCmd(d);
+  return initCmd.execute();
+}
+
+bool FaviconDatabase::LoadDatabase() {
+  LoadDatabaseCommand loadCmd(d);
+  return loadCmd.execute();
+}
diff --git a/tizen_src/impl/browser/favicon/favicon_database.h b/tizen_src/impl/browser/favicon/favicon_database.h
new file mode 100644 (file)
index 0000000..81a9bd6
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef FAVICON_DATABASE_H
+#define FAVICON_DATABASE_H
+
+#include <string>
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/sqlite/sqlite3.h"
+#include "url/gurl.h"
+#include "base/memory/weak_ptr.h"
+#include "base/macros.h"
+
+struct FaviconDatabasePrivate;
+class FaviconService;
+
+// This class implements favicon database, but it should
+// not be used directly. If you want to use favicon database,
+// then FaviconService is the class you need.
+class FaviconDatabase {
+ public:
+  static FaviconDatabase *Instance();
+
+  virtual ~FaviconDatabase();
+
+  bool SetPath(const std::string &path);
+  bool Open();
+  void Close();
+  bool IsOpen() const;
+  void SetPrivateBrowsingEnabled(bool enabled);
+  bool IsPrivateBrowsingEnabled() const;
+
+  GURL GetFaviconURLForPageURL(const GURL &pageUrl) const;
+  SkBitmap GetBitmapForPageURL(const GURL &pageUrl) const;
+  SkBitmap GetBitmapForFaviconURL(const GURL &iconUrl) const;
+
+  void SetFaviconURLForPageURL(const GURL &iconUrl, const GURL &pageUrl);
+  void SetBitmapForFaviconURL(const SkBitmap &bitmap, const GURL &iconUrl);
+  bool ExistsForPageURL(const GURL &pageUrl) const;
+  bool ExistsForFaviconURL(const GURL &iconUrl) const;
+  void Clear();
+
+ private:
+  FaviconDatabase();
+  DISALLOW_COPY_AND_ASSIGN(FaviconDatabase);
+
+  void SyncSQLite();
+  void ScheduleSync();
+  bool IsDatabaseInitialized();
+  bool InitDatabase();
+  bool LoadDatabase();
+
+  scoped_refptr<FaviconDatabasePrivate> d;
+  static const int SYNC_DELAY;
+
+  friend class FaviconService;
+};
+
+#endif // FAVICON_DATABASE_H
diff --git a/tizen_src/impl/browser/favicon/favicon_database_p.cc b/tizen_src/impl/browser/favicon/favicon_database_p.cc
new file mode 100644 (file)
index 0000000..dc7cd92
--- /dev/null
@@ -0,0 +1,50 @@
+#include "favicon_database_p.h"
+#include "favicon_commands.h"
+#include <iostream>
+
+const char *FaviconDatabasePrivate::pageUrlToFaviconUrlTable = "url_to_favicon_url";
+const char *FaviconDatabasePrivate::faviconUrlToBitmapTable = "favicon_url_to_bitmap";
+const char *FaviconDatabasePrivate::pageUrlColumn = "page_url";
+const char *FaviconDatabasePrivate::faviconUrlColumn = "favicon_url";
+const char *FaviconDatabasePrivate::bitmapColumn = "bitmap";
+
+GURL FaviconDatabasePrivate::faviconUrlForPageUrl(const GURL &pageUrl) const {
+  std::map<GURL, GURL>::const_iterator it = pageToFaviconUrl.find(pageUrl);
+  if (it != pageToFaviconUrl.end()) {
+    return it->second;
+  }
+  return GURL();
+}
+
+SkBitmap FaviconDatabasePrivate::bitmapForFaviconUrl(const GURL &faviconUrl) const {
+  std::map<GURL, SkBitmap>::const_iterator it = faviconUrlToBitmap.find(faviconUrl);
+  if (it != faviconUrlToBitmap.end()) {
+
+    return it->second;
+  }
+  return SkBitmap();
+}
+
+bool FaviconDatabasePrivate::existsForFaviconURL(const GURL &faviconUrl) const {
+  std::map<GURL, SkBitmap>::const_iterator it = faviconUrlToBitmap.find(faviconUrl);
+  return it != faviconUrlToBitmap.end();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> FaviconDatabasePrivate::taskRunner() const {
+  return content::BrowserThread::GetMessageLoopProxyForThread(content::BrowserThread::DB);
+}
+
+void FaviconDatabasePrivate::performSync() {
+  std::cerr << "[FaviconDatabasePrivate::performSync()]" << std::endl;
+  base::AutoLock locker(mutex);
+  timer.Stop();
+  while (!commands.empty()) {
+    Command *cmd = commands.front();
+    if (!cmd->sqlExecute()) {
+      std::cerr << "[FaviconDatabasePrivate::performSync] :: " << "Error while executing command:\n\t" << cmd->lastError() << std::endl;
+      // abort or what?
+    }
+    commands.pop();
+    delete cmd;
+  }
+}
diff --git a/tizen_src/impl/browser/favicon/favicon_database_p.h b/tizen_src/impl/browser/favicon/favicon_database_p.h
new file mode 100644 (file)
index 0000000..1dd213b
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef FAVICON_DATABASE_P_H
+#define FAVICON_DATABASE_P_H
+
+#include <map>
+#include <queue>
+#include "url/gurl.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/sqlite/sqlite3.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/timer/timer.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/browser_thread.h"
+#include "favicon_database.h"
+
+class Command;
+
+struct FaviconDatabasePrivate : public base::RefCountedThreadSafe<FaviconDatabasePrivate> {
+  FaviconDatabasePrivate()
+    : path("/tmp/favicon_database.db"),
+      privateBrowsing(false),
+      sqlite(0),
+      weakPtrFactory(this)
+  {}
+
+  GURL faviconUrlForPageUrl(const GURL &pageUrl) const;
+  SkBitmap bitmapForFaviconUrl(const GURL &faviconUrl) const;
+
+  bool existsForFaviconURL(const GURL &faviconUrl) const;
+
+  scoped_refptr<base::SingleThreadTaskRunner> taskRunner() const;
+  void performSync();
+
+  std::map<GURL, GURL> pageToFaviconUrl;
+  std::map<GURL, SkBitmap> faviconUrlToBitmap;
+  std::string path;
+  bool privateBrowsing;
+
+  sqlite3 *sqlite;
+  base::Lock mutex;
+  base::RepeatingTimer<FaviconDatabase> timer;
+  std::queue<Command *> commands;
+  base::WeakPtrFactory<FaviconDatabasePrivate> weakPtrFactory;
+
+  static const char *pageUrlToFaviconUrlTable;
+  static const char *faviconUrlToBitmapTable;
+  static const char *pageUrlColumn;
+  static const char *faviconUrlColumn;
+  static const char *bitmapColumn;
+};
+
+#endif // FAVICON_DATABASE_P_H
diff --git a/tizen_src/impl/browser/favicon/favicon_downloader.cc b/tizen_src/impl/browser/favicon/favicon_downloader.cc
new file mode 100644 (file)
index 0000000..5786443
--- /dev/null
@@ -0,0 +1,37 @@
+#include "favicon_downloader.h"
+#include "base/bind.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+FaviconDownloader::FaviconDownloader(content::WebContents *webContents,
+                                     const GURL &faviconUrl,
+                                     FaviconDownloader::FaviconDownloaderCallback callback)
+  : content::WebContentsObserver(webContents),
+    m_faviconUrl(faviconUrl),
+    m_callback(callback),
+    m_weakPtrFactory(this) {
+}
+
+void FaviconDownloader::Start() {
+  DownloadFavicon(m_faviconUrl);
+}
+
+int FaviconDownloader::DownloadFavicon(const GURL &faviconUrl) {
+  return web_contents()->DownloadImage(faviconUrl,
+                                       true,
+                                       0,
+                                       base::Bind(&FaviconDownloader::DidDownloadFavicon,
+                                                  m_weakPtrFactory.GetWeakPtr()));
+}
+
+void FaviconDownloader::DidDownloadFavicon(int id,
+                                           int httpStatusCode,
+                                           const GURL &imageUrl,
+                                           const std::vector<SkBitmap> &bitmaps,
+                                           const std::vector<gfx::Size> &originalBitmapSizes) {
+  if (bitmaps.empty()) {
+    m_callback.Run(false, GURL(), SkBitmap());
+    return;
+  }
+  m_callback.Run(true, imageUrl, bitmaps.front());
+}
diff --git a/tizen_src/impl/browser/favicon/favicon_downloader.h b/tizen_src/impl/browser/favicon/favicon_downloader.h
new file mode 100644 (file)
index 0000000..8f6ef90
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef FAVICON_DOWNLOADER_H
+#define FAVICON_DOWNLOADER_H
+
+#include "content/public/browser/web_contents_observer.h"
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+
+class SkBitmap;
+
+namespace gfx {
+class Size;
+}
+
+// Class used for downloading favicons
+class FaviconDownloader : public content::WebContentsObserver {
+ public:
+  typedef base::Callback<void(
+          bool success,
+          const GURL &faviconUrl,
+          const SkBitmap &bitmap)>
+      FaviconDownloaderCallback;
+  FaviconDownloader(content::WebContents *webContents,
+                    const GURL &faviconUrl,
+                    FaviconDownloaderCallback callback);
+  virtual ~FaviconDownloader() {}
+
+  void Start();
+
+ private:
+  int DownloadFavicon(const GURL &faviconUrl);
+  // DownloadImage callback
+  void DidDownloadFavicon(int id,
+                          int httpStatusCode,
+                          const GURL &imageUrl,
+                          const std::vector<SkBitmap> &bitmaps,
+                          const std::vector<gfx::Size> &originalBitmapSizes);
+
+  GURL m_faviconUrl;
+  FaviconDownloaderCallback m_callback;
+  base::WeakPtrFactory<FaviconDownloader> m_weakPtrFactory;
+  DISALLOW_COPY_AND_ASSIGN(FaviconDownloader);
+};
+
+#endif // FAVICON_DOWNLOADER_H
diff --git a/tizen_src/impl/browser/favicon/favicon_service.cc b/tizen_src/impl/browser/favicon/favicon_service.cc
new file mode 100644 (file)
index 0000000..4eebc39
--- /dev/null
@@ -0,0 +1,68 @@
+#include "browser/favicon/favicon_service.h"
+#include "browser/favicon/favicon_database.h"
+#include "browser/favicon/favicon_database_p.h"
+#include "base/synchronization/lock.h"
+
+#define CHECK_OPEN if (!m_database->Open()) {\
+                     return;\
+                   }
+
+#define CHECK_OPEN_RET(ret) if (!m_database->Open()) {\
+                          return ret;\
+                        }
+
+FaviconService::FaviconService()
+  : m_database(FaviconDatabase::Instance()) {
+}
+
+bool FaviconService::SetDatabasePath(const std::string& path) {
+  return m_database->SetPath(path);
+}
+
+void FaviconService::SetPrivateBrowsingEnabled(bool enabled) {
+  m_database->SetPrivateBrowsingEnabled(enabled);
+}
+
+bool FaviconService::IsPrivateBrowsingEnabled() const {
+  return m_database->IsPrivateBrowsingEnabled();
+}
+
+GURL FaviconService::GetFaviconURLForPageURL(const GURL& pageUrl) const {
+  CHECK_OPEN_RET(GURL());
+  return m_database->GetFaviconURLForPageURL(pageUrl);
+}
+
+SkBitmap FaviconService::GetBitmapForPageURL(const GURL& pageUrl) const {
+  CHECK_OPEN_RET(SkBitmap());
+  return m_database->GetBitmapForPageURL(pageUrl);
+}
+
+SkBitmap FaviconService::GetBitmapForFaviconURL(const GURL& iconUrl) const {
+  CHECK_OPEN_RET(SkBitmap());
+  return m_database->GetBitmapForFaviconURL(iconUrl);
+}
+
+void FaviconService::SetFaviconURLForPageURL(const GURL& iconUrl, const GURL& pageUrl) {
+  CHECK_OPEN;
+  m_database->SetFaviconURLForPageURL(iconUrl, pageUrl);
+}
+
+void FaviconService::SetBitmapForFaviconURL(const SkBitmap& bitmap, const GURL& iconUrl) {
+  CHECK_OPEN;
+  m_database->SetBitmapForFaviconURL(bitmap, iconUrl);
+}
+
+bool FaviconService::ExistsForPageURL(const GURL& pageUrl) const {
+  CHECK_OPEN_RET(false);
+  return m_database->ExistsForPageURL(pageUrl);
+}
+
+bool FaviconService::ExistsForFaviconURL(const GURL& iconUrl) const {
+  CHECK_OPEN_RET(false);
+  return m_database->ExistsForFaviconURL(iconUrl);
+}
+
+void FaviconService::Clear() {
+  CHECK_OPEN;
+  m_database->Clear();
+}
diff --git a/tizen_src/impl/browser/favicon/favicon_service.h b/tizen_src/impl/browser/favicon/favicon_service.h
new file mode 100644 (file)
index 0000000..5a22241
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef FAVICON_SERVICE_H
+#define FAVICON_SERVICE_H
+
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "url/gurl.h"
+
+class FaviconDatabase;
+
+// Use this class to store and retrieve icons in/from
+// favicon database.
+// It's methods can hang on mutex.
+class FaviconService {
+ public:
+  FaviconService();
+
+  bool SetDatabasePath(const std::string &path);
+  void SetPrivateBrowsingEnabled(bool enabled);
+  bool IsPrivateBrowsingEnabled() const;
+
+  GURL GetFaviconURLForPageURL(const GURL &pageUrl) const;
+  SkBitmap GetBitmapForPageURL(const GURL &pageUrl) const;
+  SkBitmap GetBitmapForFaviconURL(const GURL &iconUrl) const;
+
+  void SetFaviconURLForPageURL(const GURL &iconUrl, const GURL &pageUrl);
+  void SetBitmapForFaviconURL(const SkBitmap &bitmap, const GURL &iconUrl);
+
+  bool ExistsForPageURL(const GURL &pageUrl) const;
+  bool ExistsForFaviconURL(const GURL &iconUrl) const;
+  void Clear();
+
+ private:
+  FaviconDatabase *m_database;
+};
+
+#endif // FAVICON_SERVICE_H
index 8a1468b..741cc4d 100755 (executable)
       'browser/device_sensors/data_fetcher_shared_memory_tizen.cc',
       'browser/download_manager_delegate_efl.cc',
       'browser/download_manager_delegate_efl.h',
+      'browser/favicon/favicon_commands.cc',
+      'browser/favicon/favicon_commands.h',
+      'browser/favicon/favicon_database.cc',
+      'browser/favicon/favicon_database.h',
+      'browser/favicon/favicon_database_p.cc',
+      'browser/favicon/favicon_database_p.h',
+      'browser/favicon/favicon_downloader.cc',
+      'browser/favicon/favicon_downloader.h',
+      'browser/favicon/favicon_service.cc',
+      'browser/favicon/favicon_service.h',
       'browser/geolocation/access_token_store_efl.cc',
       'browser/geolocation/access_token_store_efl.h',
       # [M37] Geolocation related code changed. Figure out how to fix it.
index 68faf13..b49fb0b 100644 (file)
@@ -27,6 +27,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/local_storage_usage_info.h"
 #include "content/public/browser/dom_storage_context.h"
+#include "browser/favicon/favicon_service.h"
 #include "net/http/http_cache.h"
 #include "net/proxy/proxy_config_service_fixed.h"
 #include "net/proxy/proxy_service.h"
@@ -459,5 +460,28 @@ void EWebContext::GetAllOriginsWithFileSystem(Ewk_Local_File_System_Origins_Get_
   BrowserThread::PostTask(
       BrowserThread::FILE,
       FROM_HERE,
-      base::Bind(&GetFileSystemOriginsOnFILEThread, callback, user_data, partition));
+        base::Bind(&GetFileSystemOriginsOnFILEThread, callback, user_data, partition));
+}
+
+bool EWebContext::SetFaviconDatabasePath(const char* path) {
+  FaviconService fs;
+  return fs.SetDatabasePath(path);
+}
+
+Evas_Object *EWebContext::AddFaviconObject(const char* uri, Evas* canvas) const {
+  if (uri == NULL || canvas == NULL) {
+    return NULL;
+  }
+  FaviconService fs;
+  SkBitmap bitmap = fs.GetBitmapForPageURL(GURL(uri));
+  if (bitmap.isNull()) {
+    return NULL;
+  }
+
+  Evas_Object *favicon = evas_object_image_filled_add(canvas);
+  evas_object_image_size_set(favicon, bitmap.width(), bitmap.height());
+  evas_object_image_colorspace_set(favicon, EVAS_COLORSPACE_ARGB8888);
+  bitmap.copyPixelsTo(evas_object_image_data_get(favicon, EINA_TRUE), bitmap.getSize());
+
+  return favicon;
 }
index ea53b28..3de2974 100644 (file)
@@ -98,6 +98,8 @@ class EWebContext : public EWebObject {
   void WebStorageOriginsAllGet(Ewk_Web_Storage_Origins_Get_Callback callback, void* user_data);
   void FileSystemDelete(const GURL& host);
   void GetAllOriginsWithFileSystem(Ewk_Local_File_System_Origins_Get_Callback callback, void* user_data) const;
+  bool SetFaviconDatabasePath(const char* path);
+  Evas_Object *AddFaviconObject(const char* uri, Evas* canvas) const;
 
   void SendWidgetInfo(int widget_id, double scale, const std::string &theme, const std::string &encoded_bundle);
   void SendWrtMessage(const Ewk_IPC_Wrt_Message_Data& message);
index 72cf207..a85c361 100644 (file)
@@ -119,7 +119,8 @@ enum CallbackType {
   MagnifierHide,
   ClipboardOpened,
   ConsoleMessage,
-  WrtPluginsMessage
+  WrtPluginsMessage,
+  IconReceived
 };
 
 template <CallbackType>
@@ -271,6 +272,7 @@ DECLARE_EWK_VIEW_CALLBACK(BackForwardListChange, "back,forward,list,changed", vo
 DECLARE_EWK_VIEW_CALLBACK(WebProcessCrashed, "webprocess,crashed", bool*);
 DECLARE_EWK_VIEW_CALLBACK(ConsoleMessage, "console,message", _Ewk_Console_Message*);
 DECLARE_EWK_VIEW_CALLBACK(WrtPluginsMessage, "wrt,message", Ewk_IPC_Wrt_Message_Data*);
+DECLARE_EWK_VIEW_CALLBACK(IconReceived, "icon,received", void);
 }
 
 #endif
index df426a2..57b22ef 100755 (executable)
 #include "content/common/view_messages.h"
 #include "content/public/browser/invalidate_type.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/common/favicon_url.h"
 #include "net/base/load_states.h"
 #include "net/http/http_response_headers.h"
 #include "printing/pdf_metafile_skia.h"
 #include "url/gurl.h"
+#include "browser/favicon/favicon_service.h"
 
 using base::string16;
 
@@ -40,7 +44,8 @@ WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* view)
     : web_view_(view),
       document_created_(false),
       should_open_new_window_(true),
-      forward_backward_list_count_(0) {
+      forward_backward_list_count_(0),
+      weak_ptr_factory_(this) {
   BrowserContext* browser_context = web_view_->context()->browser_context();
   web_contents_.reset(WebContents::Create(WebContents::CreateParams(browser_context)));
   web_contents_->SetDelegate(this);
@@ -53,7 +58,8 @@ WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* view, WebContents* cont
     web_contents_(contents),
     document_created_(false),
     should_open_new_window_(true),
-    forward_backward_list_count_(0) {
+    forward_backward_list_count_(0),
+    weak_ptr_factory_(this) {
   web_contents_->SetDelegate(this);
 }
 
@@ -240,6 +246,25 @@ void WebContentsDelegateEfl::DidFinishLoad(int64 frame_id,
   if (!is_main_frame)
     return;
 
+  NavigationEntry *entry = web_contents()->GetController().GetActiveEntry();
+  FaviconStatus &favicon = entry->GetFavicon();
+
+  // check/update the url and favicon url in favicon database
+  FaviconService fs;
+  fs.SetFaviconURLForPageURL(favicon.url, validated_url);
+
+  // download favicon if there is no such in database
+  if (!fs.ExistsForFaviconURL(favicon.url)) {
+    fprintf(stderr, "[DidFinishLoad] :: no favicon in database for URL: %s\n", favicon.url.spec().c_str());
+    favicon_downloader_.reset(new FaviconDownloader(web_contents(),
+                                                   favicon.url,
+                                                   base::Bind(&WebContentsDelegateEfl::DidDownloadFavicon,
+                                                              weak_ptr_factory_.GetWeakPtr())));
+    favicon_downloader_->Start();
+  } else {
+    web_view_->SmartCallback<EWebViewCallbacks::IconReceived>().call();
+  }
+
   web_view_->SmartCallback<EWebViewCallbacks::LoadFinished>().call();
 }
 
@@ -247,6 +272,32 @@ void WebContentsDelegateEfl::DidStartLoading(RenderViewHost* render_view_host) {
   web_view_->SmartCallback<EWebViewCallbacks::LoadStarted>().call();
 }
 
+void WebContentsDelegateEfl::DidUpdateFaviconURL(int32 page_id, const std::vector<FaviconURL>& candidates) {
+  // select and set proper favicon
+  for (unsigned int i = 0; i < candidates.size(); ++i) {
+    FaviconURL favicon = candidates[i];
+    if (favicon.icon_type == FaviconURL::FAVICON && !favicon.icon_url.is_empty()) {
+      NavigationEntry *entry = web_contents_->GetController().GetActiveEntry();
+      if (!entry)
+        return;
+      entry->GetFavicon().url = favicon.icon_url;
+      entry->GetFavicon().valid = true;
+      return;
+    }
+  }
+  return;
+}
+
+void WebContentsDelegateEfl::DidDownloadFavicon(bool success, const GURL& icon_url, const SkBitmap& bitmap) {
+  favicon_downloader_.reset();
+  if (success) {
+    FaviconService fs;
+    fs.SetBitmapForFaviconURL(bitmap, icon_url);
+    // emit "icon,received"
+    web_view_->SmartCallback<EWebViewCallbacks::IconReceived>().call();
+  }
+}
+
 void WebContentsDelegateEfl::RequestCertificateConfirm(WebContents* /*web_contents*/,
                                                       int cert_error,
                                                       const net::SSLInfo& ssl_info,
index a67bad3..71f55c7 100755 (executable)
@@ -2,6 +2,7 @@
 #define WEB_CONTENTS_DELEGATE_EFL
 
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "content/public/browser/browser_context.h"
 #include "browser/javascript_dialog_manager_efl.h"
 #include "browser_context_efl.h"
@@ -15,6 +16,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "url/gurl.h"
+#include "browser/favicon/favicon_downloader.h"
 
 class PolicyResponseDelegateEfl;
 class DidPrintPagesParams;
@@ -123,6 +125,9 @@ class WebContentsDelegateEfl
                              RenderViewHost* render_view_host) OVERRIDE;
 
   virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE;
+  virtual void DidUpdateFaviconURL(int32 page_id,
+                                   const std::vector<FaviconURL>& candidates) OVERRIDE;
+  virtual void DidDownloadFavicon(bool success, const GURL& icon_url, const SkBitmap& bitmap);
 
   void SetContentSecurityPolicy(const std::string& policy, Ewk_CSP_Header_Type header_type);
   void OnHeadersReceived(PolicyResponseDelegateEfl* delegate,
@@ -172,6 +177,8 @@ class WebContentsDelegateEfl
   bool should_open_new_window_;
   scoped_ptr<JavaScriptDialogManagerEfl> dialog_manager_;
   int forward_backward_list_count_;
+  scoped_ptr<FaviconDownloader> favicon_downloader_;
+  base::WeakPtrFactory<WebContentsDelegateEfl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(WebContentsDelegateEfl);
 };