Skip to content
Permalink
Browse files
[WK2][GTK] Add API to get the favicon for a WebKitWebView
https://bugs.webkit.org/show_bug.cgi?id=96477

Reviewed by Carlos Garcia Campos.

Provide a new simple API to synchronously try to get the favicon
associated with a WebView, if any, and to keep track of changes on
it, through a new GObject property.

* UIProcess/API/gtk/WebKitWebView.cpp:
(_WebKitWebViewPrivate):
(webkitWebViewIconReadyCallback): Callback to handle the
'icon-ready' signal coming from WebKitFaviconDatabase.
(webkitWebViewWatchForChangesInFavicon): Connects to the
'icon-ready' signal from WebKitFaviconDatabase, to keep track of
changes in favicons, that must be related to the current view.
(webkitWebViewDisconnectFaviconDatabaseSignalHandlers):
Disconnects the handler for 'icon-ready' if needed.
(webkitWebViewGetProperty): Updated for the new "favicon" property .
(webkitWebViewFinalize): Disconnect the new signal handler.
(webkit_web_view_class_init): Definition of the new property.
(webkitWebViewEmitLoadChanged): Make sure we will be watching for
changes in the favicon from WEBKIT_LOAD_STARTED on.
(webkit_web_view_get_favicon): New API funtcion, returning the
current favicon for the WebView, if any, or NULL otherwise.
* UIProcess/API/gtk/WebKitWebView.h:

Internally expose a way to try to get the favicon associated to a
page URL synchronously, through WebKitFaviconDatabase.

* UIProcess/API/gtk/WebKitFaviconDatabase.cpp:
(webkitFaviconDatabaseGetFaviconSync): New internal function, it
will return either 0 or a valid pointer to a cairo_surface_t.
* UIProcess/API/gtk/WebKitFaviconDatabasePrivate.h:

Add unit tests for checking this new API.

* UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp:
(testWebViewFavicon): New unit test.
(beforeAll): Add the test to the test suite.

Canonical link: https://commits.webkit.org/115998@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@129994 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
mariospr committed Sep 30, 2012
1 parent 6e936ce commit a38b00a85f48ecfababb27aea489b1bf74337055
Showing 7 changed files with 166 additions and 2 deletions.
@@ -1,3 +1,46 @@
2012-09-30 Mario Sanchez Prada <msanchez@igalia.com>

[WK2][GTK] Add API to get the favicon for a WebKitWebView
https://bugs.webkit.org/show_bug.cgi?id=96477

Reviewed by Carlos Garcia Campos.

Provide a new simple API to synchronously try to get the favicon
associated with a WebView, if any, and to keep track of changes on
it, through a new GObject property.

* UIProcess/API/gtk/WebKitWebView.cpp:
(_WebKitWebViewPrivate):
(webkitWebViewIconReadyCallback): Callback to handle the
'icon-ready' signal coming from WebKitFaviconDatabase.
(webkitWebViewWatchForChangesInFavicon): Connects to the
'icon-ready' signal from WebKitFaviconDatabase, to keep track of
changes in favicons, that must be related to the current view.
(webkitWebViewDisconnectFaviconDatabaseSignalHandlers):
Disconnects the handler for 'icon-ready' if needed.
(webkitWebViewGetProperty): Updated for the new "favicon" property .
(webkitWebViewFinalize): Disconnect the new signal handler.
(webkit_web_view_class_init): Definition of the new property.
(webkitWebViewEmitLoadChanged): Make sure we will be watching for
changes in the favicon from WEBKIT_LOAD_STARTED on.
(webkit_web_view_get_favicon): New API funtcion, returning the
current favicon for the WebView, if any, or NULL otherwise.
* UIProcess/API/gtk/WebKitWebView.h:

Internally expose a way to try to get the favicon associated to a
page URL synchronously, through WebKitFaviconDatabase.

* UIProcess/API/gtk/WebKitFaviconDatabase.cpp:
(webkitFaviconDatabaseGetFaviconSync): New internal function, it
will return either 0 or a valid pointer to a cairo_surface_t.
* UIProcess/API/gtk/WebKitFaviconDatabasePrivate.h:

Add unit tests for checking this new API.

* UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp:
(testWebViewFavicon): New unit test.
(beforeAll): Add the test to the test suite.

2012-09-30 Mario Sanchez Prada <msanchez@igalia.com>

[WK2][GTK] Fix issues with WebKitFaviconDatabase in debug builds
@@ -183,6 +183,18 @@ WebKitFaviconDatabase* webkitFaviconDatabaseCreate(WebIconDatabase* iconDatabase
return faviconDatabase;
}

cairo_surface_t* webkitFaviconDatabaseGetFavicon(WebKitFaviconDatabase* database, const CString& pageURL)
{
ASSERT(WEBKIT_IS_FAVICON_DATABASE(database));
ASSERT(!pageURL.isNull());

cairo_surface_t* iconSurface = getIconSurfaceSynchronously(database, String::fromUTF8(pageURL.data()));
if (!iconSurface)
return 0;

return cairo_surface_reference(iconSurface);
}

static PendingIconRequestVector* getOrCreatePendingIconRequests(WebKitFaviconDatabase* database, const String& pageURL)
{
PendingIconRequestVector* icons = database->priv->pendingIconRequests.get(pageURL);
@@ -22,9 +22,11 @@

#include "WebIconDatabase.h"
#include "WebKitFaviconDatabase.h"
#include <wtf/text/CString.h>

using namespace WebKit;

WebKitFaviconDatabase* webkitFaviconDatabaseCreate(WebIconDatabase*);
cairo_surface_t* webkitFaviconDatabaseGetFavicon(WebKitFaviconDatabase*, const CString&);

#endif // WebKitFaviconDatabasePrivate_h
@@ -30,6 +30,7 @@
#include "WebKitContextMenuPrivate.h"
#include "WebKitEnumTypes.h"
#include "WebKitError.h"
#include "WebKitFaviconDatabasePrivate.h"
#include "WebKitFormClient.h"
#include "WebKitFullscreenClient.h"
#include "WebKitHitTestResultPrivate.h"
@@ -102,6 +103,7 @@ enum {
PROP_WEB_CONTEXT,
PROP_TITLE,
PROP_ESTIMATED_LOAD_PROGRESS,
PROP_FAVICON,
PROP_URI,
PROP_ZOOM_LEVEL,
PROP_IS_LOADING
@@ -120,6 +122,7 @@ struct _WebKitWebViewPrivate {

bool waitingForMainResource;
gulong mainResourceResponseHandlerID;
gulong watchForChangesInFaviconHandlerID;
WebKitLoadEvent lastDelayedEvent;

GRefPtr<WebKitBackForwardList> backForwardList;
@@ -260,6 +263,15 @@ static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebVie
getPage(webView)->setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings)));
}

static void iconReadyCallback(WebKitFaviconDatabase *database, const char *uri, WebKitWebView *webView)
{
// Consider only the icon matching the active URI for this webview.
if (webView->priv->activeURI != uri)
return;

g_object_notify(G_OBJECT(webView), "favicon");
}

static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* settings)
{
webView->priv->settings = settings;
@@ -285,6 +297,29 @@ static void webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(WebK
priv->mainResourceResponseHandlerID = 0;
}

static void webkitWebViewWatchForChangesInFavicon(WebKitWebView* webView)
{
WebKitWebViewPrivate* priv = webView->priv;
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context);

// Make sure we only connect to this signal once per view.
if (priv->watchForChangesInFaviconHandlerID)
return;

priv->watchForChangesInFaviconHandlerID =
g_signal_connect(database, "favicon-ready", G_CALLBACK(iconReadyCallback), webView);
}

static void webkitWebViewDisconnectFaviconDatabaseSignalHandlers(WebKitWebView* webView)
{
WebKitWebViewPrivate* priv = webView->priv;
WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context);

if (priv->watchForChangesInFaviconHandlerID)
g_signal_handler_disconnect(database, priv->watchForChangesInFaviconHandlerID);
priv->watchForChangesInFaviconHandlerID = 0;
}

static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request)
{
GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request);
@@ -385,6 +420,9 @@ static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* valu
case PROP_ESTIMATED_LOAD_PROGRESS:
g_value_set_double(value, webkit_web_view_get_estimated_load_progress(webView));
break;
case PROP_FAVICON:
g_value_set_pointer(value, webkit_web_view_get_favicon(webView));
break;
case PROP_URI:
g_value_set_string(value, webkit_web_view_get_uri(webView));
break;
@@ -413,6 +451,7 @@ static void webkitWebViewFinalize(GObject* object)

webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
webkitWebViewDisconnectSettingsSignalHandlers(webView);
webkitWebViewDisconnectFaviconDatabaseSignalHandlers(webView);

priv->~WebKitWebViewPrivate();
G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
@@ -499,6 +538,18 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
_("An estimate of the percent completion for a document load"),
0.0, 1.0, 0.0,
WEBKIT_PARAM_READABLE));
/**
* WebKitWebView:favicon:
*
* The favicon currently associated to the #WebKitWebView.
* See webkit_web_view_get_favicon() for more details.
*/
g_object_class_install_property(gObjectClass,
PROP_FAVICON,
g_param_spec_pointer("favicon",
_("Favicon"),
_("The favicon associated to the view, if any"),
WEBKIT_PARAM_READABLE));
/**
* WebKitWebView:uri:
*
@@ -1158,9 +1209,10 @@ static void setCertificateToMainResource(WebKitWebView* webView)

static void webkitWebViewEmitLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
{
if (loadEvent == WEBKIT_LOAD_STARTED)
if (loadEvent == WEBKIT_LOAD_STARTED) {
webkitWebViewSetIsLoading(webView, true);
else if (loadEvent == WEBKIT_LOAD_FINISHED) {
webkitWebViewWatchForChangesInFavicon(webView);
} else if (loadEvent == WEBKIT_LOAD_FINISHED) {
webkitWebViewSetIsLoading(webView, false);
webView->priv->waitingForMainResource = false;
webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
@@ -1849,6 +1901,27 @@ const gchar* webkit_web_view_get_uri(WebKitWebView* webView)
return webView->priv->activeURI.data();
}

/**
* webkit_web_view_get_favicon:
* @web_view: a #WebKitWebView
*
* Returns favicon currently associated to @web_view, if any. You can
* connect to notify::favicon signal of @web_view to be notified when
* the favicon is available.
*
* Returns: (transfer full): a pointer to a #cairo_surface_t with the
* favicon or %NULL if there's no icon associated with @web_view.
*/
cairo_surface_t* webkit_web_view_get_favicon(WebKitWebView* webView)
{
g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
if (webView->priv->activeURI.isNull())
return 0;

WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webView->priv->context);
return webkitFaviconDatabaseGetFavicon(database, webView->priv->activeURI);
}

/**
* webkit_web_view_get_custom_charset:
* @web_view: a #WebKitWebView
@@ -262,6 +262,9 @@ webkit_web_view_go_to_back_forward_list_item (WebKitWebView *w
WEBKIT_API const gchar *
webkit_web_view_get_uri (WebKitWebView *web_view);

WEBKIT_API cairo_surface_t *
webkit_web_view_get_favicon (WebKitWebView *web_view);

WEBKIT_API const gchar *
webkit_web_view_get_custom_charset (WebKitWebView *web_view);

@@ -101,6 +101,7 @@ webkit_web_view_set_custom_charset
webkit_web_view_get_back_forward_list
webkit_web_view_go_to_back_forward_list_item
webkit_web_view_get_uri
webkit_web_view_get_favicon
webkit_web_view_set_settings
webkit_web_view_get_settings
webkit_web_view_get_window_properties
@@ -37,6 +37,7 @@ class FaviconDatabaseTest: public WebViewTest {
, m_favicon(0)
, m_error(0)
, m_iconReadySignalReceived(false)
, m_faviconNotificationReceived(false)
{
}

@@ -52,6 +53,13 @@ class FaviconDatabaseTest: public WebViewTest {
test->m_iconReadySignalReceived = true;
}

static void faviconChangedCallback(WebKitWebView* webView, GParamSpec* pspec, gpointer data)
{
FaviconDatabaseTest* test = static_cast<FaviconDatabaseTest*>(data);
g_assert(test->m_webView == webView);
test->m_faviconNotificationReceived = true;
}

static void getFaviconCallback(GObject* sourceObject, GAsyncResult* result, void* data)
{
FaviconDatabaseTest* test = static_cast<FaviconDatabaseTest*>(data);
@@ -68,6 +76,7 @@ class FaviconDatabaseTest: public WebViewTest {
webkit_favicon_database_get_favicon(database, kServer->getURIForPath("/").data(), 0, getFaviconCallback, this);

g_signal_connect(database, "favicon-ready", G_CALLBACK(iconReadyCallback), this);
g_signal_connect(m_webView, "notify::favicon", G_CALLBACK(faviconChangedCallback), this);

g_main_loop_run(m_mainLoop);
}
@@ -83,6 +92,7 @@ class FaviconDatabaseTest: public WebViewTest {
cairo_surface_t* m_favicon;
GOwnPtr<GError> m_error;
bool m_iconReadySignalReceived;
bool m_faviconNotificationReceived;
};

static void
@@ -167,6 +177,25 @@ static void testGetFaviconURI(FaviconDatabaseTest* test, gconstpointer)
g_assert_cmpstr(iconURI.get(), ==, kServer->getURIForPath("/favicon.ico").data());
}

static void testWebViewFavicon(FaviconDatabaseTest* test, gconstpointer)
{
cairo_surface_t* iconFromWebView = webkit_web_view_get_favicon(test->m_webView);
g_assert(!iconFromWebView);

test->loadURI(kServer->getURIForPath("/").data());
test->waitUntilLoadFinished();

test->m_faviconNotificationReceived = false;
test->askForIconAndWaitUntilReady();
g_assert(test->m_faviconNotificationReceived);

iconFromWebView = webkit_web_view_get_favicon(test->m_webView);
g_assert(iconFromWebView);
g_assert(cairo_image_surface_get_width(iconFromWebView) > 0);
g_assert(cairo_image_surface_get_height(iconFromWebView) > 0);
cairo_surface_destroy(iconFromWebView);
}

void beforeAll()
{
// Start a soup server for testing.
@@ -181,6 +210,7 @@ void beforeAll()
FaviconDatabaseTest::add("WebKitFaviconDatabase", "get-favicon", testGetFavicon);
FaviconDatabaseTest::add("WebKitFaviconDatabase", "get-favicon-uri", testGetFaviconURI);
FaviconDatabaseTest::add("WebKitFaviconDatabase", "clear-database", testClearDatabase);
FaviconDatabaseTest::add("WebKitWebView", "favicon", testWebViewFavicon);
}

static void webkitFaviconDatabaseFinalizedCallback(gpointer, GObject*)

0 comments on commit a38b00a

Please sign in to comment.