diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-15 16:08:57 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-15 16:08:57 +0200 |
commit | 5466563f4b5b6b86523e3f89bb7f77e5b5270c78 (patch) | |
tree | 8caccf7cd03a15207cde3ba282c88bf132482a91 /Source/WebKit2/UIProcess/API/gtk | |
parent | 33b26980cb24288b5a9f2590ccf32a949281bb79 (diff) | |
download | qtwebkit-5466563f4b5b6b86523e3f89bb7f77e5b5270c78.tar.gz |
Imported WebKit commit 0dc6cd75e1d4836eaffbb520be96fac4847cc9d2 (http://svn.webkit.org/repository/webkit/trunk@131300)
WebKit update which introduces the QtWebKitWidgets module that contains the WK1
widgets based API. (In fact it renames QtWebKit to QtWebKitWidgets while we're
working on completing the entire split as part of
https://bugs.webkit.org/show_bug.cgi?id=99314
Diffstat (limited to 'Source/WebKit2/UIProcess/API/gtk')
40 files changed, 1550 insertions, 241 deletions
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp index 6e72496ef..79c1c3e2a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp @@ -34,13 +34,13 @@ using namespace WebKit; static void didStart(WKContextRef, WKDownloadRef wkDownload, const void* clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); webkitWebContextDownloadStarted(WEBKIT_WEB_CONTEXT(clientInfo), download.get()); } static void didReceiveResponse(WKContextRef, WKDownloadRef wkDownload, WKURLResponseRef wkResponse, const void* clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); if (webkitDownloadIsCancelled(download.get())) return; @@ -50,13 +50,13 @@ static void didReceiveResponse(WKContextRef, WKDownloadRef wkDownload, WKURLResp static void didReceiveData(WKContextRef, WKDownloadRef wkDownload, uint64_t length, const void* clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); webkitDownloadNotifyProgress(download.get(), length); } static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef wkDownload, WKStringRef filename, bool* allowOverwrite, const void* clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); CString destinationURI = webkitDownloadDecideDestinationWithSuggestedFilename(download.get(), toImpl(filename)->string().utf8()); return WKStringCreateWithUTF8CString(destinationURI.data()); @@ -64,33 +64,33 @@ static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownlo static void didCreateDestination(WKContextRef, WKDownloadRef wkDownload, WKStringRef path, const void* clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); webkitDownloadDestinationCreated(download.get(), toImpl(path)->string().utf8()); } static void didFail(WKContextRef, WKDownloadRef wkDownload, WKErrorRef error, const void *clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); if (webkitDownloadIsCancelled(download.get())) { // Cancellation takes precedence over other errors. webkitDownloadCancelled(download.get()); } else webkitDownloadFailed(download.get(), toImpl(error)->platformError()); - webkitWebContextRemoveDownload(wkDownload); + webkitWebContextRemoveDownload(toImpl(wkDownload)); } static void didCancel(WKContextRef, WKDownloadRef wkDownload, const void *clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); webkitDownloadCancelled(download.get()); - webkitWebContextRemoveDownload(wkDownload); + webkitWebContextRemoveDownload(toImpl(wkDownload)); } static void didFinish(WKContextRef wkContext, WKDownloadRef wkDownload, const void *clientInfo) { - GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(toImpl(wkDownload)); webkitDownloadFinished(download.get()); - webkitWebContextRemoveDownload(wkDownload); + webkitWebContextRemoveDownload(toImpl(wkDownload)); } void attachDownloadClientToContext(WebKitWebContext* webContext) @@ -110,6 +110,6 @@ void attachDownloadClientToContext(WebKitWebContext* webContext) didCancel, 0, // processDidCrash }; - WKContextSetDownloadClient(webkitWebContextGetWKContext(webContext), &wkDownloadClient); + WKContextSetDownloadClient(toAPI(webkitWebContextGetContext(webContext)), &wkDownloadClient); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.cpp new file mode 100644 index 000000000..cb016ab09 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.cpp @@ -0,0 +1,391 @@ +/* + * 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 "WebKitFaviconDatabase.h" + +#include "WebKitFaviconDatabasePrivate.h" +#include "WebKitPrivate.h" +#include <WebCore/FileSystem.h> +#include <WebCore/Image.h> +#include <WebCore/IntSize.h> +#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> + +using namespace WebKit; + +enum { + ICON_READY, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +typedef Vector<GRefPtr<GSimpleAsyncResult> > PendingIconRequestVector; +typedef HashMap<String, PendingIconRequestVector*> PendingIconRequestMap; + +struct _WebKitFaviconDatabasePrivate { + RefPtr<WebIconDatabase> iconDatabase; + PendingIconRequestMap pendingIconRequests; +}; + +G_DEFINE_TYPE(WebKitFaviconDatabase, webkit_favicon_database, G_TYPE_OBJECT) + +static void webkit_favicon_database_init(WebKitFaviconDatabase* manager) +{ + WebKitFaviconDatabasePrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(manager, WEBKIT_TYPE_FAVICON_DATABASE, WebKitFaviconDatabasePrivate); + manager->priv = priv; + new (priv) WebKitFaviconDatabasePrivate(); +} + +static void webkitFaviconDatabaseDispose(GObject* object) +{ + WebKitFaviconDatabase* database = WEBKIT_FAVICON_DATABASE(object); + + WebKitFaviconDatabasePrivate* priv = database->priv; + if (priv->iconDatabase->isOpen()) + priv->iconDatabase->close(); + + G_OBJECT_CLASS(webkit_favicon_database_parent_class)->dispose(object); +} + +static void webkitFaviconDatabaseFinalize(GObject* object) +{ + WebKitFaviconDatabase* database = WEBKIT_FAVICON_DATABASE(object); + database->priv->~WebKitFaviconDatabasePrivate(); + G_OBJECT_CLASS(webkit_favicon_database_parent_class)->finalize(object); +} + +static void webkit_favicon_database_class_init(WebKitFaviconDatabaseClass* faviconDatabaseClass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(faviconDatabaseClass); + gObjectClass->dispose = webkitFaviconDatabaseDispose; + gObjectClass->finalize = webkitFaviconDatabaseFinalize; + + /** + * WebKitFaviconDatabase::favicon-ready: + * @database: the object on which the signal is emitted + * @page_uri: the URI of the Web page containing the icon. + * + * This signal gets emitted when the favicon of @page_uri is + * ready. This means that the favicon's data is ready to be used + * by the application, either because it has been loaded from the + * network, if it's the first time it gets retrieved, or because + * it has been already imported from the icon database. + */ + signals[ICON_READY] = + g_signal_new("favicon-ready", + G_TYPE_FROM_CLASS(faviconDatabaseClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + g_type_class_add_private(faviconDatabaseClass, sizeof(WebKitFaviconDatabasePrivate)); +} + +struct GetFaviconSurfaceAsyncData { + GRefPtr<WebKitFaviconDatabase> faviconDatabase; + String pageURL; + RefPtr<cairo_surface_t> icon; + GOwnPtr<GError> error; + GRefPtr<GCancellable> cancellable; +}; +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetFaviconSurfaceAsyncData) + +static cairo_surface_t* getIconSurfaceSynchronously(WebKitFaviconDatabase* database, const String& pageURL, GError** error) +{ + ASSERT(isMainThread()); + + database->priv->iconDatabase->retainIconForPageURL(pageURL); + + // The exact size we pass is irrelevant to the iconDatabase code. + // We must pass something greater than 0x0 to get an 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()); + database->priv->iconDatabase->releaseIconForPageURL(pageURL); + return 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()); + database->priv->iconDatabase->releaseIconForPageURL(pageURL); + return 0; + } + + return icon->surface(); +} + +static void deletePendingIconRequests(WebKitFaviconDatabase* database, PendingIconRequestVector* requests, const String& pageURL) +{ + database->priv->pendingIconRequests.remove(pageURL); + delete requests; +} + +static void processPendingIconsForPageURL(WebKitFaviconDatabase* database, const String& pageURL) +{ + PendingIconRequestVector* pendingIconRequests = database->priv->pendingIconRequests.get(pageURL); + if (!pendingIconRequests) + return; + + GOwnPtr<GError> error; + RefPtr<cairo_surface_t> icon = getIconSurfaceSynchronously(database, pageURL, &error.outPtr()); + + for (size_t i = 0; i < pendingIconRequests->size(); ++i) { + GSimpleAsyncResult* result = pendingIconRequests->at(i).get(); + GetFaviconSurfaceAsyncData* data = static_cast<GetFaviconSurfaceAsyncData*>(g_simple_async_result_get_op_res_gpointer(result)); + if (!g_cancellable_is_cancelled(data->cancellable.get())) { + if (error) + g_propagate_error(&data->error.outPtr(), error.release()); + else + data->icon = icon; + } + + g_simple_async_result_complete(result); + } + deletePendingIconRequests(database, pendingIconRequests, pageURL); +} + +static void iconDataReadyForPageURLCallback(WKIconDatabaseRef wkIconDatabase, WKURLRef wkPageURL, const void* clientInfo) +{ + ASSERT(isMainThread()); + + WebKitFaviconDatabase* database = WEBKIT_FAVICON_DATABASE(clientInfo); + String pageURL = toImpl(wkPageURL)->string(); + + processPendingIconsForPageURL(database, pageURL); + g_signal_emit(database, signals[ICON_READY], 0, pageURL.utf8().data()); +} + +WebKitFaviconDatabase* webkitFaviconDatabaseCreate(WebIconDatabase* iconDatabase) +{ + WebKitFaviconDatabase* faviconDatabase = WEBKIT_FAVICON_DATABASE(g_object_new(WEBKIT_TYPE_FAVICON_DATABASE, NULL)); + faviconDatabase->priv->iconDatabase = iconDatabase; + + WKIconDatabaseClient wkIconDatabaseClient = { + kWKIconDatabaseClientCurrentVersion, + faviconDatabase, // clientInfo + 0, // didChangeIconForPageURLCallback + 0, // didRemoveAllIconsCallback + iconDataReadyForPageURLCallback, + }; + WKIconDatabaseSetIconDatabaseClient(toAPI(iconDatabase), &wkIconDatabaseClient); + 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()), 0); + if (!iconSurface) + return 0; + + return cairo_surface_reference(iconSurface); +} + +static PendingIconRequestVector* getOrCreatePendingIconRequests(WebKitFaviconDatabase* database, const String& pageURL) +{ + PendingIconRequestVector* icons = database->priv->pendingIconRequests.get(pageURL); + if (!icons) { + icons = new PendingIconRequestVector; + database->priv->pendingIconRequests.set(pageURL, icons); + } + + return icons; +} + +static void setErrorForAsyncResult(GSimpleAsyncResult* result, WebKitFaviconDatabaseError error, const String& pageURL = String()) +{ + ASSERT(result); + + switch (error) { + case WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED: + g_simple_async_result_set_error(result, WEBKIT_FAVICON_DATABASE_ERROR, error, _("Favicons database not initialized yet")); + break; + + case WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND: + 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(); + } +} + +GQuark webkit_favicon_database_error_quark(void) +{ + return g_quark_from_static_string("WebKitFaviconDatabaseError"); +} + +/** + * webkit_favicon_database_get_favicon: + * @database: a #WebKitFaviconDatabase + * @page_uri: URI of the page for which we want to retrieve the favicon + * @cancellable: (allow-none): A #GCancellable or %NULL. + * @callback: (scope async): A #GAsyncReadyCallback to call when the request is + * satisfied or %NULL if you don't care about the result. + * @user_data: (closure): The data to pass to @callback. + * + * Asynchronously obtains a #cairo_surface_t of the favicon for the + * given page URI. It returns the cached icon if it's in the database + * asynchronously waiting for the icon to be read from the database. + * + * This is an asynchronous method. When the operation is finished, callback will + * be invoked. You can then call webkit_favicon_database_get_favicon_finish() + * to get the result of the operation. + */ +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); + + 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 = createGetFaviconSurfaceAsyncData(); + 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; + + WebKitFaviconDatabasePrivate* priv = database->priv; + WebIconDatabase* iconDatabaseImpl = priv->iconDatabase.get(); + if (!iconDatabaseImpl->isOpen()) { + setErrorForAsyncResult(result.get(), WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED); + g_simple_async_result_complete_in_idle(result.get()); + return; + } + + if (data->pageURL.isEmpty() || data->pageURL.startsWith("about:")) { + setErrorForAsyncResult(result.get(), WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND, data->pageURL); + g_simple_async_result_complete_in_idle(result.get()); + return; + } + + // 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). + 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 (!iconURLForPageURL.isEmpty() || !iconDatabaseImpl->isUrlImportCompleted()) { + PendingIconRequestVector* icons = getOrCreatePendingIconRequests(database, data->pageURL); + ASSERT(icons); + icons->append(result); + return; + } + + setErrorForAsyncResult(result.get(), WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, data->pageURL); + g_simple_async_result_complete_in_idle(result.get()); +} + +/** + * webkit_favicon_database_get_favicon_finish: + * @database: a #WebKitFaviconDatabase + * @result: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to webkit_favicon_database_get_favicon() + * @error: (allow-none): Return location for error or %NULL. + * + * Finishes an operation started with webkit_favicon_database_get_favicon(). + * + * Returns: (transfer full): a new reference to a #cairo_surface_t, or + * %NULL in case of error. + */ +cairo_surface_t* webkit_favicon_database_get_favicon_finish(WebKitFaviconDatabase* database, GAsyncResult* result, GError** error) +{ + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_favicon_database_get_favicon); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + GetFaviconSurfaceAsyncData* data = static_cast<GetFaviconSurfaceAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + ASSERT(data); + if (data->error) { + g_propagate_error(error, data->error.release()); + return 0; + } + + return cairo_surface_reference(data->icon.get()); +} + +/** + * webkit_favicon_database_get_favicon_uri: + * @database: a #WebKitFaviconDatabase + * @page_uri: URI of the page containing the icon + * + * Obtains the URI of the favicon for the given @page_uri. + * + * Returns: a newly allocated URI for the favicon, or %NULL if the + * database doesn't have a favicon for @page_uri. + */ +gchar* webkit_favicon_database_get_favicon_uri(WebKitFaviconDatabase* database, const gchar* pageURL) +{ + g_return_val_if_fail(WEBKIT_IS_FAVICON_DATABASE(database), 0); + g_return_val_if_fail(pageURL, 0); + ASSERT(isMainThread()); + + String iconURLForPageURL; + database->priv->iconDatabase->synchronousIconURLForPageURL(String::fromUTF8(pageURL), iconURLForPageURL); + if (iconURLForPageURL.isEmpty()) + return 0; + + return g_strdup(iconURLForPageURL.utf8().data()); +} + +/** + * webkit_favicon_database_clear: + * @database: a #WebKitFaviconDatabase + * + * Clears all icons from the database. + */ +void webkit_favicon_database_clear(WebKitFaviconDatabase* database) +{ + g_return_if_fail(WEBKIT_IS_FAVICON_DATABASE(database)); + + database->priv->iconDatabase->removeAllIcons(); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.h new file mode 100644 index 000000000..811a8e6bb --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabase.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitFaviconDatabase_h +#define WebKitFaviconDatabase_h + +#include <cairo.h> +#include <gio/gio.h> +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_FAVICON_DATABASE (webkit_favicon_database_get_type()) +#define WEBKIT_FAVICON_DATABASE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_FAVICON_DATABASE, WebKitFaviconDatabase)) +#define WEBKIT_IS_FAVICON_DATABASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_FAVICON_DATABASE)) +#define WEBKIT_FAVICON_DATABASE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_FAVICON_DATABASE, WebKitFaviconDatabaseClass)) +#define WEBKIT_IS_FAVICON_DATABASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_FAVICON_DATABASE)) +#define WEBKIT_FAVICON_DATABASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_FAVICON_DATABASE, WebKitFaviconDatabaseClass)) +#define WEBKIT_FAVICON_DATABASE_ERROR (webkit_favicon_database_error_quark()) + +typedef struct _WebKitFaviconDatabase WebKitFaviconDatabase; +typedef struct _WebKitFaviconDatabaseClass WebKitFaviconDatabaseClass; +typedef struct _WebKitFaviconDatabasePrivate WebKitFaviconDatabasePrivate; + +struct _WebKitFaviconDatabase { + GObject parent; + + WebKitFaviconDatabasePrivate *priv; +}; + +struct _WebKitFaviconDatabaseClass { + GObjectClass parent_class; +}; + +/** + * WebKitFaviconDatabaseError: + * @WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED: The #WebKitFaviconDatabase has not been initialized yet + * @WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND: There is not an icon available for the requested URL + * @WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN: There might be an icon for the requested URL, but its data is unknown at the moment + * + * Enum values used to denote the various errors related to the #WebKitFaviconDatabase. + **/ +typedef enum { + WEBKIT_FAVICON_DATABASE_ERROR_NOT_INITIALIZED, + WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND, + WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN +} WebKitFaviconDatabaseError; + +WEBKIT_API GQuark +webkit_favicon_database_error_quark (void); + +WEBKIT_API GType +webkit_favicon_database_get_type (void); + +WEBKIT_API void +webkit_favicon_database_get_favicon (WebKitFaviconDatabase *database, + const gchar *page_uri, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +WEBKIT_API cairo_surface_t * +webkit_favicon_database_get_favicon_finish (WebKitFaviconDatabase *database, + GAsyncResult *result, + GError **error); +WEBKIT_API gchar * +webkit_favicon_database_get_favicon_uri (WebKitFaviconDatabase *database, + const gchar *page_uri); +WEBKIT_API void +webkit_favicon_database_clear (WebKitFaviconDatabase *database); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabasePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabasePrivate.h new file mode 100644 index 000000000..6c50949fb --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFaviconDatabasePrivate.h @@ -0,0 +1,32 @@ +/* + * 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 Library General Public + * License as published by the Free Software Foundation; either + * version 2 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. + */ + +#ifndef WebKitFaviconDatabasePrivate_h +#define WebKitFaviconDatabasePrivate_h + +#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 diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp index 84ad04d03..2a1b8d5a3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp @@ -21,15 +21,16 @@ #include "WebKitJavascriptResult.h" #include "WebKitJavascriptResultPrivate.h" +#include "WebSerializedScriptValue.h" #include <wtf/gobject/GRefPtr.h> struct _WebKitJavascriptResult { - _WebKitJavascriptResult(WebKitWebView* view, WKSerializedScriptValueRef wkSerializedScriptValue) + _WebKitJavascriptResult(WebKitWebView* view, WebSerializedScriptValue* serializedScriptValue) : webView(view) , referenceCount(1) - { - value = WKSerializedScriptValueDeserialize(wkSerializedScriptValue, webkit_web_view_get_javascript_global_context(view), 0); - } + { + value = serializedScriptValue->deserialize(webkit_web_view_get_javascript_global_context(view), 0); + } GRefPtr<WebKitWebView> webView; JSValueRef value; @@ -39,10 +40,10 @@ struct _WebKitJavascriptResult { G_DEFINE_BOXED_TYPE(WebKitJavascriptResult, webkit_javascript_result, webkit_javascript_result_ref, webkit_javascript_result_unref) -WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView* webView, WKSerializedScriptValueRef wkSerializedScriptValue) +WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView* webView, WebSerializedScriptValue* serializedScriptValue) { WebKitJavascriptResult* result = g_slice_new(WebKitJavascriptResult); - new (result) WebKitJavascriptResult(webView, wkSerializedScriptValue); + new (result) WebKitJavascriptResult(webView, serializedScriptValue); return result; } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h index 840ead058..ac7578857 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h @@ -24,6 +24,8 @@ #include "WebKitPrivate.h" #include "WebKitWebView.h" -WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView*, WKSerializedScriptValueRef); +using namespace WebKit; + +WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView*, WebSerializedScriptValue*); #endif // WebKitJavascriptResultPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp index 6c3bf920a..457c40141 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp @@ -152,6 +152,7 @@ void attachLoaderClientToView(WebKitWebView* webView) 0, // pluginDidFail 0, // didReceiveIntentForFrame 0, // registerIntentServiceForFrame + 0, // didLayout }; WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); WKPageSetPageLoaderClient(wkPage, &wkLoaderClient); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index 8fede827f..9ceafecb6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -34,6 +34,7 @@ #include <WebKit2/WKGeolocationManager.h> #include <WebKit2/WKGeolocationPermissionRequest.h> #include <WebKit2/WKGeolocationPosition.h> +#include <WebKit2/WKIconDatabase.h> #include <WebKit2/WKInspector.h> #include <WebKit2/WKInspectorClientGtk.h> #include <WebKit2/WKRetainPtr.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitRequestManagerClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitRequestManagerClient.cpp index 8ea09f200..babafe651 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitRequestManagerClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitRequestManagerClient.cpp @@ -26,10 +26,10 @@ using namespace WebKit; -static void didReceiveURIRequest(WKSoupRequestManagerRef soupRequestManagerRef, WKURLRef urlRef, uint64_t requestID, const void* clientInfo) +static void didReceiveURIRequest(WKSoupRequestManagerRef soupRequestManagerRef, WKURLRef urlRef, WKPageRef initiatingPageRef, uint64_t requestID, const void* clientInfo) { WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(clientInfo); - GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(webContext, soupRequestManagerRef, urlRef, requestID)); + GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(webContext, soupRequestManagerRef, urlRef, initiatingPageRef, requestID)); webkitWebContextReceivedURIRequest(webContext, request.get()); } @@ -46,6 +46,6 @@ void attachRequestManagerClientToContext(WebKitWebContext* webContext) didReceiveURIRequest, didFailToLoadURIRequest }; - WKSoupRequestManagerSetClient(webkitWebContextGetRequestManager(webContext), &wkRequestManagerClient); + WKSoupRequestManagerSetClient(toAPI(webkitWebContextGetRequestManager(webContext)), &wkRequestManagerClient); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityManager.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityManager.cpp index 53b46f875..d170fcf3f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityManager.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSecurityManager.cpp @@ -74,7 +74,7 @@ WebKitSecurityManager* webkitSecurityManagerCreate(WebKitWebContext* webContext) static void registerSecurityPolicyForURIScheme(WebKitSecurityManager* manager, const char* scheme, SecurityPolicy policy) { String urlScheme = String::fromUTF8(scheme); - WebContext* webContext = toImpl(webkitWebContextGetWKContext(manager->priv->webContext)); + WebContext* webContext = webkitWebContextGetContext(manager->priv->webContext); // We keep the WebCore::SchemeRegistry of the UI process in sync with the // web process one, so that we can return the SecurityPolicy for diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index c0a64162a..17d4c881b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -34,6 +34,7 @@ #include "WebKitPrivate.h" #include "WebKitSettingsPrivate.h" #include "WebPageProxy.h" +#include "WebPreferences.h" #include <WebCore/UserAgentGtk.h> #include <glib/gi18n-lib.h> #include <wtf/text/CString.h> @@ -117,7 +118,8 @@ enum { PROP_DRAW_COMPOSITING_INDICATORS, PROP_ENABLE_SITE_SPECIFIC_QUIRKS, PROP_ENABLE_PAGE_CACHE, - PROP_USER_AGENT + PROP_USER_AGENT, + PROP_ENABLE_SMOOTH_SCROLLING }; static void webKitSettingsSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -251,6 +253,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu case PROP_USER_AGENT: webkit_settings_set_user_agent(settings, g_value_get_string(value)); break; + case PROP_ENABLE_SMOOTH_SCROLLING: + webkit_settings_set_enable_smooth_scrolling(settings, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -388,6 +393,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val case PROP_USER_AGENT: g_value_set_string(value, webkit_settings_get_user_agent(settings)); break; + case PROP_ENABLE_SMOOTH_SCROLLING: + g_value_set_boolean(value, webkit_settings_get_enable_smooth_scrolling(settings)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -1039,6 +1047,19 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) 0, // A null string forces the standard user agent. readWriteConstructParamFlags)); + /** + * WebKitSettings:enable-smooth-scrolling: + * + * Enable or disable smooth scrolling. + */ + g_object_class_install_property(gObjectClass, + PROP_ENABLE_SMOOTH_SCROLLING, + g_param_spec_boolean("enable-smooth-scrolling", + _("Enable smooth scrolling"), + _("Whether to enable smooth scrolling"), + FALSE, + readWriteConstructParamFlags)); + g_type_class_add_private(klass, sizeof(WebKitSettingsPrivate)); } @@ -2644,3 +2665,38 @@ void webkit_settings_set_user_agent_with_application_details(WebKitSettings* set CString newUserAgent = WebCore::standardUserAgent(String::fromUTF8(applicationName), String::fromUTF8(applicationVersion)).utf8(); webkit_settings_set_user_agent(settings, newUserAgent.data()); } + +/** + * webkit_settings_get_enable_smooth_scrolling: + * @settings: a #WebKitSettings + * + * Get the #WebKitSettings:enable-smooth-scrolling property. + * + * Returns: %TRUE if smooth scrolling is enabled or %FALSE otherwise. + */ +gboolean webkit_settings_get_enable_smooth_scrolling(WebKitSettings* settings) +{ + g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); + + return WebKit::toImpl(settings->priv->preferences.get())->scrollAnimatorEnabled(); +} + +/** + * webkit_settings_set_enable_smooth_scrolling: + * @settings: a #WebKitSettings + * @enabled: Value to be set + * + * Set the #WebKitSettings:enable-smooth-scrolling property. + */ +void webkit_settings_set_enable_smooth_scrolling(WebKitSettings* settings, gboolean enabled) +{ + g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); + + WebKitSettingsPrivate* priv = settings->priv; + bool currentValue = WebKit::toImpl(priv->preferences.get())->scrollAnimatorEnabled(); + if (currentValue == enabled) + return; + + WebKit::toImpl(priv->preferences.get())->setScrollAnimatorEnabled(enabled); + g_object_notify(G_OBJECT(settings), "enable-smooth-scrolling"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h index b35a23f06..a9fe86a30 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h @@ -373,6 +373,13 @@ webkit_settings_set_user_agent_with_application_details (WebKitSettings * const gchar *application_name, const gchar *application_version); +WEBKIT_API gboolean +webkit_settings_get_enable_smooth_scrolling (WebKitSettings *settings); + +WEBKIT_API void +webkit_settings_set_enable_smooth_scrolling (WebKitSettings *settings, + gboolean enabled); + G_END_DECLS #endif /* WebKitSettings_h */ diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.cpp index e62c1faf5..e69831f29 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.cpp @@ -22,6 +22,8 @@ #include "WebKitURISchemeRequestPrivate.h" #include "WebKitWebContextPrivate.h" +#include "WebKitWebView.h" +#include "WebPageProxy.h" #include <WebCore/GOwnPtrSoup.h> #include <libsoup/soup.h> #include <wtf/gobject/GRefPtr.h> @@ -36,6 +38,7 @@ G_DEFINE_TYPE(WebKitURISchemeRequest, webkit_uri_scheme_request, G_TYPE_OBJECT) struct _WebKitURISchemeRequestPrivate { WebKitWebContext* webContext; WKRetainPtr<WKSoupRequestManagerRef> wkRequestManager; + WKRetainPtr<WKPageRef> wkInitiatingPage; uint64_t requestID; CString uri; GOwnPtr<SoupURI> soupURI; @@ -68,12 +71,13 @@ static void webkit_uri_scheme_request_class_init(WebKitURISchemeRequestClass* re g_type_class_add_private(requestClass, sizeof(WebKitURISchemeRequestPrivate)); } -WebKitURISchemeRequest* webkitURISchemeRequestCreate(WebKitWebContext* webContext, WKSoupRequestManagerRef wkRequestManager, WKURLRef wkURL, uint64_t requestID) +WebKitURISchemeRequest* webkitURISchemeRequestCreate(WebKitWebContext* webContext, WKSoupRequestManagerRef wkRequestManager, WKURLRef wkURL, WKPageRef wkInitiatingPage, uint64_t requestID) { WebKitURISchemeRequest* request = WEBKIT_URI_SCHEME_REQUEST(g_object_new(WEBKIT_TYPE_URI_SCHEME_REQUEST, NULL)); request->priv->webContext = webContext; request->priv->wkRequestManager = wkRequestManager; request->priv->uri = toImpl(wkURL)->string().utf8(); + request->priv->wkInitiatingPage = wkInitiatingPage; request->priv->requestID = requestID; return request; } @@ -138,6 +142,21 @@ const char* webkit_uri_scheme_request_get_path(WebKitURISchemeRequest* request) return request->priv->soupURI->path; } +/** + * webkit_uri_scheme_request_get_web_view: + * @request: a #WebKitURISchemeRequest + * + * Get the #WebKitWebView that initiated the request. + * + * Returns: (transfer none): the #WebKitWebView that initiated @request. + */ +WebKitWebView* webkit_uri_scheme_request_get_web_view(WebKitURISchemeRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request), 0); + + return WEBKIT_WEB_VIEW(toImpl(request->priv->wkInitiatingPage.get())->viewWidget()); +} + static void webkitURISchemeRequestReadCallback(GInputStream* inputStream, GAsyncResult* result, WebKitURISchemeRequest* schemeRequest) { GRefPtr<WebKitURISchemeRequest> request = adoptGRef(schemeRequest); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.h index 34f214489..9ead50709 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequest.h @@ -51,22 +51,25 @@ struct _WebKitURISchemeRequestClass { }; WEBKIT_API GType -webkit_uri_scheme_request_get_type (void); +webkit_uri_scheme_request_get_type (void); WEBKIT_API const gchar * -webkit_uri_scheme_request_get_scheme (WebKitURISchemeRequest *request); +webkit_uri_scheme_request_get_scheme (WebKitURISchemeRequest *request); WEBKIT_API const gchar * -webkit_uri_scheme_request_get_uri (WebKitURISchemeRequest *request); +webkit_uri_scheme_request_get_uri (WebKitURISchemeRequest *request); WEBKIT_API const gchar * -webkit_uri_scheme_request_get_path (WebKitURISchemeRequest *request); +webkit_uri_scheme_request_get_path (WebKitURISchemeRequest *request); + +WEBKIT_API WebKitWebView * +webkit_uri_scheme_request_get_web_view (WebKitURISchemeRequest *request); WEBKIT_API void -webkit_uri_scheme_request_finish (WebKitURISchemeRequest *request, - GInputStream *stream, - gint64 stream_length, - const gchar *mime_type); +webkit_uri_scheme_request_finish (WebKitURISchemeRequest *request, + GInputStream *stream, + gint64 stream_length, + const gchar *mime_type); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequestPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequestPrivate.h index 149813def..b7c011f66 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequestPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURISchemeRequestPrivate.h @@ -25,7 +25,7 @@ #include "WebKitWebContext.h" #include <WebKit2/WKSoupRequestManager.h> -WebKitURISchemeRequest* webkitURISchemeRequestCreate(WebKitWebContext*, WKSoupRequestManagerRef, WKURLRef, uint64_t requestID); +WebKitURISchemeRequest* webkitURISchemeRequestCreate(WebKitWebContext*, WKSoupRequestManagerRef, WKURLRef, WKPageRef, uint64_t requestID); uint64_t webkitURISchemeRequestGetID(WebKitURISchemeRequest*); void webkitURISchemeRequestCancel(WebKitURISchemeRequest*); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 5b2c26697..dab18a87d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -20,10 +20,10 @@ #include "config.h" #include "WebKitWebContext.h" -#include "WebContext.h" #include "WebKitCookieManagerPrivate.h" #include "WebKitDownloadClient.h" #include "WebKitDownloadPrivate.h" +#include "WebKitFaviconDatabasePrivate.h" #include "WebKitGeolocationProvider.h" #include "WebKitPluginPrivate.h" #include "WebKitPrivate.h" @@ -32,7 +32,9 @@ #include "WebKitTextChecker.h" #include "WebKitURISchemeRequestPrivate.h" #include "WebKitWebContextPrivate.h" +#include "WebResourceCacheManagerProxy.h" #include <WebCore/FileSystem.h> +#include <WebCore/IconDatabase.h> #include <WebCore/Language.h> #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> @@ -42,8 +44,6 @@ #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> -using namespace WebKit; - enum { DOWNLOAD_STARTED, @@ -93,11 +93,12 @@ typedef HashMap<String, RefPtr<WebKitURISchemeHandler> > URISchemeHandlerMap; typedef HashMap<uint64_t, GRefPtr<WebKitURISchemeRequest> > URISchemeRequestMap; struct _WebKitWebContextPrivate { - WKRetainPtr<WKContextRef> context; + RefPtr<WebContext> context; GRefPtr<WebKitCookieManager> cookieManager; + GRefPtr<WebKitFaviconDatabase> faviconDatabase; GRefPtr<WebKitSecurityManager> securityManager; - WKRetainPtr<WKSoupRequestManagerRef> requestManager; + RefPtr<WebSoupRequestManagerProxy> requestManager; URISchemeHandlerMap uriSchemeHandlers; URISchemeRequestMap uriSchemeRequests; #if ENABLE(GEOLOCATION) @@ -106,6 +107,7 @@ struct _WebKitWebContextPrivate { #if ENABLE(SPELLCHECK) OwnPtr<WebKitTextChecker> textChecker; #endif + CString faviconDatabaseDirectory; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -152,17 +154,20 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass static gpointer createDefaultWebContext(gpointer) { static GRefPtr<WebKitWebContext> webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL))); - webContext->priv->context = WKContextCreate(); - webContext->priv->requestManager = WKContextGetSoupRequestManager(webContext->priv->context.get()); - WKContextSetCacheModel(webContext->priv->context.get(), kWKCacheModelPrimaryWebBrowser); + WebKitWebContextPrivate* priv = webContext->priv; + + priv->context = WebContext::create(String()); + priv->requestManager = webContext->priv->context->soupRequestManagerProxy(); + priv->context->setCacheModel(CacheModelPrimaryWebBrowser); + attachDownloadClientToContext(webContext.get()); attachRequestManagerClientToContext(webContext.get()); + #if ENABLE(GEOLOCATION) - WKGeolocationManagerRef wkGeolocationManager = WKContextGetGeolocationManager(webContext->priv->context.get()); - webContext->priv->geolocationProvider = WebKitGeolocationProvider::create(wkGeolocationManager); + priv->geolocationProvider = WebKitGeolocationProvider::create(toAPI(priv->context->geolocationManagerProxy())); #endif #if ENABLE(SPELLCHECK) - webContext->priv->textChecker = WebKitTextChecker::create(); + priv->textChecker = WebKitTextChecker::create(); #endif return webContext.get(); } @@ -206,26 +211,26 @@ WebKitWebContext* webkit_web_context_get_default(void) */ void webkit_web_context_set_cache_model(WebKitWebContext* context, WebKitCacheModel model) { - WKCacheModel cacheModel; + CacheModel cacheModel; g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); switch (model) { case WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER: - cacheModel = kWKCacheModelDocumentViewer; + cacheModel = CacheModelDocumentViewer; break; case WEBKIT_CACHE_MODEL_WEB_BROWSER: - cacheModel = kWKCacheModelPrimaryWebBrowser; + cacheModel = CacheModelPrimaryWebBrowser; break; case WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER: - cacheModel = kWKCacheModelDocumentBrowser; + cacheModel = CacheModelDocumentBrowser; break; default: g_assert_not_reached(); } - WebKitWebContextPrivate* priv = context->priv; - if (cacheModel != WKContextGetCacheModel(priv->context.get())) - WKContextSetCacheModel(priv->context.get(), cacheModel); + + if (cacheModel != context->priv->context->cacheModel()) + context->priv->context->setCacheModel(cacheModel); } /** @@ -242,13 +247,12 @@ WebKitCacheModel webkit_web_context_get_cache_model(WebKitWebContext* context) { g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_CACHE_MODEL_WEB_BROWSER); - WebKitWebContextPrivate* priv = context->priv; - switch (WKContextGetCacheModel(priv->context.get())) { - case kWKCacheModelDocumentViewer: + switch (context->priv->context->cacheModel()) { + case CacheModelDocumentViewer: return WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER; - case kWKCacheModelPrimaryWebBrowser: + case CacheModelPrimaryWebBrowser: return WEBKIT_CACHE_MODEL_WEB_BROWSER; - case kWKCacheModelDocumentBrowser: + case CacheModelDocumentBrowser: return WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER; default: g_assert_not_reached(); @@ -268,11 +272,10 @@ void webkit_web_context_clear_cache(WebKitWebContext* context) { g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); - WebKitWebContextPrivate* priv = context->priv; - WKResourceCacheManagerClearCacheForAllOrigins(WKContextGetResourceCacheManager(priv->context.get()), WKResourceCachesToClearAll); + context->priv->context->resourceCacheManagerProxy()->clearCacheForAllOrigins(AllResourceCaches); } -typedef HashMap<WKDownloadRef, GRefPtr<WebKitDownload> > DownloadsMap; +typedef HashMap<DownloadProxy*, GRefPtr<WebKitDownload> > DownloadsMap; static DownloadsMap& downloadsMap() { @@ -295,12 +298,9 @@ WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); g_return_val_if_fail(uri, 0); - WebKitWebContextPrivate* priv = context->priv; - WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(uri)); - WKRetainPtr<WKURLRequestRef> wkRequest(AdoptWK, WKURLRequestCreateWithWKURL(wkURL.get())); - WKRetainPtr<WKDownloadRef> wkDownload = WKContextDownloadURLRequest(priv->context.get(), wkRequest.get()); - WebKitDownload* download = webkitDownloadCreate(wkDownload.get()); - downloadsMap().set(wkDownload.get(), download); + DownloadProxy* downloadProxy = context->priv->context->download(0, WebCore::ResourceRequest(String::fromUTF8(uri))); + WebKitDownload* download = webkitDownloadCreate(toAPI(downloadProxy)); + downloadsMap().set(downloadProxy, download); return download; } @@ -318,11 +318,107 @@ WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* con WebKitWebContextPrivate* priv = context->priv; if (!priv->cookieManager) - priv->cookieManager = adoptGRef(webkitCookieManagerCreate(WKContextGetCookieManager(priv->context.get()))); + priv->cookieManager = adoptGRef(webkitCookieManagerCreate(toAPI(priv->context->cookieManagerProxy()))); return priv->cookieManager.get(); } +static void ensureFaviconDatabase(WebKitWebContext* context) +{ + WebKitWebContextPrivate* priv = context->priv; + if (priv->faviconDatabase) + return; + + priv->faviconDatabase = adoptGRef(webkitFaviconDatabaseCreate(priv->context->iconDatabase())); +} + +/** + * webkit_web_context_set_favicon_database_directory: + * @context: a #WebKitWebContext + * @path: (allow-none): an absolute path to the icon database + * directory or %NULL to use the defaults + * + * Set the directory path to be used to store the favicons database + * for @context on disk. Passing %NULL as @path means using the + * default directory for the platform (see g_get_user_data_dir()). + * + * Calling this method also means enabling the favicons database for + * its use from the applications, so that's why it's expected to be + * called only once. Further calls for the same instance of + * #WebKitWebContext won't cause any effect. + */ +void webkit_web_context_set_favicon_database_directory(WebKitWebContext* context, const gchar* path) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + + WebKitWebContextPrivate* priv = context->priv; + WebIconDatabase* iconDatabase = priv->context->iconDatabase(); + if (iconDatabase->isOpen()) + return; + + ensureFaviconDatabase(context); + + // Use default if 0 is passed as parameter. + String directoryPath = WebCore::filenameToString(path); + priv->faviconDatabaseDirectory = directoryPath.isEmpty() + ? priv->context->iconDatabasePath().utf8() + : directoryPath.utf8(); + + // Build the full path to the icon database file on disk. + GOwnPtr<gchar> faviconDatabasePath(g_build_filename(priv->faviconDatabaseDirectory.data(), + WebCore::IconDatabase::defaultDatabaseFilename().utf8().data(), + NULL)); + + // Setting the path will cause the icon database to be opened. + priv->context->setIconDatabasePath(WebCore::filenameToString(faviconDatabasePath.get())); +} + +/** + * webkit_web_context_get_favicon_database_directory: + * @context: a #WebKitWebContext + * + * Get the directory path being used to store the favicons database + * for @context, or %NULL if + * webkit_web_context_set_favicon_database_directory() hasn't been + * called yet. + * + * This function will always return the same path after having called + * webkit_web_context_set_favicon_database_directory() for the first + * time. + * + * Returns: (transfer none): the path of the directory of the favicons + * database associated with @context, or %NULL. + */ +const gchar* webkit_web_context_get_favicon_database_directory(WebKitWebContext *context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + + WebKitWebContextPrivate* priv = context->priv; + if (priv->faviconDatabaseDirectory.isNull()) + return 0; + + return priv->faviconDatabaseDirectory.data(); +} + +/** + * webkit_web_context_get_favicon_database: + * @context: a #WebKitWebContext + * + * Get the #WebKitFaviconDatabase associated with @context. + * + * To initialize the database you need to call + * webkit_web_context_set_favicon_database_directory(). + * + * Returns: (transfer none): the #WebKitFaviconDatabase of @context. + */ +WebKitFaviconDatabase* webkit_web_context_get_favicon_database(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + + ensureFaviconDatabase(context); + return context->priv->faviconDatabase.get(); +} + /** * webkit_web_context_get_security_manager: * @context: a #WebKitWebContext @@ -354,7 +450,7 @@ void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* conte g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); g_return_if_fail(directory); - toImpl(context->priv->context.get())->setAdditionalPluginsDirectory(WebCore::filenameToString(directory)); + context->priv->context->setAdditionalPluginsDirectory(WebCore::filenameToString(directory)); } struct GetPluginsAsyncData { @@ -365,7 +461,7 @@ WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetPluginsAsyncData) static void webkitWebContextGetPluginThread(GSimpleAsyncResult* result, GObject* object, GCancellable*) { GetPluginsAsyncData* data = static_cast<GetPluginsAsyncData*>(g_simple_async_result_get_op_res_gpointer(result)); - data->plugins = toImpl(WEBKIT_WEB_CONTEXT(object)->priv->context.get())->pluginInfoStore().plugins(); + data->plugins = WEBKIT_WEB_CONTEXT(object)->priv->context->pluginInfoStore().plugins(); } /** @@ -472,8 +568,7 @@ void webkit_web_context_register_uri_scheme(WebKitWebContext* context, const cha RefPtr<WebKitURISchemeHandler> handler = adoptRef(new WebKitURISchemeHandler(callback, userData, destroyNotify)); context->priv->uriSchemeHandlers.set(String::fromUTF8(scheme), handler.get()); - WKRetainPtr<WKStringRef> wkScheme(AdoptWK, WKStringCreateWithUTF8CString(scheme)); - WKSoupRequestManagerRegisterURIScheme(context->priv->requestManager.get(), wkScheme.get()); + context->priv->requestManager->registerURIScheme(String::fromUTF8(scheme)); } /** @@ -587,20 +682,20 @@ void webkit_web_context_set_preferred_languages(WebKitWebContext* context, const WebCore::languageDidChange(); } -WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) +WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy* downloadProxy) { - GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); + GRefPtr<WebKitDownload> download = downloadsMap().get(downloadProxy); if (download) return download.get(); - download = adoptGRef(webkitDownloadCreate(wkDownload)); - downloadsMap().set(wkDownload, download.get()); + download = adoptGRef(webkitDownloadCreate(toAPI(downloadProxy))); + downloadsMap().set(downloadProxy, download.get()); return download.get(); } -void webkitWebContextRemoveDownload(WKDownloadRef wkDownload) +void webkitWebContextRemoveDownload(DownloadProxy* downloadProxy) { - downloadsMap().remove(wkDownload); + downloadsMap().remove(downloadProxy); } void webkitWebContextDownloadStarted(WebKitWebContext* context, WebKitDownload* download) @@ -608,14 +703,14 @@ void webkitWebContextDownloadStarted(WebKitWebContext* context, WebKitDownload* g_signal_emit(context, signals[DOWNLOAD_STARTED], 0, download); } -WKContextRef webkitWebContextGetWKContext(WebKitWebContext* context) +WebContext* webkitWebContextGetContext(WebKitWebContext* context) { g_assert(WEBKIT_IS_WEB_CONTEXT(context)); return context->priv->context.get(); } -WKSoupRequestManagerRef webkitWebContextGetRequestManager(WebKitWebContext* context) +WebSoupRequestManagerProxy* webkitWebContextGetRequestManager(WebKitWebContext* context) { return context->priv->requestManager.get(); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index f77086f4d..ae79bec87 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -28,6 +28,7 @@ #include <webkit2/WebKitCookieManager.h> #include <webkit2/WebKitDefines.h> #include <webkit2/WebKitDownload.h> +#include <webkit2/WebKitFaviconDatabase.h> #include <webkit2/WebKitSecurityManager.h> #include <webkit2/WebKitURISchemeRequest.h> @@ -114,6 +115,15 @@ webkit_web_context_download_uri (WebKitWebContext WEBKIT_API WebKitCookieManager * webkit_web_context_get_cookie_manager (WebKitWebContext *context); +WEBKIT_API WebKitFaviconDatabase * +webkit_web_context_get_favicon_database (WebKitWebContext *context); + +WEBKIT_API void +webkit_web_context_set_favicon_database_directory (WebKitWebContext *context, + const gchar *path); +WEBKIT_API const gchar * +webkit_web_context_get_favicon_database_directory (WebKitWebContext *context); + WEBKIT_API WebKitSecurityManager * webkit_web_context_get_security_manager (WebKitWebContext *context); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h index 9e5536b3a..67be48d5c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h @@ -26,15 +26,20 @@ #ifndef WebKitWebContextPrivate_h #define WebKitWebContextPrivate_h +#include "DownloadProxy.h" +#include "WebContext.h" #include "WebKitPrivate.h" #include "WebKitURISchemeRequest.h" #include "WebKitWebContext.h" +#include "WebSoupRequestManagerProxy.h" -WKContextRef webkitWebContextGetWKContext(WebKitWebContext*); -WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef); -void webkitWebContextRemoveDownload(WKDownloadRef); +using namespace WebKit; + +WebContext* webkitWebContextGetContext(WebKitWebContext*); +WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy*); +void webkitWebContextRemoveDownload(DownloadProxy*); void webkitWebContextDownloadStarted(WebKitWebContext*, WebKitDownload*); -WKSoupRequestManagerRef webkitWebContextGetRequestManager(WebKitWebContext*); +WebSoupRequestManagerProxy* webkitWebContextGetRequestManager(WebKitWebContext*); void webkitWebContextReceivedURIRequest(WebKitWebContext*, WebKitURISchemeRequest*); void webkitWebContextDidFailToLoadURIRequest(WebKitWebContext*, uint64_t requestID); void webkitWebContextDidFinishURIRequest(WebKitWebContext*, uint64_t requestID); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index 301be899c..236a4f304 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -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" @@ -56,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> @@ -102,6 +104,7 @@ enum { PROP_WEB_CONTEXT, PROP_TITLE, PROP_ESTIMATED_LOAD_PROGRESS, + PROP_FAVICON, PROP_URI, PROP_ZOOM_LEVEL, PROP_IS_LOADING @@ -120,6 +123,7 @@ struct _WebKitWebViewPrivate { bool waitingForMainResource; gulong mainResourceResponseHandlerID; + gulong watchForChangesInFaviconHandlerID; WebKitLoadEvent lastDelayedEvent; GRefPtr<WebKitBackForwardList> backForwardList; @@ -139,6 +143,9 @@ struct _WebKitWebViewPrivate { ResourcesMap subresourcesMap; GRefPtr<WebKitWebInspector> inspector; + + RefPtr<cairo_surface_t> favicon; + GRefPtr<GCancellable> faviconCancellable; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -260,6 +267,37 @@ static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebVie getPage(webView)->setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings))); } +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; + + // 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) { webView->priv->settings = settings; @@ -285,6 +323,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); @@ -337,7 +398,7 @@ static void webkitWebViewConstructed(GObject* object) WebKitWebViewPrivate* priv = webView->priv; WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView); - webkitWebViewBaseCreateWebPage(webViewBase, toImpl(webkitWebContextGetWKContext(priv->context)), 0); + webkitWebViewBaseCreateWebPage(webViewBase, webkitWebContextGetContext(priv->context), 0); attachLoaderClientToView(webView); attachUIClientToView(webView); @@ -385,6 +446,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; @@ -411,8 +475,10 @@ static void webkitWebViewFinalize(GObject* object) 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); priv->~WebKitWebViewPrivate(); G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object); @@ -500,6 +566,18 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) 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: * * The current active URI of the #WebKitWebView. @@ -1158,9 +1236,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); @@ -1182,29 +1261,52 @@ static void webkitWebViewEmitDelayedLoadEvents(WebKitWebView* webView) 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); - webView->priv->loadingResourcesMap.clear(); - webView->priv->mainResource = 0; - webView->priv->waitingForMainResource = false; + webkitWebViewCancelFaviconRequest(webView); + priv->loadingResourcesMap.clear(); + priv->mainResource = 0; + priv->waitingForMainResource = false; } else if (loadEvent == WEBKIT_LOAD_COMMITTED) { - webView->priv->subresourcesMap.clear(); - if (!webView->priv->mainResource) { + webkitWebViewRequestFavicon(webView); + + priv->subresourcesMap.clear(); + if (!priv->mainResource) { // When a page is loaded from the history cache, the main resource load callbacks // are called when the main frame load is finished. We want to make sure there's a // main resource available when load has been committed, so we delay the emission of // load-changed signal until main resource object has been created. - webView->priv->waitingForMainResource = true; + priv->waitingForMainResource = true; } else setCertificateToMainResource(webView); } - if (webView->priv->waitingForMainResource) - webView->priv->lastDelayedEvent = loadEvent; + if (priv->waitingForMainResource) + priv->lastDelayedEvent = loadEvent; else webkitWebViewEmitLoadChanged(webView, loadEvent); } @@ -1850,6 +1952,26 @@ const gchar* webkit_web_view_get_uri(WebKitWebView* webView) } /** + * 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 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) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + if (webView->priv->activeURI.isNull()) + return 0; + + return webView->priv->favicon.get(); +} + +/** * webkit_web_view_get_custom_charset: * @web_view: a #WebKitWebView * @@ -2192,7 +2314,7 @@ static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSeri g_simple_async_result_take_error(result.get(), error); else if (wkSerializedScriptValue) { GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get())))); - data->scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue); + data->scriptResult = webkitJavascriptResultCreate(webView.get(), toImpl(wkSerializedScriptValue)); } else { g_set_error_literal(&error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED, _("An exception was raised in JavaScript")); g_simple_async_result_take_error(result.get(), error); @@ -2307,6 +2429,94 @@ WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* web return data->scriptResult ? webkit_javascript_result_ref(data->scriptResult) : 0; } +static void resourcesStreamReadCallback(GObject* object, GAsyncResult* result, gpointer userData) +{ + GOutputStream* outputStream = G_OUTPUT_STREAM(object); + GRefPtr<GSimpleAsyncResult> runJavascriptResult = adoptGRef(G_SIMPLE_ASYNC_RESULT(userData)); + + GError* error = 0; + g_output_stream_splice_finish(outputStream, result, &error); + if (error) { + g_simple_async_result_take_error(runJavascriptResult.get(), error); + g_simple_async_result_complete(runJavascriptResult.get()); + return; + } + + GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(runJavascriptResult.get())))); + gpointer outputStreamData = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(outputStream)); + getPage(webView.get())->runJavaScriptInMainFrame(String::fromUTF8(reinterpret_cast<const gchar*>(outputStreamData)), + ScriptValueCallback::create(runJavascriptResult.leakRef(), webkitWebViewRunJavaScriptCallback)); +} + +/** + * webkit_web_view_run_javascript_from_gresource: + * @web_view: a #WebKitWebView + * @resource: the location of the resource to load + * @cancellable: (allow-none): a #GCancellable or %NULL to ignore + * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously run the script from @resource in the context of the + * current page in @web_view. + * + * When the operation is finished, @callback will be called. You can + * then call webkit_web_view_run_javascript_from_gresource_finish() to get the result + * of the operation. + */ +void webkit_web_view_run_javascript_from_gresource(WebKitWebView* webView, const gchar* resource, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); + g_return_if_fail(resource); + + GRefPtr<GSimpleAsyncResult> result = adoptGRef(g_simple_async_result_new(G_OBJECT(webView), callback, userData, + reinterpret_cast<gpointer>(webkit_web_view_run_javascript_from_gresource))); + RunJavaScriptAsyncData* data = createRunJavaScriptAsyncData(); + data->cancellable = cancellable; + g_simple_async_result_set_op_res_gpointer(result.get(), data, reinterpret_cast<GDestroyNotify>(destroyRunJavaScriptAsyncData)); + + GError* error = 0; + GRefPtr<GInputStream> inputStream = adoptGRef(g_resources_open_stream(resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &error)); + if (error) { + g_simple_async_result_take_error(result.get(), error); + g_simple_async_result_complete_in_idle(result.get()); + return; + } + + GRefPtr<GOutputStream> outputStream = adoptGRef(g_memory_output_stream_new(0, 0, fastRealloc, fastFree)); + g_output_stream_splice_async(outputStream.get(), inputStream.get(), + static_cast<GOutputStreamSpliceFlags>(G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET), + G_PRIORITY_DEFAULT, + cancellable, resourcesStreamReadCallback, result.leakRef()); +} + +/** + * webkit_web_view_run_javascript_from_gresource_finish: + * @web_view: a #WebKitWebView + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_web_view_run_javascript_from_gresource(). + * + * Check webkit_web_view_run_javascript_finish() for a usage example. + * + * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script + * or %NULL in case of error + */ +WebKitJavascriptResult* webkit_web_view_run_javascript_from_gresource_finish(WebKitWebView* webView, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_view_run_javascript_from_gresource); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + RunJavaScriptAsyncData* data = static_cast<RunJavaScriptAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return data->scriptResult ? webkit_javascript_result_ref(data->scriptResult) : 0; +} + /** * webkit_web_view_get_main_resource: * @web_view: a #WebKitWebView @@ -2341,7 +2551,7 @@ GList* webkit_web_view_get_subresources(WebKitWebView* webView) WebKitWebViewPrivate* priv = webView->priv; ResourcesMap::const_iterator end = priv->subresourcesMap.end(); for (ResourcesMap::const_iterator it = priv->subresourcesMap.begin(); it != end; ++it) - subresources = g_list_prepend(subresources, it->second.get()); + subresources = g_list_prepend(subresources, it->value.get()); return g_list_reverse(subresources); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h index 8a397b752..ac2e2813f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h @@ -191,170 +191,185 @@ struct _WebKitWebViewClass { }; WEBKIT_API GType -webkit_web_view_get_type (void); +webkit_web_view_get_type (void); WEBKIT_API GtkWidget * -webkit_web_view_new (void); +webkit_web_view_new (void); WEBKIT_API GtkWidget * -webkit_web_view_new_with_context (WebKitWebContext *context); +webkit_web_view_new_with_context (WebKitWebContext *context); WEBKIT_API WebKitWebContext * -webkit_web_view_get_context (WebKitWebView *web_view); +webkit_web_view_get_context (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_load_uri (WebKitWebView *web_view, - const gchar *uri); +webkit_web_view_load_uri (WebKitWebView *web_view, + const gchar *uri); WEBKIT_API void -webkit_web_view_load_html (WebKitWebView *web_view, - const gchar *content, - const gchar *base_uri); +webkit_web_view_load_html (WebKitWebView *web_view, + const gchar *content, + const gchar *base_uri); WEBKIT_API void -webkit_web_view_load_alternate_html (WebKitWebView *web_view, - const gchar *content, - const gchar *content_uri, - const gchar *base_uri); +webkit_web_view_load_alternate_html (WebKitWebView *web_view, + const gchar *content, + const gchar *content_uri, + const gchar *base_uri); WEBKIT_API void -webkit_web_view_load_plain_text (WebKitWebView *web_view, - const gchar *plain_text); +webkit_web_view_load_plain_text (WebKitWebView *web_view, + const gchar *plain_text); WEBKIT_API void -webkit_web_view_load_request (WebKitWebView *web_view, - WebKitURIRequest *request); +webkit_web_view_load_request (WebKitWebView *web_view, + WebKitURIRequest *request); WEBKIT_API void -webkit_web_view_stop_loading (WebKitWebView *web_view); +webkit_web_view_stop_loading (WebKitWebView *web_view); WEBKIT_API gboolean -webkit_web_view_is_loading (WebKitWebView *web_view); +webkit_web_view_is_loading (WebKitWebView *web_view); WEBKIT_API const gchar * -webkit_web_view_get_title (WebKitWebView *web_view); +webkit_web_view_get_title (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_reload (WebKitWebView *web_view); +webkit_web_view_reload (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_reload_bypass_cache (WebKitWebView *web_view); +webkit_web_view_reload_bypass_cache (WebKitWebView *web_view); WEBKIT_API gdouble -webkit_web_view_get_estimated_load_progress (WebKitWebView *web_view); +webkit_web_view_get_estimated_load_progress (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_go_back (WebKitWebView *web_view); +webkit_web_view_go_back (WebKitWebView *web_view); WEBKIT_API gboolean -webkit_web_view_can_go_back (WebKitWebView *web_view); +webkit_web_view_can_go_back (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_go_forward (WebKitWebView *web_view); +webkit_web_view_go_forward (WebKitWebView *web_view); WEBKIT_API gboolean -webkit_web_view_can_go_forward (WebKitWebView *web_view); +webkit_web_view_can_go_forward (WebKitWebView *web_view); WEBKIT_API WebKitBackForwardList * -webkit_web_view_get_back_forward_list (WebKitWebView *web_view); +webkit_web_view_get_back_forward_list (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_go_to_back_forward_list_item (WebKitWebView *web_view, - WebKitBackForwardListItem *list_item); +webkit_web_view_go_to_back_forward_list_item (WebKitWebView *web_view, + WebKitBackForwardListItem *list_item); WEBKIT_API const gchar * -webkit_web_view_get_uri (WebKitWebView *web_view); +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); +webkit_web_view_get_custom_charset (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_set_custom_charset (WebKitWebView *web_view, - const gchar *charset); +webkit_web_view_set_custom_charset (WebKitWebView *web_view, + const gchar *charset); WEBKIT_API void -webkit_web_view_set_settings (WebKitWebView *web_view, - WebKitSettings *settings); +webkit_web_view_set_settings (WebKitWebView *web_view, + WebKitSettings *settings); WEBKIT_API WebKitSettings * -webkit_web_view_get_settings (WebKitWebView *web_view); +webkit_web_view_get_settings (WebKitWebView *web_view); WEBKIT_API WebKitWindowProperties * -webkit_web_view_get_window_properties (WebKitWebView *web_view); +webkit_web_view_get_window_properties (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_set_zoom_level (WebKitWebView *web_view, - gdouble zoom_level); +webkit_web_view_set_zoom_level (WebKitWebView *web_view, + gdouble zoom_level); WEBKIT_API gdouble -webkit_web_view_get_zoom_level (WebKitWebView *web_view); +webkit_web_view_get_zoom_level (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_can_execute_editing_command (WebKitWebView *web_view, - const gchar *command, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +webkit_web_view_can_execute_editing_command (WebKitWebView *web_view, + const gchar *command, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); WEBKIT_API gboolean -webkit_web_view_can_execute_editing_command_finish (WebKitWebView *web_view, - GAsyncResult *result, - GError **error); +webkit_web_view_can_execute_editing_command_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); WEBKIT_API void -webkit_web_view_execute_editing_command (WebKitWebView *web_view, - const gchar *command); +webkit_web_view_execute_editing_command (WebKitWebView *web_view, + const gchar *command); WEBKIT_API WebKitFindController * -webkit_web_view_get_find_controller (WebKitWebView *web_view); +webkit_web_view_get_find_controller (WebKitWebView *web_view); WEBKIT_API JSGlobalContextRef -webkit_web_view_get_javascript_global_context (WebKitWebView *web_view); +webkit_web_view_get_javascript_global_context (WebKitWebView *web_view); WEBKIT_API void -webkit_web_view_run_javascript (WebKitWebView *web_view, - const gchar *script, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +webkit_web_view_run_javascript (WebKitWebView *web_view, + const gchar *script, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +WEBKIT_API WebKitJavascriptResult * +webkit_web_view_run_javascript_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); + +WEBKIT_API void +webkit_web_view_run_javascript_from_gresource (WebKitWebView *web_view, + const gchar *resource, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + WEBKIT_API WebKitJavascriptResult * -webkit_web_view_run_javascript_finish (WebKitWebView *web_view, - GAsyncResult *result, - GError **error); +webkit_web_view_run_javascript_from_gresource_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); WEBKIT_API WebKitWebResource * -webkit_web_view_get_main_resource (WebKitWebView *web_view); +webkit_web_view_get_main_resource (WebKitWebView *web_view); WEBKIT_API GList * -webkit_web_view_get_subresources (WebKitWebView *web_view); +webkit_web_view_get_subresources (WebKitWebView *web_view); WEBKIT_API WebKitWebInspector * -webkit_web_view_get_inspector (WebKitWebView *web_view); +webkit_web_view_get_inspector (WebKitWebView *web_view); WEBKIT_API gboolean -webkit_web_view_can_show_mime_type (WebKitWebView *web_view, - const gchar *mime_type); +webkit_web_view_can_show_mime_type (WebKitWebView *web_view, + const gchar *mime_type); WEBKIT_API void -webkit_web_view_save (WebKitWebView *web_view, - WebKitSaveMode save_mode, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +webkit_web_view_save (WebKitWebView *web_view, + WebKitSaveMode save_mode, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); WEBKIT_API GInputStream * -webkit_web_view_save_finish (WebKitWebView *web_view, - GAsyncResult *result, - GError **error); +webkit_web_view_save_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); WEBKIT_API void -webkit_web_view_save_to_file (WebKitWebView *web_view, - GFile *file, - WebKitSaveMode save_mode, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +webkit_web_view_save_to_file (WebKitWebView *web_view, + GFile *file, + WebKitSaveMode save_mode, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); WEBKIT_API gboolean -webkit_web_view_save_to_file_finish (WebKitWebView *web_view, - GAsyncResult *result, - GError **error); +webkit_web_view_save_to_file_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index b42b2ee8f..e5bac671e 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -75,6 +75,10 @@ using namespace WebCore; typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap; +#if USE(TEXTURE_MAPPER_GL) +void redirectedWindowDamagedCallback(void* data); +#endif + struct _WebKitWebViewBasePrivate { WebKitWebViewChildrenMap children; OwnPtr<PageClientImpl> pageClient; @@ -111,7 +115,6 @@ struct _WebKitWebViewBasePrivate { #if USE(TEXTURE_MAPPER_GL) OwnPtr<RedirectedXCompositeWindow> redirectedWindow; - bool readyToRenderAcceleratedCompositingResults; #endif }; @@ -300,7 +303,7 @@ static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean i WebKitWebViewChildrenMap children = priv->children; WebKitWebViewChildrenMap::const_iterator end = children.end(); for (WebKitWebViewChildrenMap::const_iterator current = children.begin(); current != end; ++current) - (*callback)(current->first, callbackData); + (*callback)(current->key, callbackData); if (includeInternals && priv->inspectorView) (*callback)(priv->inspectorView, callbackData); @@ -351,7 +354,8 @@ static void webkit_web_view_base_init(WebKitWebViewBase* webkitWebViewBase) #if USE(TEXTURE_MAPPER_GL) priv->redirectedWindow = RedirectedXCompositeWindow::create(IntSize(1, 1)); - priv->readyToRenderAcceleratedCompositingResults = false; + if (priv->redirectedWindow) + priv->redirectedWindow->setDamageNotifyCallback(redirectedWindowDamagedCallback, webkitWebViewBase); #endif } @@ -364,10 +368,9 @@ static bool webkitWebViewRenderAcceleratedCompositingResults(WebKitWebViewBase* // To avoid flashes when initializing accelerated compositing for the first // time, we wait until we know there's a frame ready before rendering. WebKitWebViewBasePrivate* priv = webViewBase->priv; - if (!priv->readyToRenderAcceleratedCompositingResults) + if (!priv->redirectedWindow) return false; - ASSERT(priv->redirectedWindow); cairo_rectangle(cr, clipRect->x, clipRect->y, clipRect->width, clipRect->height); cairo_surface_t* surface = priv->redirectedWindow->cairoSurfaceForWidget(GTK_WIDGET(webViewBase)); cairo_set_source_surface(cr, surface, 0, 0); @@ -430,7 +433,7 @@ static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase } #if USE(TEXTURE_MAPPER_GL) - if (sizeChanged) + if (sizeChanged && webViewBase->priv->redirectedWindow) webViewBase->priv->redirectedWindow->resize(viewRect.size()); #endif @@ -801,7 +804,8 @@ void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WebCon #endif #if USE(TEXTURE_MAPPER_GL) - priv->pageProxy->setAcceleratedCompositingWindowId(priv->redirectedWindow->windowId()); + if (priv->redirectedWindow) + priv->pageProxy->setAcceleratedCompositingWindowId(priv->redirectedWindow->windowId()); #endif } @@ -928,37 +932,9 @@ GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebView } #if USE(TEXTURE_MAPPER_GL) -static gboolean queueAnotherDrawOfAcceleratedCompositingResults(gpointer* webViewBasePointer) +void redirectedWindowDamagedCallback(void* data) { - // The WebViewBase may have been destroyed in the time since we queued this - // draw and the time we are actually executing. - if (!*webViewBasePointer) { - fastFree(webViewBasePointer); - return FALSE; - } - - WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(*webViewBasePointer); - gtk_widget_queue_draw(GTK_WIDGET(webViewBase)); - webViewBase->priv->readyToRenderAcceleratedCompositingResults = true; - - g_object_remove_weak_pointer(G_OBJECT(webViewBase), webViewBasePointer); - fastFree(webViewBasePointer); - - return FALSE; -} - -void webkitWebViewBaseQueueDrawOfAcceleratedCompositingResults(WebKitWebViewBase* webViewBase) -{ - gtk_widget_queue_draw(GTK_WIDGET(webViewBase)); - - // Redraw again, one frame later, as it might take some time for the new GL frame to be available. - // This prevents the display from always being one frame behind in the case GL hasn't yet finished - // rendering to the window. - // TODO: Add XDamage support to RedirectedXCompositeWindow to accomplish this. - gpointer* webViewBasePointer = static_cast<gpointer*>(fastMalloc(sizeof(gpointer))); - g_object_add_weak_pointer(G_OBJECT(webViewBase), webViewBasePointer); - *webViewBasePointer = webViewBase; - g_timeout_add(1000 / 60, reinterpret_cast<GSourceFunc>(queueAnotherDrawOfAcceleratedCompositingResults), webViewBasePointer); + gtk_widget_queue_draw(GTK_WIDGET(data)); } #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index a7f34e6d1..8623af33e 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -30,6 +30,7 @@ <xi:include href="xml/WebKitPrintOperation.xml"/> <xi:include href="xml/WebKitWebResource.xml"/> <xi:include href="xml/WebKitError.xml"/> + <xi:include href="xml/WebKitFaviconDatabase.xml"/> <xi:include href="xml/WebKitFileChooserRequest.xml"/> <xi:include href="xml/WebKitFindController.xml"/> <xi:include href="xml/WebKitCookieManager.xml"/> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index 1827b6b16..f56267b9a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -30,6 +30,9 @@ webkit_web_context_set_cache_model webkit_web_context_clear_cache webkit_web_context_download_uri webkit_web_context_get_cookie_manager +webkit_web_context_get_favicon_database +webkit_web_context_set_favicon_database_directory +webkit_web_context_get_favicon_database_directory webkit_web_context_get_security_manager webkit_web_context_set_additional_plugins_directory webkit_web_context_get_plugins @@ -98,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 @@ -111,6 +115,8 @@ webkit_web_view_get_inspector webkit_web_view_get_javascript_global_context webkit_web_view_run_javascript webkit_web_view_run_javascript_finish +webkit_web_view_run_javascript_from_gresource +webkit_web_view_run_javascript_from_gresource_finish webkit_web_view_can_show_mime_type webkit_web_view_save webkit_web_view_save_finish @@ -291,6 +297,8 @@ webkit_settings_set_enable_page_cache webkit_settings_get_user_agent webkit_settings_set_user_agent webkit_settings_set_user_agent_with_application_details +webkit_settings_get_enable_smooth_scrolling +webkit_settings_set_enable_smooth_scrolling <SUBSECTION Standard> WebKitSettingsClass @@ -602,6 +610,31 @@ webkit_javascript_error_quark </SECTION> <SECTION> +<FILE>WebKitFaviconDatabase</FILE> +WebKitFaviconDatabase +WEBKIT_FAVICON_DATABASE_ERROR +WebKitFaviconDatabaseError +webkit_favicon_database_get_favicon +webkit_favicon_database_get_favicon_finish +webkit_favicon_database_get_favicon_uri +webkit_favicon_database_clear + +<SUBSECTION Standard> +WebKitFaviconDatabaseClass +WEBKIT_TYPE_FAVICON_DATABASE +WEBKIT_FAVICON_DATABASE +WEBKIT_IS_FAVICON_DATABASE +WEBKIT_FAVICON_DATABASE_CLASS +WEBKIT_IS_FAVICON_DATABASE_CLASS +WEBKIT_FAVICON_DATABASE_GET_CLASS + +<SUBSECTION Private> +WebKitFaviconDatabasePrivate +webkit_favicon_database_get_type +webkit_favicon_database_error_quark +</SECTION> + +<SECTION> <FILE>WebKitFileChooserRequest</FILE> WebKitFileChooserRequest webkit_file_chooser_request_get_mime_types @@ -745,6 +778,7 @@ WebKitURISchemeRequest webkit_uri_scheme_request_get_scheme webkit_uri_scheme_request_get_uri webkit_uri_scheme_request_get_path +webkit_uri_scheme_request_get_web_view webkit_uri_scheme_request_finish <SUBSECTION Standard> diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index 3fadf40b4..06ea1af7c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -11,6 +11,7 @@ TEST_PROGS += \ Programs/WebKit2APITests/TestResources \ Programs/WebKit2APITests/TestSSL \ Programs/WebKit2APITests/TestWebKitVersion \ + Programs/WebKit2APITests/TestWebKitFaviconDatabase \ Programs/WebKit2APITests/TestWebKitFindController \ Programs/WebKit2APITests/TestWebKitPolicyClient \ Programs/WebKit2APITests/TestWebKitSettings \ @@ -29,6 +30,7 @@ endif webkit2_tests_cppflags = \ -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs\" \ -DWEBKIT_SRC_DIR=\"${shell pwd}/${srcdir}\" \ + -DWEBKIT_DERIVED_SRC_DIR=\"${shell pwd}/${top_builddir}/DerivedSources\" \ $(javascriptcore_cppflags) \ -I$(srcdir)/Source/JavaScriptCore \ -I$(srcdir)/Source \ @@ -55,6 +57,12 @@ webkit2_tests_ldflags = \ -no-install \ -no-fast-install +DerivedSources/WebKit2/webkit2gtk-tests-resources.gresource: Source/WebKit2/UIProcess/API/gtk/tests/resources/webkit2gtk-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies $(srcdir)/Source/WebKit2/UIProcess/API/gtk/tests/resources/webkit2gtk-tests.gresource.xml) + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< + +DISTCLEANFILES += DerivedSources/WebKit2/webkit2gtk-tests-resources.gresource +noinst_DATA += DerivedSources/WebKit2/webkit2gtk-tests-resources.gresource + noinst_LTLIBRARIES += Libraries/libWebKit2APITestCore.la Libraries_libWebKit2APITestCore_la_SOURCES = \ Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp \ @@ -69,7 +77,9 @@ Libraries_libWebKit2APITestCore_la_CPPFLAGS = $(webkit2_tests_cppflags) EXTRA_DIST += \ Source/WebKit2/UIProcess/API/gtk/tests/resources/test-cert.pem \ - Source/WebKit2/UIProcess/API/gtk/tests/resources/test-key.pem + Source/WebKit2/UIProcess/API/gtk/tests/resources/test-key.pem \ + Source/WebKit2/UIProcess/API/gtk/tests/resources/webkit2gtk-tests.gresource.xml \ + Source/WebKit2/UIProcess/API/gtk/tests/resources/link-title.js Programs_WebKit2APITests_TestWebKitWebContext_SOURCES = \ Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp @@ -141,6 +151,12 @@ Programs_WebKit2APITests_TestPrinting_CPPFLAGS = $(webkit2_tests_cppflags) $(GTK Programs_WebKit2APITests_TestPrinting_LDADD = $(webkit2_tests_ldadd) $(GTK_UNIX_PRINTING_LIBS) Programs_WebKit2APITests_TestPrinting_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestWebKitFaviconDatabase_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp +Programs_WebKit2APITests_TestWebKitFaviconDatabase_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestWebKitFaviconDatabase_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestWebKitFaviconDatabase_LDFLAGS = $(webkit2_tests_ldflags) + Programs_WebKit2APITests_TestWebKitFindController_SOURCES = \ Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFindController.cpp Programs_WebKit2APITests_TestWebKitFindController_CPPFLAGS = $(webkit2_tests_cppflags) diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp index e70e391ff..b479366a4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp @@ -38,6 +38,11 @@ static void serverCallback(SoupServer* server, SoupMessage* msg, const char* pat return; } + if (g_str_has_suffix(path, "favicon.ico")) { + soup_message_set_status(msg, SOUP_STATUS_NOT_FOUND); + return; + } + soup_message_set_status(msg, SOUP_STATUS_OK); char* body = g_strdup_printf("<html><title>%s</title><body>%s</body></html>", path + 1, path + 1); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp index 2fe8998b5..94aeef6e1 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp @@ -295,7 +295,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* } else if (g_str_equal(path, "/image.png")) soup_message_headers_replace(message->response_headers, "Set-Cookie", "baz=qux; Max-Age=60"); else - g_assert_not_reached(); + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); soup_message_body_complete(message->response_body); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp index c3a14193d..8fcf33009 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp @@ -312,7 +312,8 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); soup_server_unpause_message(server, message); return; - } + } else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); soup_message_body_complete(message->response_body); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.cpp index 8622af19c..9db47f82b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.cpp @@ -25,12 +25,24 @@ void beforeAll(); void afterAll(); +static void registerGResource(void) +{ + GOwnPtr<char> resourcesPath(g_build_filename(WEBKIT_DERIVED_SRC_DIR, "WebKit2", "webkit2gtk-tests-resources.gresource", NULL)); + GResource* resource = g_resource_load(resourcesPath.get(), 0); + g_assert(resource); + + g_resources_register(resource); + g_resource_unref(resource); +} + int main(int argc, char** argv) { gtk_test_init(&argc, &argv, 0); g_setenv("WEBKIT_EXEC_PATH", WEBKIT_EXEC_PATH, FALSE); g_test_bug_base("https://bugs.webkit.org/"); + registerGResource(); + beforeAll(); int returnValue = g_test_run(); afterAll(); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp index 7e2e5de61..20b90b0b4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp @@ -80,6 +80,11 @@ public: { test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resource)); test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + + // Ignore favicons. + if (g_str_has_suffix(webkit_uri_request_get_uri(request), "favicon.ico")) + return; + test->resourceLoadStarted(resource, request); g_signal_connect(resource, "sent-request", G_CALLBACK(resourceSentRequestCallback), test); g_signal_connect(resource, "notify::response", G_CALLBACK(resourceReceivedResponseCallback), test); @@ -507,21 +512,31 @@ static void testWebResourceGetData(ResourcesTest* test, gconstpointer) static void testWebViewResourcesHistoryCache(SingleResourceLoadTest* test, gconstpointer) { - test->loadURI(kServer->getURIForPath("/").data()); + CString javascriptURI = kServer->getURIForPath("/javascript.html"); + test->loadURI(javascriptURI.data()); test->waitUntilResourceLoadFinished(); - g_assert(webkit_web_view_get_main_resource(test->m_webView)); + WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_resource_get_uri(resource), ==, javascriptURI.data()); - test->loadURI(kServer->getURIForPath("/javascript.html").data()); + CString simpleStyleCSSURI = kServer->getURIForPath("/simple-style-css.html"); + test->loadURI(simpleStyleCSSURI.data()); test->waitUntilResourceLoadFinished(); - g_assert(webkit_web_view_get_main_resource(test->m_webView)); + resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_resource_get_uri(resource), ==, simpleStyleCSSURI.data()); test->goBack(); test->waitUntilResourceLoadFinished(); - g_assert(webkit_web_view_get_main_resource(test->m_webView)); + resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_resource_get_uri(resource), ==, javascriptURI.data()); test->goForward(); test->waitUntilResourceLoadFinished(); - g_assert(webkit_web_view_get_main_resource(test->m_webView)); + resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_resource_get_uri(resource), ==, simpleStyleCSSURI.data()); } static void addCacheHTTPHeadersToResponse(SoupMessage* message) @@ -567,6 +582,9 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* } else if (g_str_equal(path, "/invalid-css.html")) { static const char* invalidCSSHtml = "<html><head><link rel='stylesheet' href='/invalid.css' type='text/css'></head><body></html>"; soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, invalidCSSHtml, strlen(invalidCSSHtml)); + } else if (g_str_equal(path, "/simple-style-css.html")) { + static const char* simpleStyleCSSHtml = "<html><head><link rel='stylesheet' href='/simple-style.css' type='text/css'></head><body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, simpleStyleCSSHtml, strlen(simpleStyleCSSHtml)); } else if (g_str_equal(path, "/style.css")) { soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleCSS, strlen(kStyleCSS)); addCacheHTTPHeadersToResponse(message); @@ -594,6 +612,8 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* soup_message_headers_append(message->response_headers, "Location", "/simple-style.css"); } else if (g_str_equal(path, "/invalid.css")) soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT); + else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); soup_message_body_complete(message->response_body); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestSSL.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestSSL.cpp index 40e9fbeee..8fa013dc4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestSSL.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestSSL.cpp @@ -82,9 +82,12 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - soup_message_set_status(message, SOUP_STATUS_OK); - soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHTML, strlen(indexHTML)); - soup_message_body_complete(message->response_body); + if (g_str_equal(path, "/")) { + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHTML, strlen(indexHTML)); + soup_message_body_complete(message->response_body); + } else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); } void beforeAll() diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp new file mode 100644 index 000000000..40fb5a17a --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFaviconDatabase.cpp @@ -0,0 +1,246 @@ +/* + * 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/gobject/GOwnPtr.h> + +static WebKitTestServer* kServer; +static char* kTempDirectory; + +class FaviconDatabaseTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(FaviconDatabaseTest); + + FaviconDatabaseTest() + : m_webContext(webkit_web_context_get_default()) + , m_favicon(0) + , m_error(0) + , m_iconReadySignalReceived(false) + , m_faviconNotificationReceived(false) + { + 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); + } + + static void iconReadyCallback(WebKitFaviconDatabase* database, const char* pageURI, FaviconDatabaseTest* test) + { + g_assert_cmpstr(webkit_web_view_get_uri(test->m_webView), ==, pageURI); + 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; + 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_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(faviconChangedCallback), this); + g_main_loop_run(m_mainLoop); + g_signal_handler_disconnect(m_webView, handlerID); + } + + 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); + } + + WebKitWebContext* m_webContext; + cairo_surface_t* m_favicon; + GOwnPtr<GError> m_error; + bool m_iconReadySignalReceived; + 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; + } + + char* contents; + gsize length; + if (g_str_equal(path, "/favicon.ico")) { + GOwnPtr<char> pathToFavicon(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "blank.ico", NULL)); + g_file_get_contents(pathToFavicon.get(), &contents, &length, 0); + } else if (g_str_equal(path, "/nofavicon/favicon.ico")) { + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); + soup_message_body_complete(message->response_body); + return; + } else { + contents = g_strdup("<html><body>test</body></html>"); + 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 testNotInitialized(FaviconDatabaseTest* test, gconstpointer) +{ + // Try to retrieve a valid favicon from a not initialized database. + test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/").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, 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)); +} + +static void testClearDatabase(FaviconDatabaseTest* test, gconstpointer) +{ + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext); + webkit_favicon_database_clear(database); + + GOwnPtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, kServer->getURIForPath("/").data())); + g_assert(!iconURI); +} + +static void testGetFavicon(FaviconDatabaseTest* test, gconstpointer) +{ + // 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->waitUntilFaviconChanged(); + g_assert(test->m_iconReadySignalReceived); + + // Check the API retrieving a valid favicon. + 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); + + // Check the API retrieving an invalid favicon. + test->loadURI(kServer->getURIForPath("/nofavicon").data()); + test->waitUntilFaviconChanged(); + g_assert(!test->m_iconReadySignalReceived); + + test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/nofavicon/").data()); + g_assert(!test->m_favicon); + g_assert(test->m_error); + g_assert(!test->m_iconReadySignalReceived); +} + +static void testGetFaviconURI(FaviconDatabaseTest* test, gconstpointer) +{ + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext); + + const char* baseURI = kServer->getURIForPath("/").data(); + GOwnPtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, baseURI)); + 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->waitUntilFaviconChanged(); + g_assert(test->m_faviconNotificationReceived); + + 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); +} + +void beforeAll() +{ + // Start a soup server for testing. + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0); + g_assert(kTempDirectory); + + // Add tests to the suite. + FaviconDatabaseTest::add("WebKitFaviconDatabase", "not-initialized", testNotInitialized); + FaviconDatabaseTest::add("WebKitFaviconDatabase", "set-directory", testSetDirectory); + 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*) +{ + if (!g_file_test(kTempDirectory, G_FILE_TEST_IS_DIR)) + return; + + GOwnPtr<char> filename(g_build_filename(kTempDirectory, "WebpageIcons.db", NULL)); + g_unlink(filename.get()); + + g_rmdir(kTempDirectory); +} + +void afterAll() +{ + delete kServer; + + // Delete the temporary files after the IconDatabase has been + // closed, that is, once WebKitFaviconDatabase is being destroyed. + WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webkit_web_context_get_default()); + g_object_weak_ref(G_OBJECT(database), webkitFaviconDatabaseFinalizedCallback, 0); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp index 9f6ce7819..abbfd652a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp @@ -232,11 +232,13 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - soup_message_set_status(message, SOUP_STATUS_OK); - - static const char* responseString = "<html><body>Testing!</body></html>"; - soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); - soup_message_body_complete(message->response_body); + if (g_str_equal(path, "/")) { + static const char* responseString = "<html><body>Testing!</body></html>"; + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); + soup_message_body_complete(message->response_body); + } else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); } void beforeAll() diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp index d8e355472..c7a0dc259 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -243,6 +243,11 @@ static void testWebKitSettings(Test*, gconstpointer) webkit_settings_set_enable_page_cache(settings, FALSE); g_assert(!webkit_settings_get_enable_page_cache(settings)); + // By default, smooth scrolling is disabled. + g_assert(!webkit_settings_get_enable_smooth_scrolling(settings)); + webkit_settings_set_enable_smooth_scrolling(settings, TRUE); + g_assert(webkit_settings_get_enable_smooth_scrolling(settings)); + g_object_unref(G_OBJECT(settings)); } @@ -315,10 +320,13 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - soup_message_set_status(message, SOUP_STATUS_OK); - const char* userAgent = soup_message_headers_get_one(message->request_headers, "User-Agent"); - soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, userAgent, strlen(userAgent)); - soup_message_body_complete(message->response_body); + if (g_str_equal(path, "/")) { + const char* userAgent = soup_message_headers_get_one(message->request_headers, "User-Agent"); + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, userAgent, strlen(userAgent)); + soup_message_body_complete(message->response_body); + } else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); } void beforeAll() diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp index 7a13d285d..185c06cfe 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp @@ -146,6 +146,8 @@ public: test->m_uriSchemeRequest = request; test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + g_assert(webkit_uri_scheme_request_get_web_view(request) == test->m_webView); + GRefPtr<GInputStream> inputStream = adoptGRef(g_memory_input_stream_new()); test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inputStream.get())); @@ -291,10 +293,13 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - soup_message_set_status(message, SOUP_STATUS_OK); - const char* acceptLanguage = soup_message_headers_get_one(message->request_headers, "Accept-Language"); - soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, acceptLanguage, strlen(acceptLanguage)); - soup_message_body_complete(message->response_body); + if (g_str_equal(path, "/")) { + const char* acceptLanguage = soup_message_headers_get_one(message->request_headers, "Accept-Language"); + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, acceptLanguage, strlen(acceptLanguage)); + soup_message_body_complete(message->response_body); + } else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); } class SecurityPolicyTest: public Test { diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp index 02e8138de..f5197b936 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp @@ -643,6 +643,17 @@ static void testWebViewRunJavaScript(WebViewTest* test, gconstpointer) g_assert(!error.get()); g_assert(WebViewTest::javascriptResultIsUndefined(javascriptResult)); + javascriptResult = test->runJavaScriptFromGResourceAndWaitUntilFinished("/org/webkit/webkit2gtk/tests/link-title.js", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.set(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Title"); + + javascriptResult = test->runJavaScriptFromGResourceAndWaitUntilFinished("/wrong/path/to/resource.js", &error.outPtr()); + g_assert(!javascriptResult); + g_assert_error(error.get(), G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND); + error.clear(); + javascriptResult = test->runJavaScriptAndWaitUntilFinished("foo();", &error.outPtr()); g_assert(!javascriptResult); g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp index 04747480e..7e7eb0167 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp @@ -313,6 +313,12 @@ static void runJavaScriptReadyCallback(GObject*, GAsyncResult* result, WebViewTe g_main_loop_quit(test->m_mainLoop); } +static void runJavaScriptFromGResourceReadyCallback(GObject*, GAsyncResult* result, WebViewTest* test) +{ + test->m_javascriptResult = webkit_web_view_run_javascript_from_gresource_finish(test->m_webView, result, test->m_javascriptError); + g_main_loop_quit(test->m_mainLoop); +} + WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* javascript, GError** error) { if (m_javascriptResult) @@ -325,6 +331,18 @@ WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const cha return m_javascriptResult; } +WebKitJavascriptResult* WebViewTest::runJavaScriptFromGResourceAndWaitUntilFinished(const char* resource, GError** error) +{ + if (m_javascriptResult) + webkit_javascript_result_unref(m_javascriptResult); + m_javascriptResult = 0; + m_javascriptError = error; + webkit_web_view_run_javascript_from_gresource(m_webView, resource, 0, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptFromGResourceReadyCallback), this); + g_main_loop_run(m_mainLoop); + + return m_javascriptResult; +} + static char* jsValueToCString(JSGlobalContextRef context, JSValueRef value) { g_assert(value); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h index 25209caa3..06f398f96 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h @@ -55,6 +55,7 @@ public: void keyStroke(unsigned int keyVal, unsigned int keyModifiers = 0); WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**); + WebKitJavascriptResult* runJavaScriptFromGResourceAndWaitUntilFinished(const char* resource, GError**); // Javascript result helpers. static char* javascriptResultToCString(WebKitJavascriptResult*); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/resources/link-title.js b/Source/WebKit2/UIProcess/API/gtk/tests/resources/link-title.js new file mode 100644 index 000000000..2c824da38 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/resources/link-title.js @@ -0,0 +1 @@ +window.document.getElementById('WebKitLink').title; diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/resources/webkit2gtk-tests.gresource.xml b/Source/WebKit2/UIProcess/API/gtk/tests/resources/webkit2gtk-tests.gresource.xml new file mode 100644 index 000000000..4f1e5a654 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/resources/webkit2gtk-tests.gresource.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/org/webkit/webkit2gtk/tests/"> + <file alias="link-title.js">Source/WebKit2/UIProcess/API/gtk/tests/resources/link-title.js</file> + </gresource> +</gresources> diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index e1f3ba04a..1b4fa86a1 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -34,6 +34,7 @@ #include <webkit2/WebKitEditingCommands.h> #include <webkit2/WebKitEnumTypes.h> #include <webkit2/WebKitError.h> +#include <webkit2/WebKitFaviconDatabase.h> #include <webkit2/WebKitFileChooserRequest.h> #include <webkit2/WebKitFindController.h> #include <webkit2/WebKitFormSubmissionRequest.h> |