WebKitFaviconDatabase.cpp [plain text]
#include "config.h"
#include "WebKitFaviconDatabase.h"
#include "IconDatabase.h"
#include "WebKitFaviconDatabasePrivate.h"
#include <WebCore/Image.h>
#include <WebCore/IntSize.h>
#include <WebCore/RefPtrCairo.h>
#include <WebCore/SharedBuffer.h>
#include <glib/gi18n-lib.h>
#include <wtf/FileSystem.h>
#include <wtf/RunLoop.h>
#include <wtf/glib/GRefPtr.h>
#include <wtf/glib/GUniquePtr.h>
#include <wtf/glib/WTFGType.h>
#include <wtf/text/CString.h>
using namespace WebKit;
using namespace WebCore;
enum {
FAVICON_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
struct _WebKitFaviconDatabasePrivate {
RefPtr<IconDatabase> iconDatabase;
};
WEBKIT_DEFINE_TYPE(WebKitFaviconDatabase, webkit_favicon_database, G_TYPE_OBJECT)
static void webkit_favicon_database_class_init(WebKitFaviconDatabaseClass* faviconDatabaseClass)
{
signals[FAVICON_CHANGED] = g_signal_new(
"favicon-changed",
G_TYPE_FROM_CLASS(faviconDatabaseClass),
G_SIGNAL_RUN_LAST,
0, nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
G_TYPE_STRING,
G_TYPE_STRING);
}
WebKitFaviconDatabase* webkitFaviconDatabaseCreate()
{
return WEBKIT_FAVICON_DATABASE(g_object_new(WEBKIT_TYPE_FAVICON_DATABASE, nullptr));
}
static bool webkitFaviconDatabaseIsOpen(WebKitFaviconDatabase* database)
{
return !!database->priv->iconDatabase;
}
void webkitFaviconDatabaseOpen(WebKitFaviconDatabase* database, const String& path, bool isEphemeral)
{
if (webkitFaviconDatabaseIsOpen(database))
return;
database->priv->iconDatabase = IconDatabase::create(path, isEphemeral ? IconDatabase::AllowDatabaseWrite::No : IconDatabase::AllowDatabaseWrite::Yes);
}
void webkitFaviconDatabaseClose(WebKitFaviconDatabase* database)
{
database->priv->iconDatabase = nullptr;
}
#if PLATFORM(GTK)
void webkitFaviconDatabaseGetLoadDecisionForIcon(WebKitFaviconDatabase* database, const LinkIcon& icon, const String& pageURL, bool isEphemeral, Function<void(bool)>&& completionHandler)
{
if (!webkitFaviconDatabaseIsOpen(database)) {
completionHandler(false);
return;
}
database->priv->iconDatabase->checkIconURLAndSetPageURLIfNeeded(icon.url.string(), pageURL,
isEphemeral ? IconDatabase::AllowDatabaseWrite::No : IconDatabase::AllowDatabaseWrite::Yes,
[database = GRefPtr<WebKitFaviconDatabase>(database), url = icon.url.string().isolatedCopy(), pageURL = pageURL.isolatedCopy(), completionHandler = WTFMove(completionHandler)](bool found, bool changed) {
if (!webkitFaviconDatabaseIsOpen(database.get()))
return;
if (found && changed)
g_signal_emit(database.get(), signals[FAVICON_CHANGED], 0, pageURL.utf8().data(), url.utf8().data());
completionHandler(!found);
});
}
void webkitFaviconDatabaseSetIconForPageURL(WebKitFaviconDatabase* database, const LinkIcon& icon, API::Data& iconData, const String& pageURL, bool isEphemeral)
{
if (!webkitFaviconDatabaseIsOpen(database))
return;
database->priv->iconDatabase->setIconForPageURL(icon.url.string(), iconData.bytes(), iconData.size(), pageURL,
isEphemeral ? IconDatabase::AllowDatabaseWrite::No : IconDatabase::AllowDatabaseWrite::Yes,
[database = GRefPtr<WebKitFaviconDatabase>(database), url = icon.url.string().isolatedCopy(), pageURL = pageURL.isolatedCopy()](bool success) {
if (!webkitFaviconDatabaseIsOpen(database.get()) || !success)
return;
g_signal_emit(database.get(), signals[FAVICON_CHANGED], 0, pageURL.utf8().data(), url.utf8().data());
});
}
#endif
GQuark webkit_favicon_database_error_quark(void)
{
return g_quark_from_static_string("WebKitFaviconDatabaseError");
}
#if PLATFORM(GTK)
void webkitFaviconDatabaseGetFaviconInternal(WebKitFaviconDatabase* database, const gchar* pageURI, bool isEphemeral, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
if (!webkitFaviconDatabaseIsOpen(database)) {
g_task_report_new_error(database, callback, userData, 0,
WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED, _("Favicons database not initialized yet"));
return;
}
if (g_str_has_prefix(pageURI, "about:")) {
g_task_report_new_error(database, callback, userData, 0,
WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND, _("Page %s does not have a favicon"), pageURI);
return;
}
GRefPtr<GTask> task = adoptGRef(g_task_new(database, cancellable, callback, userData));
WebKitFaviconDatabasePrivate* priv = database->priv;
priv->iconDatabase->loadIconForPageURL(String::fromUTF8(pageURI), isEphemeral ? IconDatabase::AllowDatabaseWrite::No : IconDatabase::AllowDatabaseWrite::Yes,
[task = WTFMove(task), pageURI = CString(pageURI)](RefPtr<cairo_surface_t>&& icon) {
if (!icon) {
g_task_return_new_error(task.get(), WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN,
_("Unknown favicon for page %s"), pageURI.data());
return;
}
g_task_return_pointer(task.get(), icon.leakRef(), reinterpret_cast<GDestroyNotify>(cairo_surface_destroy));
});
}
void webkit_favicon_database_get_favicon(WebKitFaviconDatabase* database, const gchar* pageURI, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
{
g_return_if_fail(WEBKIT_IS_FAVICON_DATABASE(database));
g_return_if_fail(pageURI);
webkitFaviconDatabaseGetFaviconInternal(database, pageURI, false, cancellable, callback, userData);
}
cairo_surface_t* webkit_favicon_database_get_favicon_finish(WebKitFaviconDatabase* database, GAsyncResult* result, GError** error)
{
g_return_val_if_fail(WEBKIT_IS_FAVICON_DATABASE(database), 0);
g_return_val_if_fail(g_task_is_valid(result, database), 0);
GTask* task = G_TASK(result);
if (auto* icon = g_task_propagate_pointer(task, error))
return static_cast<cairo_surface_t*>(icon);
return nullptr;
}
#endif
gchar* webkit_favicon_database_get_favicon_uri(WebKitFaviconDatabase* database, const gchar* pageURL)
{
g_return_val_if_fail(WEBKIT_IS_FAVICON_DATABASE(database), nullptr);
g_return_val_if_fail(pageURL, nullptr);
ASSERT(RunLoop::isMain());
if (!webkitFaviconDatabaseIsOpen(database))
return nullptr;
String iconURLForPageURL = database->priv->iconDatabase->iconURLForPageURL(String::fromUTF8(pageURL));
if (iconURLForPageURL.isEmpty())
return nullptr;
return g_strdup(iconURLForPageURL.utf8().data());
}
void webkit_favicon_database_clear(WebKitFaviconDatabase* database)
{
g_return_if_fail(WEBKIT_IS_FAVICON_DATABASE(database));
if (!webkitFaviconDatabaseIsOpen(database))
return;
database->priv->iconDatabase->clear([] { });
}