Title: [130279] trunk/Source/WebKit2
Revision
130279
Author
carlo...@webkit.org
Date
2012-10-03 06:06:27 -0700 (Wed, 03 Oct 2012)

Log Message

[GTK] WebKitWebView doesn't emit notify:favicon when it changes in some cases in WebKit2
https://bugs.webkit.org/show_bug.cgi?id=98153

Reviewed by Martin Robinson.

The main problem is that it relies on icon-ready signal to be
emitted by the favicon database, but that signal is only emitted
when the icon is loaded from the network or imported from the
database, but not when the icon is already in memory. The way to
detect if a web page doesn't have a favicon or it's unknown it's
also incorrectly done and the wrong error is returned for pages
not having a favicon.

* UIProcess/API/gtk/WebKitFaviconDatabase.cpp:
(GetFaviconSurfaceAsyncData): Add a GError field.
(getIconSurfaceSynchronously): Add a GError parameter and fill it
accordingly. Use imageForPageURL() instead of
nativeImageForPageURL() because the latter always returns NULL for
empty images, so it's not possible to know whether it's an empty
image or not. If the image is empty is because the web page is
known by the database and it doesn't have a favicon.
(processPendingIconsForURI): Pass the data error to
getIconSurfaceSynchronously(). Don't set the icon if the request
has been cancelled.
(webkitFaviconDatabaseGetFavicon): Pass NULL as error to
getIconSurfaceSynchronously().
(setErrorForAsyncResult): Fill also error for
WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN.
(webkit_favicon_database_get_favicon): If we get NULL as icon in
the first place, check the error code returned by
getIconSurfaceSynchronously() and return early if the page doesn't
have a favicon. Remove the cancelled signal to avoid race
conditions.
(webkit_favicon_database_get_favicon_finish): Errors are processed
before now, so simply propagate the error if any or return the
favicon.
* UIProcess/API/gtk/WebKitWebView.cpp:
(_WebKitWebViewPrivate): Keep a reference of the favicon.
(webkitWebViewCancelFaviconRequest): Cancel any async operation to
get the favicon.
(webkitWebViewUpdateFavicon): Check if favicon has changed and
save it emitting also notify::favicon signal.
(iconReadyCallback): Only update the favicon if we don't have one
already.
(webkitWebViewFinalize): Call webkitWebViewCancelFaviconRequest().
(getFaviconReadyCallback): Update the favicon.
(webkitWebViewRequestFavicon): Request a new favicon.
(webkitWebViewLoadChanged): Try to get the favicon when the load
has been committed and the URI is the final one.
(webkit_web_view_get_favicon): Return the cached favicon.
* UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp:
(serverCallback):
(testSetDirectory):
(testGetFavicon):
(testWebViewFavicon):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (130278 => 130279)


--- trunk/Source/WebKit2/ChangeLog	2012-10-03 12:55:24 UTC (rev 130278)
+++ trunk/Source/WebKit2/ChangeLog	2012-10-03 13:06:27 UTC (rev 130279)
@@ -1,3 +1,61 @@
+2012-10-03  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GTK] WebKitWebView doesn't emit notify:favicon when it changes in some cases in WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=98153
+
+        Reviewed by Martin Robinson.
+
+        The main problem is that it relies on icon-ready signal to be
+        emitted by the favicon database, but that signal is only emitted
+        when the icon is loaded from the network or imported from the
+        database, but not when the icon is already in memory. The way to
+        detect if a web page doesn't have a favicon or it's unknown it's
+        also incorrectly done and the wrong error is returned for pages
+        not having a favicon.
+
+        * UIProcess/API/gtk/WebKitFaviconDatabase.cpp:
+        (GetFaviconSurfaceAsyncData): Add a GError field.
+        (getIconSurfaceSynchronously): Add a GError parameter and fill it
+        accordingly. Use imageForPageURL() instead of
+        nativeImageForPageURL() because the latter always returns NULL for
+        empty images, so it's not possible to know whether it's an empty
+        image or not. If the image is empty is because the web page is
+        known by the database and it doesn't have a favicon.
+        (processPendingIconsForURI): Pass the data error to
+        getIconSurfaceSynchronously(). Don't set the icon if the request
+        has been cancelled.
+        (webkitFaviconDatabaseGetFavicon): Pass NULL as error to
+        getIconSurfaceSynchronously().
+        (setErrorForAsyncResult): Fill also error for
+        WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN.
+        (webkit_favicon_database_get_favicon): If we get NULL as icon in
+        the first place, check the error code returned by
+        getIconSurfaceSynchronously() and return early if the page doesn't
+        have a favicon. Remove the cancelled signal to avoid race
+        conditions.
+        (webkit_favicon_database_get_favicon_finish): Errors are processed
+        before now, so simply propagate the error if any or return the
+        favicon.
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (_WebKitWebViewPrivate): Keep a reference of the favicon.
+        (webkitWebViewCancelFaviconRequest): Cancel any async operation to
+        get the favicon.
+        (webkitWebViewUpdateFavicon): Check if favicon has changed and
+        save it emitting also notify::favicon signal.
+        (iconReadyCallback): Only update the favicon if we don't have one
+        already.
+        (webkitWebViewFinalize): Call webkitWebViewCancelFaviconRequest().
+        (getFaviconReadyCallback): Update the favicon.
+        (webkitWebViewRequestFavicon): Request a new favicon.
+        (webkitWebViewLoadChanged): Try to get the favicon when the load
+        has been committed and the URI is the final one.
+        (webkit_web_view_get_favicon): Return the cached favicon.
+        * UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp:
+        (serverCallback):
+        (testSetDirectory):
+        (testGetFavicon):
+        (testWebViewFavicon):
+
 2012-10-02  Carlos Garcia Campos  <cgar...@igalia.com>
 
         [GTK] Add API to get the web view that initiated a custom URI request to WebKit2 GTK+

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.cpp (130278 => 130279)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.cpp	2012-10-03 12:55:24 UTC (rev 130278)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.cpp	2012-10-03 13:06:27 UTC (rev 130279)
@@ -28,6 +28,7 @@
 #include <WebCore/RefPtrCairo.h>
 #include <glib/gi18n-lib.h>
 #include <wtf/MainThread.h>
+#include <wtf/gobject/GOwnPtr.h>
 #include <wtf/gobject/GRefPtr.h>
 #include <wtf/text/CString.h>
 
@@ -109,28 +110,30 @@
     GRefPtr<WebKitFaviconDatabase> faviconDatabase;
     String pageURL;
     RefPtr<cairo_surface_t> icon;
+    GOwnPtr<GError> error;
     GRefPtr<GCancellable> cancellable;
-    unsigned long cancelledId;
-
-    ~GetFaviconSurfaceAsyncData()
-    {
-        if (cancelledId)
-            g_cancellable_disconnect(cancellable.get(), cancelledId);
-    }
 };
 WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetFaviconSurfaceAsyncData)
 
-static cairo_surface_t* getIconSurfaceSynchronously(WebKitFaviconDatabase* database, const String& pageURL)
+static cairo_surface_t* getIconSurfaceSynchronously(WebKitFaviconDatabase* database, const String& pageURL, GError** error)
 {
     ASSERT(isMainThread());
 
     // The exact size we pass is irrelevant to the iconDatabase code.
     // We must pass something greater than 0x0 to get an icon.
-    WebCore::NativeImagePtr icon = database->priv->iconDatabase->nativeImageForPageURL(pageURL, WebCore::IntSize(1, 1));
-    if (!icon)
+    WebCore::Image* iconImage = database->priv->iconDatabase->imageForPageURL(pageURL, WebCore::IntSize(1, 1));
+    if (!iconImage) {
+        g_set_error(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, _("Unknown favicon for page %s"), pageURL.utf8().data());
         return 0;
+    }
 
-    return icon ? icon->surface() : 0;
+    WebCore::NativeImagePtr icon = iconImage->nativeImageForCurrentFrame();
+    if (!icon) {
+        g_set_error(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND, _("Page %s does not have a favicon"), pageURL.utf8().data());
+        return 0;
+    }
+
+    return icon->surface();
 }
 
 static void deletePendingIconRequests(WebKitFaviconDatabase* database, PendingIconRequestVector* requests, const String& pageURL)
@@ -148,7 +151,8 @@
     for (size_t i = 0; i < icons->size(); ++i) {
         GSimpleAsyncResult* result = icons->at(i).get();
         GetFaviconSurfaceAsyncData* data = ""
-        data->icon = getIconSurfaceSynchronously(database, pageURL);
+        if (!g_cancellable_is_cancelled(data->cancellable.get()))
+            data->icon = getIconSurfaceSynchronously(database, pageURL, &data->error.outPtr());
 
         g_simple_async_result_complete(result);
     }
@@ -188,7 +192,7 @@
     ASSERT(WEBKIT_IS_FAVICON_DATABASE(database));
     ASSERT(!pageURL.isNull());
 
-    cairo_surface_t* iconSurface = getIconSurfaceSynchronously(database, String::fromUTF8(pageURL.data()));
+    cairo_surface_t* iconSurface = getIconSurfaceSynchronously(database, String::fromUTF8(pageURL.data()), 0);
     if (!iconSurface)
         return 0;
 
@@ -206,34 +210,6 @@
     return icons;
 }
 
-static void getIconSurfaceCancelled(void* userData)
-{
-    GSimpleAsyncResult* result = static_cast<GSimpleAsyncResult*>(userData);
-
-    // Get the data we might need and complete the request.
-    GetFaviconSurfaceAsyncData* data = ""
-    WebKitFaviconDatabase* database = data->faviconDatabase.get();
-    String pageURL = data->pageURL;
-
-    g_simple_async_result_complete(result);
-
-    PendingIconRequestVector* icons = database->priv->pendingIconRequests.get(pageURL);
-    if (!icons)
-        return;
-
-    size_t itemIndex = icons->find(result);
-    if (itemIndex != notFound)
-        icons->remove(itemIndex);
-    if (icons->isEmpty())
-        deletePendingIconRequests(database, icons, pageURL);
-}
-
-static void getIconSurfaceCancelledCallback(GCancellable* cancellable, GSimpleAsyncResult* result)
-{
-    // Handle cancelled in a in idle since it might be called from any thread.
-    callOnMainThread(getIconSurfaceCancelled, result);
-}
-
 static void setErrorForAsyncResult(GSimpleAsyncResult* result, WebKitFaviconDatabaseError error, const String& pageURL = String())
 {
     ASSERT(result);
@@ -247,6 +223,10 @@
         g_simple_async_result_set_error(result, WEBKIT_FAVICON_DATABASE_ERROR, error, _("Page %s does not have a favicon"), pageURL.utf8().data());
         break;
 
+    case WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN:
+        g_simple_async_result_set_error(result, WEBKIT_FAVICON_DATABASE_ERROR, error, _("Unknown favicon for page %s"), pageURL.utf8().data());
+        break;
+
     default:
         ASSERT_NOT_REACHED();
     }
@@ -280,16 +260,13 @@
     g_return_if_fail(pageURI);
 
     GRefPtr<GSimpleAsyncResult> result = adoptGRef(g_simple_async_result_new(G_OBJECT(database), callback, userData, reinterpret_cast<gpointer>(webkit_favicon_database_get_favicon)));
+    g_simple_async_result_set_check_cancellable(result.get(), cancellable);
+
     GetFaviconSurfaceAsyncData* data = ""
     g_simple_async_result_set_op_res_gpointer(result.get(), data, reinterpret_cast<GDestroyNotify>(destroyGetFaviconSurfaceAsyncData));
     data->faviconDatabase = database;
     data->pageURL = String::fromUTF8(pageURI);
     data->cancellable = cancellable;
-    if (cancellable) {
-        data->cancelledId =
-            g_cancellable_connect(cancellable, G_CALLBACK(getIconSurfaceCancelledCallback), result.get(), 0);
-        g_simple_async_result_set_check_cancellable(result.get(), cancellable);
-    }
 
     WebKitFaviconDatabasePrivate* priv = database->priv;
     WebIconDatabase* iconDatabaseImpl = priv->iconDatabase.get();
@@ -307,29 +284,33 @@
 
     // We ask for the icon directly. If we don't get the icon data now,
     // we'll be notified later (even if the database is still importing icons).
-    data->icon = getIconSurfaceSynchronously(database, data->pageURL);
+    GOwnPtr<GError> error;
+    data->icon = getIconSurfaceSynchronously(database, data->pageURL, &error.outPtr());
+    if (data->icon) {
+        g_simple_async_result_complete_in_idle(result.get());
+        return;
+    }
 
+    if (g_error_matches(error.get(), WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND)) {
+        g_simple_async_result_take_error(result.get(), error.release());
+        g_simple_async_result_complete_in_idle(result.get());
+        return;
+    }
+
     // If there's not a valid icon, but there's an iconURL registered,
     // or it's still not registered but the import process hasn't
     // finished yet, we need to wait for iconDataReadyForPage to be
     // called before making and informed decision.
     String iconURLForPageURL;
     iconDatabaseImpl->synchronousIconURLForPageURL(data->pageURL, iconURLForPageURL);
-    if (!data->icon && (!iconURLForPageURL.isEmpty() || !iconDatabaseImpl->isUrlImportCompleted())) {
+    if (!iconURLForPageURL.isEmpty() || !iconDatabaseImpl->isUrlImportCompleted()) {
         PendingIconRequestVector* icons = getOrCreatePendingIconRequests(database, data->pageURL);
         ASSERT(icons);
         icons->append(result);
         return;
     }
 
-    // If we reached this point without a valid icon, which means that
-    // there's no iconURL registered for this pageURI and the
-    // urlImport process has already finished, or do have a valid icon
-    // but it's an empty image, that means there's no favicon.
-    if (!data->icon || !cairo_image_surface_get_data(data->icon.get()))
-        setErrorForAsyncResult(result.get(), WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND, data->pageURL);
-
-    // Complete the asynchronous process;
+    setErrorForAsyncResult(result.get(), WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, data->pageURL);
     g_simple_async_result_complete_in_idle(result.get());
 }
 
@@ -354,28 +335,12 @@
 
     GetFaviconSurfaceAsyncData* data = ""
     ASSERT(data);
-
-    if (data->icon)
-        return cairo_surface_reference(data->icon.get());
-
-    // If the icon is not available at this stage, investigate why
-    // and come up with a descriptive, and hopefully helpful, error.
-    String iconURLForPageURL;
-    database->priv->iconDatabase->synchronousIconURLForPageURL(data->pageURL, iconURLForPageURL);
-
-    if (iconURLForPageURL.isEmpty()) {
-        // If there's no icon URL in the database at this point, we can
-        // conclude there's no favicon at all for the requested page URL.
-        g_set_error(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND,
-                    _("Page %s does not have a favicon"), data->pageURL.utf8().data());
-    } else {
-        // If the icon URL is known it obviously means that the icon data
-        // hasn't been retrieved yet, so report that it's 'unknown'.
-        g_set_error(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN,
-                    _("Unknown favicon for page %s"), data->pageURL.utf8().data());
+    if (data->error) {
+        g_propagate_error(error, data->error.release());
+        return 0;
     }
 
-    return 0;
+    return cairo_surface_reference(data->icon.get());
 }
 
 /**

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp (130278 => 130279)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp	2012-10-03 12:55:24 UTC (rev 130278)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp	2012-10-03 13:06:27 UTC (rev 130279)
@@ -57,6 +57,7 @@
 #include <WebCore/DragIcon.h>
 #include <WebCore/GOwnPtrGtk.h>
 #include <WebCore/GtkUtilities.h>
+#include <WebCore/RefPtrCairo.h>
 #include <glib/gi18n-lib.h>
 #include <wtf/gobject/GOwnPtr.h>
 #include <wtf/gobject/GRefPtr.h>
@@ -142,6 +143,9 @@
     ResourcesMap subresourcesMap;
 
     GRefPtr<WebKitWebInspector> inspector;
+
+    RefPtr<cairo_surface_t> favicon;
+    GRefPtr<GCancellable> faviconCancellable;
 };
 
 static guint signals[LAST_SIGNAL] = { 0, };
@@ -263,13 +267,35 @@
     getPage(webView)->setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings)));
 }
 
-static void iconReadyCallback(WebKitFaviconDatabase *database, const char *uri, WebKitWebView *webView)
+static void webkitWebViewCancelFaviconRequest(WebKitWebView* webView)
 {
+    if (!webView->priv->faviconCancellable)
+        return;
+
+    g_cancellable_cancel(webView->priv->faviconCancellable.get());
+    webView->priv->faviconCancellable = 0;
+}
+
+static void webkitWebViewUpdateFavicon(WebKitWebView* webView, cairo_surface_t* favicon)
+{
+    if (webView->priv->favicon.get() == favicon)
+        return;
+
+    webView->priv->favicon = favicon;
+    g_object_notify(G_OBJECT(webView), "favicon");
+}
+
+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");
+    // Update the favicon only if we don't have one already.
+    if (!webView->priv->favicon) {
+        RefPtr<cairo_surface_t> favicon = adoptRef(webkitFaviconDatabaseGetFavicon(database, webView->priv->activeURI));
+        webkitWebViewUpdateFavicon(webView, favicon.get());
+    }
 }
 
 static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* settings)
@@ -449,6 +475,7 @@
     if (priv->modalLoop && g_main_loop_is_running(priv->modalLoop.get()))
         g_main_loop_quit(priv->modalLoop.get());
 
+    webkitWebViewCancelFaviconRequest(webView);
     webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
     webkitWebViewDisconnectSettingsSignalHandlers(webView);
     webkitWebViewDisconnectFaviconDatabaseSignalHandlers(webView);
@@ -1234,16 +1261,39 @@
     priv->waitingForMainResource = false;
 }
 
+static void getFaviconReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
+{
+    GOwnPtr<GError> error;
+    RefPtr<cairo_surface_t> favicon = adoptRef(webkit_favicon_database_get_favicon_finish(WEBKIT_FAVICON_DATABASE(object), result, &error.outPtr()));
+    if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+        WebKitWebView* webView = WEBKIT_WEB_VIEW(userData);
+        webkitWebViewUpdateFavicon(webView, favicon.get());
+        webView->priv->faviconCancellable = 0;
+    }
+}
+
+static void webkitWebViewRequestFavicon(WebKitWebView* webView)
+{
+    WebKitWebViewPrivate* priv = webView->priv;
+    WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context);
+    priv->faviconCancellable = adoptGRef(g_cancellable_new());
+    webkit_favicon_database_get_favicon(database, priv->activeURI.data(), priv->faviconCancellable.get(), getFaviconReadyCallback, webView);
+}
+
 void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
 {
+    WebKitWebViewPrivate* priv = webView->priv;
     if (loadEvent == WEBKIT_LOAD_STARTED) {
         // Finish a possible previous load waiting for main resource.
         webkitWebViewEmitDelayedLoadEvents(webView);
 
+        webkitWebViewCancelFaviconRequest(webView);
         webView->priv->loadingResourcesMap.clear();
         webView->priv->mainResource = 0;
         webView->priv->waitingForMainResource = false;
     } else if (loadEvent == WEBKIT_LOAD_COMMITTED) {
+        webkitWebViewRequestFavicon(webView);
+
         webView->priv->subresourcesMap.clear();
         if (!webView->priv->mainResource) {
             // When a page is loaded from the history cache, the main resource load callbacks
@@ -1909,7 +1959,7 @@
  * 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
+ * Returns: (transfer none): 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)
@@ -1918,8 +1968,7 @@
     if (webView->priv->activeURI.isNull())
         return 0;
 
-    WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webView->priv->context);
-    return webkitFaviconDatabaseGetFavicon(database, webView->priv->activeURI);
+    return webView->priv->favicon.get();
 }
 
 /**

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp (130278 => 130279)


--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp	2012-10-03 12:55:24 UTC (rev 130278)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp	2012-10-03 13:06:27 UTC (rev 130279)
@@ -39,10 +39,18 @@
         , m_iconReadySignalReceived(false)
         , m_faviconNotificationReceived(false)
     {
+        if (!g_str_equal(webkit_web_context_get_favicon_database_directory(m_webContext), kTempDirectory))
+            webkit_web_context_set_favicon_database_directory(m_webContext, kTempDirectory);
+
+        WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+        g_signal_connect(database, "favicon-ready", G_CALLBACK(iconReadyCallback), this);
     }
 
     ~FaviconDatabaseTest()
     {
+        if (m_favicon)
+            cairo_surface_destroy(m_favicon);
+
         WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
         g_signal_handlers_disconnect_matched(database, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
     }
@@ -58,31 +66,32 @@
         FaviconDatabaseTest* test = static_cast<FaviconDatabaseTest*>(data);
         g_assert(test->m_webView == webView);
         test->m_faviconNotificationReceived = true;
+        test->quitMainLoop();
     }
 
     static void getFaviconCallback(GObject* sourceObject, GAsyncResult* result, void* data)
     {
         FaviconDatabaseTest* test = static_cast<FaviconDatabaseTest*>(data);
         WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
-
-        test->m_error.clear();
         test->m_favicon = webkit_favicon_database_get_favicon_finish(database, result, &test->m_error.outPtr());
-        g_main_loop_quit(test->m_mainLoop);
+        test->quitMainLoop();
     }
 
-    void askForIconAndWaitUntilReady()
+    void waitUntilFaviconChanged()
     {
-        WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
-        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);
-
+        m_faviconNotificationReceived = false;
+        unsigned long handlerID = g_signal_connect(m_webView, "notify::favicon", G_CALLBACK(faviconChangedCallback), this);
         g_main_loop_run(m_mainLoop);
+        g_signal_handler_disconnect(m_webView, handlerID);
     }
 
-    void askAndWaitForFavicon(const char* pageURI)
+    void getFaviconForPageURIAndWaitUntilReady(const char* pageURI)
     {
+        m_error.clear();
+        if (m_favicon) {
+            cairo_surface_destroy(m_favicon);
+            m_favicon = 0;
+        }
         WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
         webkit_favicon_database_get_favicon(database, pageURI, 0, getFaviconCallback, this);
         g_main_loop_run(m_mainLoop);
@@ -102,7 +111,6 @@
         soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
         return;
     }
-    soup_message_set_status(message, SOUP_STATUS_OK);
 
     char* contents;
     gsize length;
@@ -118,13 +126,13 @@
         length = strlen(contents);
     }
 
+    soup_message_set_status(message, SOUP_STATUS_OK);
     soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
     soup_message_body_complete(message->response_body);
 }
 
 static void testSetDirectory(FaviconDatabaseTest* test, gconstpointer)
 {
-    webkit_web_context_set_favicon_database_directory(test->m_webContext, kTempDirectory);
     g_assert_cmpstr(kTempDirectory, ==, webkit_web_context_get_favicon_database_directory(test->m_webContext));
 }
 
@@ -142,30 +150,29 @@
     // We need to load the page first to ensure the icon data will be
     // in the database in case there's an associated favicon.
     test->loadURI(kServer->getURIForPath("/").data());
-    test->waitUntilLoadFinished();
-
-    // Check the WebKitFaviconDatabase::icon-ready signal.
-    test->m_iconReadySignalReceived = false;
-    test->askForIconAndWaitUntilReady();
+    test->waitUntilFaviconChanged();
     g_assert(test->m_iconReadySignalReceived);
 
     // Check the API retrieving a valid favicon.
-    test->askAndWaitForFavicon(kServer->getURIForPath("/").data());
+    test->m_iconReadySignalReceived = false;
+    test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/").data());
     g_assert(test->m_favicon);
     g_assert(!test->m_error);
+    g_assert(!test->m_iconReadySignalReceived);
 
     // Check that width and height match those from blank.ico (16x16 favicon).
     g_assert_cmpint(cairo_image_surface_get_width(test->m_favicon), ==, 16);
     g_assert_cmpint(cairo_image_surface_get_height(test->m_favicon), ==, 16);
-    cairo_surface_destroy(test->m_favicon);
 
     // Check the API retrieving an invalid favicon.
     test->loadURI(kServer->getURIForPath("/nofavicon").data());
-    test->waitUntilLoadFinished();
+    test->waitUntilFaviconChanged();
+    g_assert(!test->m_iconReadySignalReceived);
 
-    test->askAndWaitForFavicon(kServer->getURIForPath("/nofavicon/").data());
+    test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/nofavicon/").data());
     g_assert(!test->m_favicon);
-    g_assert(test->m_error && (test->m_error->code & WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND));
+    g_assert(test->m_error);
+    g_assert(!test->m_iconReadySignalReceived);
 }
 
 static void testGetFaviconURI(FaviconDatabaseTest* test, gconstpointer)
@@ -183,17 +190,13 @@
     g_assert(!iconFromWebView);
 
     test->loadURI(kServer->getURIForPath("/").data());
-    test->waitUntilLoadFinished();
-
-    test->m_faviconNotificationReceived = false;
-    test->askForIconAndWaitUntilReady();
+    test->waitUntilFaviconChanged();
     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);
+    g_assert_cmpuint(cairo_image_surface_get_width(iconFromWebView), ==, 16);
+    g_assert_cmpuint(cairo_image_surface_get_height(iconFromWebView), ==, 16);
 }
 
 void beforeAll()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to