From d98dbbc10ff4f7b875f45fc34dba42b9e0fc01c9 Mon Sep 17 00:00:00 2001 From: Filip Piechocki Date: Fri, 16 May 2014 12:56:49 +0200 Subject: [PATCH] Implementn FaviconDatabase. 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 --- tizen_src/impl/browser/favicon/favicon_commands.cc | 404 +++++++++++++++++++++ tizen_src/impl/browser/favicon/favicon_commands.h | 132 +++++++ tizen_src/impl/browser/favicon/favicon_database.cc | 223 ++++++++++++ tizen_src/impl/browser/favicon/favicon_database.h | 56 +++ .../impl/browser/favicon/favicon_database_p.cc | 50 +++ .../impl/browser/favicon/favicon_database_p.h | 52 +++ .../impl/browser/favicon/favicon_downloader.cc | 37 ++ .../impl/browser/favicon/favicon_downloader.h | 44 +++ tizen_src/impl/browser/favicon/favicon_service.cc | 68 ++++ tizen_src/impl/browser/favicon/favicon_service.h | 35 ++ tizen_src/impl/chromium-efl.gyp | 10 + tizen_src/impl/eweb_context.cc | 26 +- tizen_src/impl/eweb_context.h | 2 + tizen_src/impl/eweb_view_callbacks.h | 4 +- tizen_src/impl/web_contents_delegate_efl.cc | 55 ++- tizen_src/impl/web_contents_delegate_efl.h | 7 + 16 files changed, 1201 insertions(+), 4 deletions(-) create mode 100644 tizen_src/impl/browser/favicon/favicon_commands.cc create mode 100644 tizen_src/impl/browser/favicon/favicon_commands.h create mode 100644 tizen_src/impl/browser/favicon/favicon_database.cc create mode 100644 tizen_src/impl/browser/favicon/favicon_database.h create mode 100644 tizen_src/impl/browser/favicon/favicon_database_p.cc create mode 100644 tizen_src/impl/browser/favicon/favicon_database_p.h create mode 100644 tizen_src/impl/browser/favicon/favicon_downloader.cc create mode 100644 tizen_src/impl/browser/favicon/favicon_downloader.h create mode 100644 tizen_src/impl/browser/favicon/favicon_service.cc create mode 100644 tizen_src/impl/browser/favicon/favicon_service.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 index 0000000..4c975c7 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_commands.cc @@ -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 + +#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 Command::serialize(const SkBitmap &bitmap) { + scoped_refptr res(new SerializedBitmap); + if (bitmap.isNull()) { + return res; + } + res->alloc(bitmap.getSize() + 3 * sizeof(int)); + static_cast(res->data)[0] = static_cast(bitmap.config()); + static_cast(res->data)[1] = bitmap.width(); + static_cast(res->data)[2] = bitmap.height(); + if (!bitmap.copyPixelsTo(static_cast(res->data) + 3, bitmap.getSize())) { + res->free(); + } + return res; +} + +SkBitmap Command::deserialize(const void *data) { + if (!data) { + return SkBitmap(); + } + + SkBitmap::Config config = static_cast(static_cast(data)[0]); + int width = static_cast(data)[1]; + int height = static_cast(data)[2]; + SkBitmap bitmap; + bitmap.setConfig(config, width, height); + bitmap.setPixels(static_cast(const_cast(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(©, 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(sqlite3_column_text(stmt, 0))); + GURL faviconUrl(reinterpret_cast(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(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 = 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 = 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::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 index 0000000..e8cda90 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_commands.h @@ -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() : 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 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 index 0000000..a70aeed --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_database.cc @@ -0,0 +1,223 @@ +#include "favicon_database.h" +#include "favicon_database_p.h" +#include "favicon_commands.h" +#include +#include + +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::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 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 index 0000000..81a9bd6 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_database.h @@ -0,0 +1,56 @@ +#ifndef FAVICON_DATABASE_H +#define FAVICON_DATABASE_H + +#include +#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 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 index 0000000..dc7cd92 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_database_p.cc @@ -0,0 +1,50 @@ +#include "favicon_database_p.h" +#include "favicon_commands.h" +#include + +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::const_iterator it = pageToFaviconUrl.find(pageUrl); + if (it != pageToFaviconUrl.end()) { + return it->second; + } + return GURL(); +} + +SkBitmap FaviconDatabasePrivate::bitmapForFaviconUrl(const GURL &faviconUrl) const { + std::map::const_iterator it = faviconUrlToBitmap.find(faviconUrl); + if (it != faviconUrlToBitmap.end()) { + + return it->second; + } + return SkBitmap(); +} + +bool FaviconDatabasePrivate::existsForFaviconURL(const GURL &faviconUrl) const { + std::map::const_iterator it = faviconUrlToBitmap.find(faviconUrl); + return it != faviconUrlToBitmap.end(); +} + +scoped_refptr 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 index 0000000..1dd213b --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_database_p.h @@ -0,0 +1,52 @@ +#ifndef FAVICON_DATABASE_P_H +#define FAVICON_DATABASE_P_H + +#include +#include +#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() + : 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 taskRunner() const; + void performSync(); + + std::map pageToFaviconUrl; + std::map faviconUrlToBitmap; + std::string path; + bool privateBrowsing; + + sqlite3 *sqlite; + base::Lock mutex; + base::RepeatingTimer timer; + std::queue commands; + base::WeakPtrFactory 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 index 0000000..5786443 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_downloader.cc @@ -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 &bitmaps, + const std::vector &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 index 0000000..8f6ef90 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_downloader.h @@ -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 + 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 &bitmaps, + const std::vector &originalBitmapSizes); + + GURL m_faviconUrl; + FaviconDownloaderCallback m_callback; + base::WeakPtrFactory 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 index 0000000..4eebc39 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_service.cc @@ -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 index 0000000..5a22241 --- /dev/null +++ b/tizen_src/impl/browser/favicon/favicon_service.h @@ -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 diff --git a/tizen_src/impl/chromium-efl.gyp b/tizen_src/impl/chromium-efl.gyp index 8a1468b..741cc4d 100755 --- a/tizen_src/impl/chromium-efl.gyp +++ b/tizen_src/impl/chromium-efl.gyp @@ -70,6 +70,16 @@ '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. diff --git a/tizen_src/impl/eweb_context.cc b/tizen_src/impl/eweb_context.cc index 68faf13..b49fb0b 100644 --- a/tizen_src/impl/eweb_context.cc +++ b/tizen_src/impl/eweb_context.cc @@ -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; } diff --git a/tizen_src/impl/eweb_context.h b/tizen_src/impl/eweb_context.h index ea53b28..3de2974 100644 --- a/tizen_src/impl/eweb_context.h +++ b/tizen_src/impl/eweb_context.h @@ -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); diff --git a/tizen_src/impl/eweb_view_callbacks.h b/tizen_src/impl/eweb_view_callbacks.h index 72cf207..a85c361 100644 --- a/tizen_src/impl/eweb_view_callbacks.h +++ b/tizen_src/impl/eweb_view_callbacks.h @@ -119,7 +119,8 @@ enum CallbackType { MagnifierHide, ClipboardOpened, ConsoleMessage, - WrtPluginsMessage + WrtPluginsMessage, + IconReceived }; template @@ -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 diff --git a/tizen_src/impl/web_contents_delegate_efl.cc b/tizen_src/impl/web_contents_delegate_efl.cc index df426a2..57b22ef 100755 --- a/tizen_src/impl/web_contents_delegate_efl.cc +++ b/tizen_src/impl/web_contents_delegate_efl.cc @@ -20,10 +20,14 @@ #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().call(); + } + web_view_->SmartCallback().call(); } @@ -247,6 +272,32 @@ void WebContentsDelegateEfl::DidStartLoading(RenderViewHost* render_view_host) { web_view_->SmartCallback().call(); } +void WebContentsDelegateEfl::DidUpdateFaviconURL(int32 page_id, const std::vector& 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().call(); + } +} + void WebContentsDelegateEfl::RequestCertificateConfirm(WebContents* /*web_contents*/, int cert_error, const net::SSLInfo& ssl_info, diff --git a/tizen_src/impl/web_contents_delegate_efl.h b/tizen_src/impl/web_contents_delegate_efl.h index a67bad3..71f55c7 100755 --- a/tizen_src/impl/web_contents_delegate_efl.h +++ b/tizen_src/impl/web_contents_delegate_efl.h @@ -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& 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 dialog_manager_; int forward_backward_list_count_; + scoped_ptr favicon_downloader_; + base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(WebContentsDelegateEfl); }; -- 2.7.4