diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp new file mode 100644 index 000000000..8d5be9250 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "WebKitTestServer.h" +#include "WebViewTest.h" +#include <glib/gstdio.h> +#include <libsoup/soup.h> +#include <wtf/glib/GUniquePtr.h> + +static WebKitTestServer* kServer; + +class FaviconDatabaseTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(FaviconDatabaseTest); + + FaviconDatabaseTest() + : m_favicon(nullptr) + , m_faviconNotificationReceived(false) + { + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get()); + g_signal_connect(database, "favicon-changed", G_CALLBACK(faviconChangedCallback), this); + } + + ~FaviconDatabaseTest() + { + if (m_favicon) + cairo_surface_destroy(m_favicon); + + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get()); + g_signal_handlers_disconnect_matched(database, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + } + + static void faviconChangedCallback(WebKitFaviconDatabase* database, const char* pageURI, const char* faviconURI, FaviconDatabaseTest* test) + { + if (!g_strcmp0(webkit_web_view_get_uri(test->m_webView), pageURI)) + test->m_faviconURI = faviconURI; + } + + static void viewFaviconChangedCallback(WebKitWebView* webView, GParamSpec* pspec, gpointer data) + { + 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.get()); + test->m_favicon = webkit_favicon_database_get_favicon_finish(database, result, &test->m_error.outPtr()); + test->quitMainLoop(); + } + + void waitUntilFaviconChanged() + { + m_faviconNotificationReceived = false; + unsigned long handlerID = g_signal_connect(m_webView, "notify::favicon", G_CALLBACK(viewFaviconChangedCallback), this); + g_main_loop_run(m_mainLoop); + g_signal_handler_disconnect(m_webView, handlerID); + } + + void getFaviconForPageURIAndWaitUntilReady(const char* pageURI) + { + if (m_favicon) { + cairo_surface_destroy(m_favicon); + m_favicon = 0; + } + + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get()); + webkit_favicon_database_get_favicon(database, pageURI, 0, getFaviconCallback, this); + g_main_loop_run(m_mainLoop); + } + + cairo_surface_t* m_favicon; + CString m_faviconURI; + GUniqueOutPtr<GError> m_error; + bool m_faviconNotificationReceived; +}; + +static void +serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable* query, SoupClientContext* context, void* data) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + if (g_str_equal(path, "/favicon.ico")) { + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); + soup_message_body_complete(message->response_body); + return; + } + + char* contents; + gsize length; + if (g_str_equal(path, "/icon/favicon.ico")) { + GUniquePtr<char> pathToFavicon(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr)); + g_file_get_contents(pathToFavicon.get(), &contents, &length, 0); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length); + } else if (g_str_equal(path, "/nofavicon")) { + static const char* noFaviconHTML = "<html><head><body>test</body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, noFaviconHTML, strlen(noFaviconHTML)); + } else { + static const char* contentsHTML = "<html><head><link rel='icon' href='/icon/favicon.ico' type='image/x-ico; charset=binary'></head><body>test</body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, contentsHTML, strlen(contentsHTML)); + } + + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_complete(message->response_body); +} + +static void testNotInitialized(FaviconDatabaseTest* test) +{ + // Try to retrieve a valid favicon from a not initialized database. + test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/foo").data()); + g_assert(!test->m_favicon); + g_assert(test->m_error); + g_assert_cmpint(test->m_error->code, ==, WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED); +} + +static void testSetDirectory(FaviconDatabaseTest* test) +{ + webkit_web_context_set_favicon_database_directory(test->m_webContext.get(), Test::dataDirectory()); + g_assert_cmpstr(Test::dataDirectory(), ==, webkit_web_context_get_favicon_database_directory(test->m_webContext.get())); +} + +static void testClearDatabase(FaviconDatabaseTest* test) +{ + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get()); + webkit_favicon_database_clear(database); + + GUniquePtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, kServer->getURIForPath("/foo").data())); + g_assert(!iconURI); +} + +static void testGetFavicon(FaviconDatabaseTest* test) +{ + // 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("/foo").data()); + test->waitUntilFaviconChanged(); + CString faviconURI = kServer->getURIForPath("/icon/favicon.ico"); + + // Check the API retrieving a valid favicon. + test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/foo").data()); + g_assert(test->m_favicon); + g_assert_cmpstr(test->m_faviconURI.data(), ==, faviconURI.data()); + g_assert(!test->m_error); + + // 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); + + // Check that another page with the same favicon return the same icon. + cairo_surface_t* favicon = cairo_surface_reference(test->m_favicon); + test->loadURI(kServer->getURIForPath("/bar").data()); + // It's a new page in the database, so favicon will change twice, first to reset it + // and then when the icon is loaded. + test->waitUntilFaviconChanged(); + test->waitUntilFaviconChanged(); + test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/bar").data()); + g_assert(test->m_favicon); + g_assert_cmpstr(test->m_faviconURI.data(), ==, faviconURI.data()); + g_assert(test->m_favicon == favicon); + g_assert(!test->m_error); + cairo_surface_destroy(favicon); + + // Check the API retrieving an invalid favicon. + test->loadURI(kServer->getURIForPath("/nofavicon").data()); + test->waitUntilFaviconChanged(); + + test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/nofavicon").data()); + g_assert(!test->m_favicon); + g_assert(test->m_error); +} + +static void testGetFaviconURI(FaviconDatabaseTest* test) +{ + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get()); + + CString baseURI = kServer->getURIForPath("/foo"); + GUniquePtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, baseURI.data())); + ASSERT_CMP_CSTRING(iconURI.get(), ==, kServer->getURIForPath("/icon/favicon.ico")); +} + +static void testWebViewFavicon(FaviconDatabaseTest* test) +{ + test->m_faviconURI = CString(); + + cairo_surface_t* iconFromWebView = webkit_web_view_get_favicon(test->m_webView); + g_assert(!iconFromWebView); + + test->loadURI(kServer->getURIForPath("/foo").data()); + test->waitUntilFaviconChanged(); + g_assert(test->m_faviconNotificationReceived); + // The icon is known and hasn't changed in the database, so notify::favicon is emitted + // but WebKitFaviconDatabase::icon-changed isn't. + g_assert(test->m_faviconURI.isNull()); + + iconFromWebView = webkit_web_view_get_favicon(test->m_webView); + g_assert(iconFromWebView); + g_assert_cmpuint(cairo_image_surface_get_width(iconFromWebView), ==, 16); + g_assert_cmpuint(cairo_image_surface_get_height(iconFromWebView), ==, 16); +} + +static void testFaviconDatabase(FaviconDatabaseTest* test, gconstpointer) +{ + // These tests depend on this order to run properly so we declare them in a single one. + // See https://bugs.webkit.org/show_bug.cgi?id=111434. + testNotInitialized(test); + testSetDirectory(test); + testGetFavicon(test); + testGetFaviconURI(test); + testWebViewFavicon(test); + testClearDatabase(test); +} + +void beforeAll() +{ + // Start a soup server for testing. + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + // Add tests to the suite. + FaviconDatabaseTest::add("WebKitFaviconDatabase", "favicon-database-test", testFaviconDatabase); +} + +void afterAll() +{ + delete kServer; +} |