diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/API/gtk')
56 files changed, 3311 insertions, 292 deletions
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp index fab54fb21..1caca868e 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp @@ -22,7 +22,7 @@ #include "WebKitBackForwardListPrivate.h" #include "WebKitMarshal.h" -#include <WebKit2/WKBackForwardList.h> +#include "WebKitPrivate.h" #include <wtf/gobject/GRefPtr.h> /** diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp index ed44f1f1e..c6a4b598c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp @@ -21,8 +21,7 @@ #include "WebKitBackForwardListItem.h" #include "WebKitBackForwardListPrivate.h" -#include <WebKit2/WKBackForwardListItem.h> -#include <WebKit2/WKRetainPtr.h> +#include "WebKitPrivate.h" #include <wtf/HashMap.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp new file mode 100644 index 000000000..4d4eba18d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp @@ -0,0 +1,510 @@ +/* + * 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. + */ + +#include "config.h" +#include "WebKitDownload.h" + +#include "WebKitDownloadPrivate.h" +#include "WebKitMarshal.h" +#include "WebKitURIResponsePrivate.h" +#include <WebCore/ErrorsGtk.h> +#include <WebCore/ResourceResponse.h> +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> + +using namespace WebKit; +using namespace WebCore; + +enum { + RECEIVED_DATA, + FINISHED, + FAILED, + DECIDE_DESTINATION, + CREATED_DESTINATION, + + LAST_SIGNAL +}; + +enum { + PROP_0, + + PROP_DESTINATION, + PROP_RESPONSE, + PROP_ESTIMATED_PROGRESS +}; + +struct _WebKitDownloadPrivate { + WKRetainPtr<WKDownloadRef> wkDownload; + + GRefPtr<WebKitURIResponse> response; + CString destinationURI; + guint64 currentSize; + bool isCancelled; + GOwnPtr<GTimer> timer; + gdouble lastProgress; + gdouble lastElapsed; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitDownload, webkit_download, G_TYPE_OBJECT) + +static void webkitDownloadFinalize(GObject* object) +{ + WEBKIT_DOWNLOAD(object)->priv->~WebKitDownloadPrivate(); + G_OBJECT_CLASS(webkit_download_parent_class)->finalize(object); +} + +static void webkitDownloadGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitDownload* download = WEBKIT_DOWNLOAD(object); + + switch (propId) { + case PROP_DESTINATION: + g_value_set_string(value, webkit_download_get_destination(download)); + break; + case PROP_RESPONSE: + g_value_set_object(value, webkit_download_get_response(download)); + break; + case PROP_ESTIMATED_PROGRESS: + g_value_set_double(value, webkit_download_get_estimated_progress(download)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + } +} + +static gboolean webkitDownloadDecideDestination(WebKitDownload* download, const gchar* suggestedFilename) +{ + if (!download->priv->destinationURI.isNull()) + return FALSE; + GOwnPtr<char> destination(g_build_filename(g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD), suggestedFilename, NULL)); + GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); + download->priv->destinationURI = destinationURI.get(); + g_object_notify(G_OBJECT(download), "destination"); + return TRUE; +} + +static void webkit_download_init(WebKitDownload* download) +{ + WebKitDownloadPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(download, WEBKIT_TYPE_DOWNLOAD, WebKitDownloadPrivate); + download->priv = priv; + new (priv) WebKitDownloadPrivate(); +} + +static void webkit_download_class_init(WebKitDownloadClass* downloadClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(downloadClass); + objectClass->get_property = webkitDownloadGetProperty; + objectClass->finalize = webkitDownloadFinalize; + + downloadClass->decide_destination = webkitDownloadDecideDestination; + + /** + * WebKitDownload:destination: + * + * The local URI to where the download will be saved. + */ + g_object_class_install_property(objectClass, + PROP_DESTINATION, + g_param_spec_string("destination", + _("Destination"), + _("The local URI to where the download will be saved"), + 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:response: + * + * The #WebKitURIResponse associated with this download. + */ + g_object_class_install_property(objectClass, + PROP_RESPONSE, + g_param_spec_object("response", + _("Response"), + _("The response of the download"), + WEBKIT_TYPE_URI_RESPONSE, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:estimated-progress: + * + * An estimate of the percent completion for the download operation. + * This value will range from 0.0 to 1.0. The value is an estimate + * based on the total number of bytes expected to be received for + * a download. + * If you need a more accurate progress information you can connect to + * #WebKitDownload::received-data signal to track the progress. + */ + g_object_class_install_property(objectClass, + PROP_ESTIMATED_PROGRESS, + g_param_spec_double("estimated-progress", + _("Estimated Progress"), + _("Determines the current progress of the download"), + 0.0, 1.0, 1.0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload::received-data: + * @download: the #WebKitDownload + * @data_length: the length of data received in bytes + * + * This signal is emitted after response is received, + * every time new data has been written to the destination. It's + * useful to know the progress of the download operation. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[RECEIVED_DATA] = + g_signal_new("received-data", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, received_data), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__UINT64, + G_TYPE_BOOLEAN, 1, + G_TYPE_UINT64); + + /** + * WebKitDownload::finished: + * @download: the #WebKitDownload + * + * This signal is emitted when download finishes successfully or due to an error. + * In case of errors #WebKitDownload::failed signal is emitted before this one. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[FINISHED] = + g_signal_new("finished", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, finished), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitDownload::failed: + * @download: the #WebKitDownload + * @error: the #GError that was triggered + * + * This signal is emitted when an error occurs during the download + * operation. The given @error, of the domain %WEBKIT_DOWNLOAD_ERROR, + * contains further details of the failure. If the download is cancelled + * with webkit_download_cancel(), this signal is emitted with error + * %WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER. The download operation finishes + * after an error and #WebKitDownload::finished signal is emitted after this one. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[FAILED] = + g_signal_new("failed", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, failed), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + /** + * WebKitDownload::decide-destination: + * @download: the #WebKitDownload + * @suggested_filename: the filename suggested for the download + * + * This signal is emitted after response is received to + * decide a destination URI for the download. If this signal is not + * handled the file will be downloaded to %G_USER_DIRECTORY_DOWNLOAD + * directory using @suggested_filename. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[DECIDE_DESTINATION] = + g_signal_new("decide-destination", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, decide_destination), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + /** + * WebKitDownload::created-destination: + * @download: the #WebKitDownload + * @destination: the destination URI + * + * This signal is emitted after #WebKitDownload::decide-destination and before + * #WebKitDownload::received-data to notify that destination file has been + * created successfully at @destination. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[CREATED_DESTINATION] = + g_signal_new("created-destination", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, created_destination), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + g_type_class_add_private(downloadClass, sizeof(WebKitDownloadPrivate)); +} + +WebKitDownload* webkitDownloadCreate(WKDownloadRef wkDownload) +{ + ASSERT(wkDownload); + WebKitDownload* download = WEBKIT_DOWNLOAD(g_object_new(WEBKIT_TYPE_DOWNLOAD, NULL)); + download->priv->wkDownload = wkDownload; + return download; +} + +void webkitDownloadSetResponse(WebKitDownload* download, WebKitURIResponse* response) +{ + download->priv->response = response; + g_object_notify(G_OBJECT(download), "response"); +} + +bool webkitDownloadIsCancelled(WebKitDownload* download) +{ + return download->priv->isCancelled; +} + +void webkitDownloadNotifyProgress(WebKitDownload* download, guint64 bytesReceived) +{ + WebKitDownloadPrivate* priv = download->priv; + if (priv->isCancelled) + return; + + if (!download->priv->timer) + download->priv->timer.set(g_timer_new()); + + priv->currentSize += bytesReceived; + gboolean returnValue; + g_signal_emit(download, signals[RECEIVED_DATA], 0, bytesReceived, &returnValue); + + // Throttle progress notification to not consume high amounts of + // CPU on fast links, except when the last notification occured + // more than 0.016 secs ago (60 FPS), or the last notified progress + // is passed in 1% or we reached the end. + gdouble currentElapsed = g_timer_elapsed(priv->timer.get(), 0); + gdouble currentProgress = webkit_download_get_estimated_progress(download); + + if (priv->lastElapsed + && priv->lastProgress + && (currentElapsed - priv->lastElapsed) < 0.016 + && (currentProgress - priv->lastProgress) < 0.01 + && currentProgress < 1.0) { + return; + } + priv->lastElapsed = currentElapsed; + priv->lastProgress = currentProgress; + g_object_notify(G_OBJECT(download), "estimated-progress"); +} + +void webkitDownloadFailed(WebKitDownload* download, const ResourceError& resourceError) +{ + GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), + resourceError.errorCode(), + resourceError.localizedDescription().utf8().data())); + if (download->priv->timer) + g_timer_stop(download->priv->timer.get()); + gboolean returnValue; + g_signal_emit(download, signals[FAILED], 0, webError.get(), &returnValue); + g_signal_emit(download, signals[FINISHED], 0, &returnValue); +} + +void webkitDownloadCancelled(WebKitDownload* download) +{ + WebKitDownloadPrivate* priv = download->priv; + webkitDownloadFailed(download, downloadCancelledByUserError(priv->response ? webkitURIResponseGetResourceResponse(priv->response.get()) : ResourceResponse())); +} + +void webkitDownloadFinished(WebKitDownload* download) +{ + if (download->priv->isCancelled) { + // Since cancellation is asynchronous, didFinish might be called even + // if the download was cancelled. User cancelled the download, + // so we should fail with cancelled error even if the download + // actually finished successfully. + webkitDownloadCancelled(download); + return; + } + if (download->priv->timer) + g_timer_stop(download->priv->timer.get()); + gboolean returnValue; + g_signal_emit(download, signals[FINISHED], 0, &returnValue); +} + +CString webkitDownloadDecideDestinationWithSuggestedFilename(WebKitDownload* download, const CString& suggestedFilename) +{ + if (download->priv->isCancelled) + return ""; + gboolean returnValue; + g_signal_emit(download, signals[DECIDE_DESTINATION], 0, suggestedFilename.data(), &returnValue); + return download->priv->destinationURI; +} + +void webkitDownloadDestinationCreated(WebKitDownload* download, const CString& destinationURI) +{ + if (download->priv->isCancelled) + return; + gboolean returnValue; + g_signal_emit(download, signals[CREATED_DESTINATION], 0, destinationURI.data(), &returnValue); +} + +/** + * webkit_download_get_destination: + * @download: a #WebKitDownload + * + * Obtains the URI to which the downloaded file will be written. You + * can connect to #WebKitDownload::created-destination to make + * sure this method returns a valid destination. + * + * Returns: the destination URI or %NULL + */ +const gchar* webkit_download_get_destination(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + return download->priv->destinationURI.data(); +} + +/** + * webkit_download_set_destination: + * @download: a #WebKitDownload + * @uri: the destination URI + * + * Sets the URI to which the downloaded file will be written. + * This method should be called before the download transfer + * starts or it will not have any effect on the ongoing download + * operation. To set the destination using the filename suggested + * by the server connect to #WebKitDownload::decide-destination + * signal and call webkit_download_set_destination(). If you want to + * set a fixed destination URI that doesn't depend on the suggested + * filename you can connect to notify::response signal and call + * webkit_download_set_destination(). + * If #WebKitDownload::decide-destination signal is not handled + * and destination URI is not set when the download tranfer starts, + * the file will be saved with the filename suggested by the server in + * %G_USER_DIRECTORY_DOWNLOAD directory. + */ +void webkit_download_set_destination(WebKitDownload* download, const gchar* uri) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + g_return_if_fail(uri); + + WebKitDownloadPrivate* priv = download->priv; + if (priv->destinationURI == uri) + return; + + priv->destinationURI = uri; + g_object_notify(G_OBJECT(download), "destination"); +} + +/** + * webkit_download_get_response: + * @download: a #WebKitDownload + * + * Retrieves the #WebKitURIResponse object that backs the download + * process. This method returns %NULL if called before the response + * is received from the server. You can connect to notify::response + * signal to be notified when the response is received. + * + * Returns: (transfer none): the #WebKitURIResponse, or %NULL if + * the response hasn't been received yet. + */ +WebKitURIResponse* webkit_download_get_response(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + return download->priv->response.get(); +} + +/** + * webkit_download_cancel: + * @download: a #WebKitDownload + * + * Cancels the download. When the ongoing download + * operation is effectively cancelled the signal + * #WebKitDownload::failed is emitted with + * %WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER error. + */ +void webkit_download_cancel(WebKitDownload* download) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + + download->priv->isCancelled = true; + WKDownloadCancel(download->priv->wkDownload.get()); +} + +/** + * webkit_download_get_estimated_progress: + * @download: a #WebKitDownload + * + * Gets the value of the #WebKitDownload:estimated-progress property. + * You can monitor the estimated progress of the download operation by + * connecting to the notify::estimated-progress signal of @download. + * + * Returns: an estimate of the of the percent complete for a download + * as a range from 0.0 to 1.0. + */ +gdouble webkit_download_get_estimated_progress(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + WebKitDownloadPrivate* priv = download->priv; + if (!priv->response) + return 0; + + guint64 contentLength = webkit_uri_response_get_content_length(priv->response.get()); + if (!contentLength) + return 0; + + return static_cast<gdouble>(priv->currentSize) / static_cast<gdouble>(contentLength); +} + +/** + * webkit_download_get_elapsed_time: + * @download: a #WebKitDownload + * + * Gets the elapsed time in seconds, including any fractional part. + * If the download finished, had an error or was cancelled this is + * the time between its start and the event. + * + * Returns: seconds since the download was started + */ +gdouble webkit_download_get_elapsed_time(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + WebKitDownloadPrivate* priv = download->priv; + if (!priv->timer) + return 0; + + return g_timer_elapsed(priv->timer.get(), 0); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.h new file mode 100644 index 000000000..e200fec53 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitDownload_h +#define WebKitDownload_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitURIResponse.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_DOWNLOAD (webkit_download_get_type()) +#define WEBKIT_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownload)) +#define WEBKIT_IS_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOWNLOAD)) +#define WEBKIT_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadClass)) +#define WEBKIT_IS_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOWNLOAD)) +#define WEBKIT_DOWNLOAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadClass)) + +typedef struct _WebKitDownload WebKitDownload; +typedef struct _WebKitDownloadClass WebKitDownloadClass; +typedef struct _WebKitDownloadPrivate WebKitDownloadPrivate; + +struct _WebKitDownload { + GObject parent; + + WebKitDownloadPrivate *priv; +}; + +struct _WebKitDownloadClass { + GObjectClass parent_class; + + gboolean (* received_data) (WebKitDownload *download, + guint64 data_length); + gboolean (* finished) (WebKitDownload *download); + gboolean (* failed) (WebKitDownload *download, + GError *error); + gboolean (* decide_destination) (WebKitDownload *download, + const gchar *suggested_filename); + gboolean (* created_destination) (WebKitDownload *download, + const gchar *destination); +}; + +WEBKIT_API GType +webkit_download_get_type (void); + +WEBKIT_API const gchar * +webkit_download_get_destination (WebKitDownload *download); + +WEBKIT_API void +webkit_download_set_destination (WebKitDownload *download, + const gchar *uri); + +WEBKIT_API WebKitURIResponse* +webkit_download_get_response (WebKitDownload *download); + +WEBKIT_API void +webkit_download_cancel (WebKitDownload *download); + +WEBKIT_API gdouble +webkit_download_get_estimated_progress (WebKitDownload *download); + +WEBKIT_API gdouble +webkit_download_get_elapsed_time (WebKitDownload *download); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp new file mode 100644 index 000000000..6e72496ef --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#include "config.h" +#include "WebKitDownloadClient.h" + +#include "WebContext.h" +#include "WebKitDownloadPrivate.h" +#include "WebKitURIResponsePrivate.h" +#include "WebKitWebContextPrivate.h" +#include "WebURLResponse.h" +#include <WebKit2/WKString.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebCore; +using namespace WebKit; + +static void didStart(WKContextRef, WKDownloadRef wkDownload, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitWebContextDownloadStarted(WEBKIT_WEB_CONTEXT(clientInfo), download.get()); +} + +static void didReceiveResponse(WKContextRef, WKDownloadRef wkDownload, WKURLResponseRef wkResponse, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + if (webkitDownloadIsCancelled(download.get())) + return; + + GRefPtr<WebKitURIResponse> response = adoptGRef(webkitURIResponseCreateForResourceResponse(toImpl(wkResponse)->resourceResponse())); + webkitDownloadSetResponse(download.get(), response.get()); +} + +static void didReceiveData(WKContextRef, WKDownloadRef wkDownload, uint64_t length, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadNotifyProgress(download.get(), length); +} + +static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef wkDownload, WKStringRef filename, bool* allowOverwrite, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + CString destinationURI = webkitDownloadDecideDestinationWithSuggestedFilename(download.get(), + toImpl(filename)->string().utf8()); + return WKStringCreateWithUTF8CString(destinationURI.data()); +} + +static void didCreateDestination(WKContextRef, WKDownloadRef wkDownload, WKStringRef path, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadDestinationCreated(download.get(), toImpl(path)->string().utf8()); +} + +static void didFail(WKContextRef, WKDownloadRef wkDownload, WKErrorRef error, const void *clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + if (webkitDownloadIsCancelled(download.get())) { + // Cancellation takes precedence over other errors. + webkitDownloadCancelled(download.get()); + } else + webkitDownloadFailed(download.get(), toImpl(error)->platformError()); + webkitWebContextRemoveDownload(wkDownload); +} + +static void didCancel(WKContextRef, WKDownloadRef wkDownload, const void *clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadCancelled(download.get()); + webkitWebContextRemoveDownload(wkDownload); +} + +static void didFinish(WKContextRef wkContext, WKDownloadRef wkDownload, const void *clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadFinished(download.get()); + webkitWebContextRemoveDownload(wkDownload); +} + +void attachDownloadClientToContext(WebKitWebContext* webContext) +{ + WKContextDownloadClient wkDownloadClient = { + kWKContextDownloadClientCurrentVersion, + webContext, // ClientInfo + didStart, + 0, // didReceiveAuthenticationChallenge + didReceiveResponse, + didReceiveData, + 0, // shouldDecodeSourceDataOfMIMEType + decideDestinationWithSuggestedFilename, + didCreateDestination, + didFinish, + didFail, + didCancel, + 0, // processDidCrash + }; + WKContextSetDownloadClient(webkitWebContextGetWKContext(webContext), &wkDownloadClient); +} + diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.h new file mode 100644 index 000000000..c2566e897 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.h @@ -0,0 +1,27 @@ +/* + * 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 WebKitDownloadClient_h +#define WebKitDownloadClient_h + +#include "WebKitWebContext.h" + +void attachDownloadClientToContext(WebKitWebContext*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadPrivate.h new file mode 100644 index 000000000..6f4b5363c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadPrivate.h @@ -0,0 +1,38 @@ +/* + * 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 WebKitDownloadPrivate_h +#define WebKitDownloadPrivate_h + +#include "WebKitDownload.h" +#include "WebKitPrivate.h" +#include <WebCore/ResourceError.h> +#include <wtf/text/CString.h> + +WebKitDownload* webkitDownloadCreate(WKDownloadRef); +bool webkitDownloadIsCancelled(WebKitDownload*); +void webkitDownloadSetResponse(WebKitDownload*, WebKitURIResponse*); +void webkitDownloadNotifyProgress(WebKitDownload*, guint64 bytesReceived); +void webkitDownloadFailed(WebKitDownload*, const WebCore::ResourceError&); +void webkitDownloadCancelled(WebKitDownload*); +void webkitDownloadFinished(WebKitDownload*); +CString webkitDownloadDecideDestinationWithSuggestedFilename(WebKitDownload*, const CString& suggestedFilename); +void webkitDownloadDestinationCreated(WebKitDownload*, const CString& destinationURI); + +#endif // WebKitDownloadPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp index 6c24aa12e..42cf0ab35 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp @@ -24,6 +24,8 @@ #include "WebKitPrivate.h" #include <WebCore/ErrorsGtk.h> +using namespace WebCore; + GQuark webkit_network_error_quark() { return g_quark_from_static_string(WebCore::errorDomainNetwork); @@ -57,3 +59,12 @@ COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_CANNOT_LOAD_PLUGIN, PluginError COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_JAVA_UNAVAILABLE, PluginErrorJavaUnavailable); COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_CONNECTION_CANCELLED, PluginErrorConnectionCancelled); COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD, PluginErrorWillHandleLoad); + +GQuark webkit_download_error_quark() +{ + return g_quark_from_static_string(WebCore::errorDomainDownload); +} + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_NETWORK, DownloadErrorNetwork); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER, DownloadErrorCancelledByUser); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_DESTINATION, DownloadErrorDestination); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h index 3ce0e20f1..9b0e630c8 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h @@ -32,6 +32,7 @@ G_BEGIN_DECLS #define WEBKIT_NETWORK_ERROR webkit_network_error_quark () #define WEBKIT_POLICY_ERROR webkit_policy_error_quark () #define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () +#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () /** * WebKitNetworkError: @@ -89,14 +90,31 @@ typedef enum { WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD = 204, } WebKitPluginError; +/** + * WebKitDownloadError: + * @WEBKIT_DOWNLOAD_ERROR_NETWORK: Download failure due to network error + * @WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER: Download was cancelled by user + * @WEBKIT_DOWNLOAD_ERROR_DESTINATION: Download failure due to destination error + * + * Enum values used to denote the various download errors. + */ +typedef enum { + WEBKIT_DOWNLOAD_ERROR_NETWORK = 499, + WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER = 400, + WEBKIT_DOWNLOAD_ERROR_DESTINATION = 401 +} WebKitDownloadError; + +WEBKIT_API GQuark +webkit_network_error_quark (void); + WEBKIT_API GQuark -webkit_network_error_quark (void); +webkit_policy_error_quark (void); WEBKIT_API GQuark -webkit_policy_error_quark (void); +webkit_plugin_error_quark (void); WEBKIT_API GQuark -webkit_plugin_error_quark (void); +webkit_download_error_quark (void); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp index d27560f53..6d1133941 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp @@ -19,9 +19,10 @@ */ #include "config.h" -#include "WebKitWebLoaderClient.h" +#include "WebKitLoaderClient.h" #include "WebKitBackForwardListPrivate.h" +#include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include <wtf/gobject/GOwnPtr.h> #include <wtf/text/CString.h> @@ -29,14 +30,12 @@ using namespace WebKit; using namespace WebCore; -G_DEFINE_TYPE(WebKitWebLoaderClient, webkit_web_loader_client, G_TYPE_OBJECT) - static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) { if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_STARTED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_STARTED); } static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) @@ -44,7 +43,7 @@ static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, W if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_REDIRECTED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_REDIRECTED); } static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo) @@ -56,7 +55,7 @@ static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef f GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), resourceError.errorCode(), resourceError.localizedDescription().utf8().data())); - webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_STARTED, + webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_STARTED, resourceError.failingURL().utf8().data(), webError.get()); } @@ -65,7 +64,7 @@ static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_COMMITTED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_COMMITTED); } static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) @@ -73,7 +72,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_FINISHED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_FINISHED); } static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef, const void* clientInfo) @@ -85,43 +84,41 @@ static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErr GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), resourceError.errorCode(), resourceError.localizedDescription().utf8().data())); - webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_COMMITTED, + webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_COMMITTED, resourceError.failingURL().utf8().data(), webError.get()); } -static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType, WKTypeRef, const void*) +static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType, WKTypeRef, const void* clientInfo) { if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewUpdateURI(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + webkitWebViewUpdateURI(WEBKIT_WEB_VIEW(clientInfo)); } -static void didReceiveTitleForFrame(WKPageRef page, WKStringRef titleRef, WKFrameRef frameRef, WKTypeRef, const void*) +static void didReceiveTitleForFrame(WKPageRef page, WKStringRef titleRef, WKFrameRef frameRef, WKTypeRef, const void* clientInfo) { if (!WKFrameIsMainFrame(frameRef)) return; - webkitWebViewSetTitle(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(titleRef)->string().utf8()); + webkitWebViewSetTitle(WEBKIT_WEB_VIEW(clientInfo), toImpl(titleRef)->string().utf8()); } static void didChangeProgress(WKPageRef page, const void* clientInfo) { - WebKitWebView* webView = WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()); - webkitWebViewSetEstimatedLoadProgress(webView, WKPageGetEstimatedProgress(page)); + webkitWebViewSetEstimatedLoadProgress(WEBKIT_WEB_VIEW(clientInfo), WKPageGetEstimatedProgress(page)); } static void didChangeBackForwardList(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void* clientInfo) { - WebKitWebView* webView = WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()); - webkitBackForwardListChanged(webkit_web_view_get_back_forward_list(webView), addedItem, removedItems); + webkitBackForwardListChanged(webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(clientInfo)), addedItem, removedItems); } -void webkitWebLoaderClientAttachLoaderClientToPage(WebKitWebLoaderClient* loaderClient, WKPageRef wkPage) +void attachLoaderClientToView(WebKitWebView* webView) { WKPageLoaderClient wkLoaderClient = { kWKPageLoaderClientCurrentVersion, - loaderClient, // clientInfo + webView, // clientInfo didStartProvisionalLoadForFrame, didReceiveServerRedirectForProvisionalLoadForFrame, didFailProvisionalLoadWithErrorForFrame, @@ -149,13 +146,7 @@ void webkitWebLoaderClientAttachLoaderClientToPage(WebKitWebLoaderClient* loader 0, // didFailToInitializePlugin 0 // didDetectXSSForFrame }; + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); WKPageSetPageLoaderClient(wkPage, &wkLoaderClient); } -static void webkit_web_loader_client_init(WebKitWebLoaderClient*) -{ -} - -static void webkit_web_loader_client_class_init(WebKitWebLoaderClientClass*) -{ -} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h new file mode 100644 index 000000000..dfac3c86f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2011 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 WebKitLoaderClient_h +#define WebKitLoaderClient_h + +#include "WebKitWebView.h" + +void attachLoaderClientToView(WebKitWebView*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.cpp new file mode 100644 index 000000000..fcd57b4a6 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.cpp @@ -0,0 +1,307 @@ +/* + * 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. + */ + +#include "config.h" +#include "WebKitNavigationPolicyDecision.h" + +#include "WebKitEnumTypes.h" +#include "WebKitPolicyDecisionPrivate.h" +#include "WebKitPrivate.h" +#include "WebKitURIRequestPrivate.h" +#include "WebURLRequest.h" +#include <gdk/gdk.h> +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +/** + * SECTION: WebKitNavigationPolicyDecision + * @Short_description: A policy decision for navigation actions + * @Title: WebKitNavigationPolicyDecision + * @See_also: #WebKitPolicyDecision, #WebKitWebView + * + * WebKitNavigationPolicyDecision represents a policy decision for events associated with + * navigations. If the value of WebKitNavigationPolicyDecision:mouse-button is not 0, then + * the navigation was triggered by a mouse event. + */ + +G_DEFINE_TYPE(WebKitNavigationPolicyDecision, webkit_navigation_policy_decision, WEBKIT_TYPE_POLICY_DECISION) + +struct _WebKitNavigationPolicyDecisionPrivate { + WebKitNavigationType navigationType; + unsigned modifiers; + unsigned mouseButton; + GRefPtr<WebKitURIRequest> request; + CString frameName; +}; + +enum { + PROP_0, + PROP_NAVIGATION_TYPE, + PROP_MOUSE_BUTTON, + PROP_MODIFIERS, + PROP_REQUEST, + PROP_FRAME_NAME, +}; + +static void webkit_navigation_policy_decision_init(WebKitNavigationPolicyDecision* decision) +{ + decision->priv = G_TYPE_INSTANCE_GET_PRIVATE(decision, WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecisionPrivate); + new (decision->priv) WebKitNavigationPolicyDecisionPrivate(); +} + +static void webkitNavigationPolicyDecisionFinalize(GObject* object) +{ + WEBKIT_NAVIGATION_POLICY_DECISION(object)->priv->~WebKitNavigationPolicyDecisionPrivate(); + G_OBJECT_CLASS(webkit_navigation_policy_decision_parent_class)->finalize(object); +} + +static void webkitNavigationPolicyDecisionGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(object); + switch (propId) { + case PROP_NAVIGATION_TYPE: + g_value_set_enum(value, webkit_navigation_policy_decision_get_navigation_type(decision)); + break; + case PROP_MOUSE_BUTTON: + g_value_set_enum(value, webkit_navigation_policy_decision_get_mouse_button(decision)); + break; + case PROP_MODIFIERS: + g_value_set_uint(value, webkit_navigation_policy_decision_get_modifiers(decision)); + break; + case PROP_REQUEST: + g_value_set_object(value, webkit_navigation_policy_decision_get_request(decision)); + break; + case PROP_FRAME_NAME: + g_value_set_string(value, webkit_navigation_policy_decision_get_frame_name(decision)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + break; + } +} + +static void webkit_navigation_policy_decision_class_init(WebKitNavigationPolicyDecisionClass* decisionClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(decisionClass); + objectClass->finalize = webkitNavigationPolicyDecisionFinalize; + objectClass->get_property = webkitNavigationPolicyDecisionGetProperty; + g_type_class_add_private(decisionClass, sizeof(WebKitNavigationPolicyDecisionPrivate)); + + /** + * WebKitNavigationPolicyDecision:navigation-type: + * + * The type of navigation that triggered this policy decision. This is + * useful for enacting different policies depending on what type of user + * action caused the navigation. + */ + g_object_class_install_property(objectClass, + PROP_NAVIGATION_TYPE, + g_param_spec_enum("navigation-type", + _("Navigation type"), + _("The type of navigation triggering this decision"), + WEBKIT_TYPE_NAVIGATION_TYPE, + WEBKIT_NAVIGATION_TYPE_LINK_CLICKED, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:mouse-button: + * + * If the navigation associated with this policy decision was originally + * triggered by a mouse event, this property contains non-zero button number + * of the button triggering that event. The button numbers match those from GDK. + * If the navigation was not triggered by a mouse event, the value of this + * property will be 0. + */ + g_object_class_install_property(objectClass, + PROP_MOUSE_BUTTON, + g_param_spec_uint("mouse-button", + _("Mouse button"), + _("The mouse button used if this decision was triggered by a mouse event"), + 0, G_MAXUINT, 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:modifiers: + * + * If the navigation associated with this policy decision was originally + * triggered by a mouse event, this property contains a bitmask of various + * GdkModifierType values describing the modifiers used for that click. + * If the navigation was not triggered by a mouse event or no modifiers + * were active, the value of this property will be zero. + */ + g_object_class_install_property(objectClass, + PROP_MODIFIERS, + g_param_spec_uint("modifiers", + _("Mouse event modifiers"), + _("The modifiers active if this decision was triggered by a mouse event"), + 0, G_MAXUINT, 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:request: + * + * This property contains the #WebKitURIRequest associated with this + * navigation. + */ + g_object_class_install_property(objectClass, + PROP_REQUEST, + g_param_spec_object("request", + _("Navigation URI request"), + _("The URI request that is associated with this navigation"), + WEBKIT_TYPE_URI_REQUEST, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:frame-name: + * + * If this navigation request targets a new frame, this property contains + * the name of that frame. For example if the decision was triggered by clicking a + * link with a target attribute equal to "_blank", this property will contain the + * value of that attribute. In all other cases, this value will be %NULL. + */ + g_object_class_install_property(objectClass, + PROP_FRAME_NAME, + g_param_spec_string("frame-name", + _("Frame name"), + _("The name of the new frame this navigation action targets"), + 0, + WEBKIT_PARAM_READABLE)); +} + +/** + * webkit_navigation_policy_decision_get_navigation_type: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:navigation-type property. + * + * Returns: The type of navigation triggering this policy decision. + */ +WebKitNavigationType webkit_navigation_policy_decision_get_navigation_type(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), WEBKIT_NAVIGATION_TYPE_OTHER); + return decision->priv->navigationType; +} + +/** + * webkit_navigation_policy_decision_get_mouse_button: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:mouse-button property. + * + * Returns: The mouse button used if this decision was triggered by a mouse event or 0 otherwise + */ +guint webkit_navigation_policy_decision_get_mouse_button(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->mouseButton; +} + +/** + * webkit_navigation_policy_decision_get_modifiers: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:modifiers property. + * + * Returns: The modifiers active if this decision was triggered by a mouse event + */ +unsigned webkit_navigation_policy_decision_get_modifiers(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->modifiers; +} + +/** + * webkit_navigation_policy_decision_get_request: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:request property. + * + * Returns: (transfer none): The URI request that is associated with this navigation + */ +WebKitURIRequest* webkit_navigation_policy_decision_get_request(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->request.get(); +} + +/** + * webkit_navigation_policy_decision_get_frame_name: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:frame-name property. + * + * Returns: The name of the new frame this navigation action targets or %NULL + */ +const char* webkit_navigation_policy_decision_get_frame_name(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->frameName.data(); +} + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_LINK_CLICKED, kWKFrameNavigationTypeLinkClicked); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED, kWKFrameNavigationTypeFormSubmitted); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_BACK_FORWARD, kWKFrameNavigationTypeBackForward); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_RELOAD, kWKFrameNavigationTypeReload); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED, kWKFrameNavigationTypeFormResubmitted); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_OTHER, kWKFrameNavigationTypeOther); + +static unsigned wkEventMouseButtonToWebKitMouseButton(WKEventMouseButton wkButton) +{ + switch (wkButton) { + case kWKEventMouseButtonNoButton: + return 0; + case kWKEventMouseButtonLeftButton: + return 1; + case kWKEventMouseButtonMiddleButton: + return 2; + case kWKEventMouseButtonRightButton: + return 3; + } + ASSERT_NOT_REACHED(); + return 0; +} + +unsigned wkEventModifiersToUnsigned(WKEventModifiers wkModifiers) +{ + unsigned modifiers = 0; + if (wkModifiers & kWKEventModifiersShiftKey) + modifiers |= GDK_SHIFT_MASK; + if (wkModifiers & kWKEventModifiersControlKey) + modifiers |= GDK_CONTROL_MASK; + if (wkModifiers & kWKEventModifiersAltKey) + modifiers |= GDK_MOD1_MASK; + if (wkModifiers & kWKEventModifiersMetaKey) + modifiers |= GDK_META_MASK; + return modifiers; +} + +WebKitNavigationPolicyDecision* webkitNavigationPolicyDecisionCreate(WKFrameNavigationType navigationType, WKEventMouseButton mouseButton, WKEventModifiers modifiers, WKURLRequestRef request, const char* frameName, WKFramePolicyListenerRef listener) +{ + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(g_object_new(WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, NULL)); + decision->priv->navigationType = static_cast<WebKitNavigationType>(navigationType); + decision->priv->mouseButton = wkEventMouseButtonToWebKitMouseButton(mouseButton); + decision->priv->modifiers = wkEventModifiersToUnsigned(modifiers); + decision->priv->request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(request)->resourceRequest())); + decision->priv->frameName = frameName; + webkitPolicyDecisionSetListener(WEBKIT_POLICY_DECISION(decision), listener); + return decision; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h new file mode 100644 index 000000000..bbf241268 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h @@ -0,0 +1,91 @@ +/* + * 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. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitNavigationPolicyDecision_h +#define WebKitNavigationPolicyDecision_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitPolicyDecision.h> +#include <webkit2/WebKitURIRequest.h> + +G_BEGIN_DECLS + +/** + * WebKitNavigationType: + * @WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: The navigation was triggered by clicking a link. + * @WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: The navigation was triggered by submitting a form. + * @WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: The navigation was triggered by navigating forward or backward. + * @WEBKIT_NAVIGATION_TYPE_RELOAD: The navigation was triggered by reloading. + * @WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED: The navigation was triggered by resubmitting a form. + * @WEBKIT_NAVIGATION_TYPE_OTHER: The navigation was triggered by some other action. + * + * Enum values used to denote the various navigation types. + */ +typedef enum { + WEBKIT_NAVIGATION_TYPE_LINK_CLICKED, + WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED, + WEBKIT_NAVIGATION_TYPE_BACK_FORWARD, + WEBKIT_NAVIGATION_TYPE_RELOAD, + WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED, + WEBKIT_NAVIGATION_TYPE_OTHER, +} WebKitNavigationType; + +#define WEBKIT_TYPE_NAVIGATION_POLICY_DECISION (webkit_navigation_policy_decision_get_type()) +#define WEBKIT_NAVIGATION_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecision)) +#define WEBKIT_NAVIGATION_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecisionClass)) +#define WEBKIT_IS_NAVIGATION_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION)) +#define WEBKIT_IS_NAVIGATION_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION)) +#define WEBKIT_NAVIGATION_POLICY_DECISION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecisionClass)) + +typedef struct _WebKitNavigationPolicyDecision WebKitNavigationPolicyDecision; +typedef struct _WebKitNavigationPolicyDecisionClass WebKitNavigationPolicyDecisionClass; +typedef struct _WebKitNavigationPolicyDecisionPrivate WebKitNavigationPolicyDecisionPrivate; + +struct _WebKitNavigationPolicyDecision { + WebKitPolicyDecision parent; + + /*< private >*/ + WebKitNavigationPolicyDecisionPrivate *priv; +}; + +struct _WebKitNavigationPolicyDecisionClass { + WebKitPolicyDecisionClass parent_class; +}; + +WEBKIT_API GType +webkit_navigation_policy_decision_get_type (void); + +WEBKIT_API WebKitNavigationType +webkit_navigation_policy_decision_get_navigation_type (WebKitNavigationPolicyDecision *decision); +WEBKIT_API guint +webkit_navigation_policy_decision_get_mouse_button (WebKitNavigationPolicyDecision *decision); +WEBKIT_API guint +webkit_navigation_policy_decision_get_modifiers (WebKitNavigationPolicyDecision *decision); +WEBKIT_API WebKitURIRequest * +webkit_navigation_policy_decision_get_request (WebKitNavigationPolicyDecision *decision); +WEBKIT_API const gchar * +webkit_navigation_policy_decision_get_frame_name (WebKitNavigationPolicyDecision *decision); +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecisionPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecisionPrivate.h new file mode 100644 index 000000000..f3c0e1f50 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecisionPrivate.h @@ -0,0 +1,28 @@ +/* + * 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 WebKitNavigationPolicyDecisionPrivate_h +#define WebKitNavigationPolicyDecisionPrivate_h + +#include "WebKitNavigationPolicyDecision.h" +#include "WebKitPrivate.h" + +WebKitNavigationPolicyDecision* webkitNavigationPolicyDecisionCreate(WKFrameNavigationType, WKEventMouseButton, WKEventModifiers, WKURLRequestRef, const char* frameName, WKFramePolicyListenerRef); + +#endif // WebKitNavigationPolicyDecisionPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.cpp new file mode 100644 index 000000000..61757d428 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.cpp @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#include "config.h" +#include "WebKitPolicyClient.h" + +#include "WebKitNavigationPolicyDecisionPrivate.h" +#include "WebKitPolicyDecision.h" +#include "WebKitPrivate.h" +#include "WebKitWebViewBasePrivate.h" +#include "WebKitWebViewPrivate.h" +#include <wtf/gobject/GRefPtr.h> + +using namespace WebKit; + +static void decidePolicyForNavigationActionCallback(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) +{ + GRefPtr<WebKitNavigationPolicyDecision> decision = + adoptGRef(webkitNavigationPolicyDecisionCreate(navigationType, + mouseButton, + modifiers, + request, + 0, /* frame name */ + listener)); + webkitWebViewMakePolicyDecision(WEBKIT_WEB_VIEW(clientInfo), + WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION, + WEBKIT_POLICY_DECISION(decision.get())); +} + +static void decidePolicyForNewWindowActionCallback(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKStringRef frameName, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) +{ + GRefPtr<WebKitNavigationPolicyDecision> decision = + adoptGRef(webkitNavigationPolicyDecisionCreate(navigationType, + mouseButton, + modifiers, + request, + toImpl(frameName)->string().utf8().data(), + listener)); + webkitWebViewMakePolicyDecision(WEBKIT_WEB_VIEW(clientInfo), + WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION, + WEBKIT_POLICY_DECISION(decision.get())); +} + +void attachPolicyClientToPage(WebKitWebView* webView) +{ + WKPagePolicyClient policyClient = { + kWKPagePolicyClientCurrentVersion, + webView, // clientInfo + decidePolicyForNavigationActionCallback, + decidePolicyForNewWindowActionCallback, + 0, // decidePolicyForResponseCallback, + 0, // unableToImplementPolicy + }; + WKPageSetPagePolicyClient(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))), &policyClient); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.h new file mode 100644 index 000000000..90d8d62cc --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.h @@ -0,0 +1,27 @@ +/* + * 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 WebKitPolicyClient_h +#define WebKitPolicyClient_h + +#include "WebKitWebView.h" + +void attachPolicyClientToPage(WebKitWebView*); + +#endif // WebKitPolicyClient_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.cpp new file mode 100644 index 000000000..6b6759012 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.cpp @@ -0,0 +1,119 @@ +/* + * 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. + */ + +#include "config.h" +#include "WebKitPolicyDecision.h" + +#include "WebKitPolicyDecisionPrivate.h" +#include "WebKitPrivate.h" + + +/** + * SECTION: WebKitPolicyDecision + * @Short_description: A pending policy decision + * @Title: WebKitPolicyDecision + * @See_also: #WebKitWebView + * + * Often WebKit allows the client to decide the policy for certain + * operations. For instance, a client may want to open a link in a new + * tab, block a navigation entirely, query the user or trigger a download + * instead of a navigation. In these cases WebKit will fire the + * #WebKitWebView::decide-policy signal with a #WebKitPolicyDecision + * object. If the signal handler does nothing, WebKit will act as if + * webkit_policy_decision_use() was called as soon as signal handling + * completes. To make a policy decision asynchronously, simply increment + * the reference count of the #WebKitPolicyDecision object. + */ +G_DEFINE_ABSTRACT_TYPE(WebKitPolicyDecision, webkit_policy_decision, G_TYPE_OBJECT) + +struct _WebKitPolicyDecisionPrivate { + WKRetainPtr<WKFramePolicyListenerRef> listener; + bool madePolicyDecision; +}; + +static void webkit_policy_decision_init(WebKitPolicyDecision* decision) +{ + decision->priv = G_TYPE_INSTANCE_GET_PRIVATE(decision, WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecisionPrivate); + new (decision->priv) WebKitPolicyDecisionPrivate(); + decision->priv->madePolicyDecision = false; +} + +static void webkitPolicyDecisionFinalize(GObject* object) +{ + WebKitPolicyDecisionPrivate* priv = WEBKIT_POLICY_DECISION(object)->priv; + + // This is the default choice for all policy decisions in WebPageProxy.cpp. + if (!priv->madePolicyDecision) + WKFramePolicyListenerUse(priv->listener.get()); + + priv->~WebKitPolicyDecisionPrivate(); + G_OBJECT_CLASS(webkit_policy_decision_parent_class)->finalize(object); +} + +void webkitPolicyDecisionSetListener(WebKitPolicyDecision* decision, WKFramePolicyListenerRef listener) +{ + decision->priv->listener = listener; +} + +static void webkit_policy_decision_class_init(WebKitPolicyDecisionClass* decisionClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(decisionClass); + objectClass->finalize = webkitPolicyDecisionFinalize; + g_type_class_add_private(decisionClass, sizeof(WebKitPolicyDecisionPrivate)); +} + +/** + * webkit_policy_decision_use: + * @decision: a #WebKitPolicyDecision + * + * Accept the action which triggerd this decision. + */ +void webkit_policy_decision_use(WebKitPolicyDecision* decision) +{ + g_return_if_fail(WEBKIT_IS_POLICY_DECISION(decision)); + WKFramePolicyListenerUse(decision->priv->listener.get()); + decision->priv->madePolicyDecision = true; +} + +/** + * webkit_policy_decision_ignore: + * @decision: a #WebKitPolicyDecision + * + * Ignore the action which triggerd this decision. For instance, for a + * #WebKitResponsePolicyDecision, this would cancel the request. + */ +void webkit_policy_decision_ignore(WebKitPolicyDecision* decision) +{ + g_return_if_fail(WEBKIT_IS_POLICY_DECISION(decision)); + WKFramePolicyListenerIgnore(decision->priv->listener.get()); + decision->priv->madePolicyDecision = true; +} + +/** + * webkit_policy_decision_download: + * @decision: a #WebKitPolicyDecision + * + * Spawn a download from this decision. + */ +void webkit_policy_decision_download(WebKitPolicyDecision* decision) +{ + g_return_if_fail(WEBKIT_IS_POLICY_DECISION(decision)); + WKFramePolicyListenerDownload(decision->priv->listener.get()); + decision->priv->madePolicyDecision = true; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.h new file mode 100644 index 000000000..ecca5f9c3 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.h @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitPolicyDecision_h +#define WebKitPolicyDecision_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_POLICY_DECISION (webkit_policy_decision_get_type()) +#define WEBKIT_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecision)) +#define WEBKIT_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecisionClass)) +#define WEBKIT_IS_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_POLICY_DECISION)) +#define WEBKIT_IS_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_POLICY_DECISION)) +#define WEBKIT_POLICY_DECISION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecisionClass)) + +typedef struct _WebKitPolicyDecision WebKitPolicyDecision; +typedef struct _WebKitPolicyDecisionClass WebKitPolicyDecisionClass; +typedef struct _WebKitPolicyDecisionPrivate WebKitPolicyDecisionPrivate; + +struct _WebKitPolicyDecision { + GObject parent; + + /*< private >*/ + WebKitPolicyDecisionPrivate *priv; +}; + +struct _WebKitPolicyDecisionClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_policy_decision_get_type (void); + +WEBKIT_API void +webkit_policy_decision_use (WebKitPolicyDecision *decision); + +WEBKIT_API void +webkit_policy_decision_ignore (WebKitPolicyDecision *decision); + +WEBKIT_API void +webkit_policy_decision_download (WebKitPolicyDecision *decision); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h new file mode 100644 index 000000000..62580c83e --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h @@ -0,0 +1,28 @@ +/* + * 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 WebKitPolicyDecisionPrivate_h +#define WebKitPolicyDecisionPrivate_h + +#include "WebKitPolicyDecision.h" +#include <WebKit2/WebKit2.h> + +void webkitPolicyDecisionSetListener(WebKitPolicyDecision*, WKFramePolicyListenerRef); + +#endif // WebKitResponsePolicyDecisionPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index 423c464b0..13280d600 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -26,18 +26,18 @@ #ifndef WebKitPrivate_h #define WebKitPrivate_h +#include <WebKit2/WKAPICast.h> +#include <WebKit2/WKDownload.h> +#include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WebKit2.h> #include <glib.h> #include <wtf/Assertions.h> -G_BEGIN_DECLS - #define WEBKIT_PARAM_READABLE (static_cast<GParamFlags>(G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)) #define WEBKIT_PARAM_WRITABLE (static_cast<GParamFlags>(G_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)) #define WEBKIT_PARAM_READWRITE (static_cast<GParamFlags>(G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)) #define COMPILE_ASSERT_MATCHING_ENUM(webkitName, webcoreName) \ - COMPILE_ASSERT(int(webkitName) == int(WebCore::webcoreName), mismatchingEnums) - -G_END_DECLS + COMPILE_ASSERT(int(webkitName) == int(webcoreName), mismatchingEnums) #endif // WebKitPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index 837a9a1e5..06418613d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -33,9 +33,6 @@ #include "WebKitPrivate.h" #include "WebKitSettingsPrivate.h" -#include <WebKit2/WKAPICast.h> -#include <WebKit2/WKString.h> -#include <WebKit2/WKRetainPtr.h> #include <glib/gi18n-lib.h> #include <wtf/text/CString.h> @@ -103,7 +100,8 @@ enum { PROP_ENABLE_TABS_TO_LINKS, PROP_ENABLE_DNS_PREFETCHING, PROP_ENABLE_CARET_BROWSING, - PROP_ENABLE_FULLSCREEN + PROP_ENABLE_FULLSCREEN, + PROP_PRINT_BACKGROUNDS }; static void webKitSettingsSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -201,6 +199,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu case PROP_ENABLE_FULLSCREEN: webkit_settings_set_enable_fullscreen(settings, g_value_get_boolean(value)); break; + case PROP_PRINT_BACKGROUNDS: + webkit_settings_set_print_backgrounds(settings, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -302,6 +303,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val case PROP_ENABLE_FULLSCREEN: g_value_set_boolean(value, webkit_settings_get_enable_fullscreen(settings)); break; + case PROP_PRINT_BACKGROUNDS: + g_value_set_boolean(value, webkit_settings_get_print_backgrounds(settings)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -751,6 +755,19 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) FALSE, readWriteConstructParamFlags)); + /** + * WebKitSettings:print-backgrounds: + * + * Whether background images should be drawn during printing. + */ + g_object_class_install_property(gObjectClass, + PROP_PRINT_BACKGROUNDS, + g_param_spec_boolean("print-backgrounds", + _("Print Backgrounds"), + _("Whether background images should be drawn during printing"), + TRUE, + readWriteConstructParamFlags)); + g_type_class_add_private(klass, sizeof(WebKitSettingsPrivate)); } @@ -1885,7 +1902,7 @@ gboolean webkit_settings_get_enable_fullscreen(WebKitSettings* settings) } /** - * webkit_settings_set_enable_fullscreen + * webkit_settings_set_enable_fullscreen: * @settings: a #WebKitSettings * @enabled: Value to be set * @@ -1903,3 +1920,38 @@ void webkit_settings_set_enable_fullscreen(WebKitSettings* settings, gboolean en WKPreferencesSetFullScreenEnabled(priv->preferences.get(), enabled); g_object_notify(G_OBJECT(settings), "enable-fullscreen"); } + +/** + * webkit_settings_get_print_backgrounds: + * @settings: a #WebKitSettings + * + * Get the #WebKitSettings:print-backgrounds property. + * + * Returns: %TRUE If background images should be printed or %FALSE otherwise. + */ +gboolean webkit_settings_get_print_backgrounds(WebKitSettings* settings) +{ + g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); + + return WKPreferencesGetShouldPrintBackgrounds(settings->priv->preferences.get()); +} + +/** + * webkit_settings_set_print_backgrounds: + * @settings: a #WebKitSettings + * @print_backgrounds: Value to be set + * + * Set the #WebKitSettings:print-backgrounds property. + */ +void webkit_settings_set_print_backgrounds(WebKitSettings* settings, gboolean printBackgrounds) +{ + g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); + + WebKitSettingsPrivate* priv = settings->priv; + bool currentValue = WKPreferencesGetShouldPrintBackgrounds(priv->preferences.get()); + if (currentValue == printBackgrounds) + return; + + WKPreferencesSetShouldPrintBackgrounds(priv->preferences.get(), printBackgrounds); + g_object_notify(G_OBJECT(settings), "print-backgrounds"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h index 8b19a465b..a6769fc0e 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h @@ -286,6 +286,13 @@ WEBKIT_API void webkit_settings_set_enable_fullscreen (WebKitSettings *settings, gboolean enabled); +WEBKIT_API gboolean +webkit_settings_get_print_backgrounds (WebKitSettings *settings); + +WEBKIT_API void +webkit_settings_set_print_backgrounds (WebKitSettings *settings, + gboolean print_backgrounds); + G_END_DECLS #endif /* WebKitSettings_h */ diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp index fcfdddb53..a659ad314 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Igalia S.L. + * Copyright (C) 2011, 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 @@ -20,117 +20,117 @@ #include "config.h" #include "WebKitUIClient.h" +#include "WebKitPrivate.h" +#include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebPageProxy.h" -#include <WebKit2/WKBase.h> +#include <WebCore/GtkUtilities.h> using namespace WebKit; -G_DEFINE_TYPE(WebKitUIClient, webkit_ui_client, G_TYPE_OBJECT) - -static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef, WKDictionaryRef wkWindowFeatures, WKEventModifiers, WKEventMouseButton, const void*) +static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef, WKDictionaryRef wkWindowFeatures, WKEventModifiers, WKEventMouseButton, const void* clientInfo) { - return webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), wkWindowFeatures); + return webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(clientInfo), wkWindowFeatures); } -static void showPage(WKPageRef page, const void*) +static void showPage(WKPageRef page, const void* clientInfo) { - webkitWebViewReadyToShowPage(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + webkitWebViewReadyToShowPage(WEBKIT_WEB_VIEW(clientInfo)); } -static void closePage(WKPageRef page, const void*) +static void closePage(WKPageRef page, const void* clientInfo) { - webkitWebViewClosePage(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + webkitWebViewClosePage(WEBKIT_WEB_VIEW(clientInfo)); } -static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef, const void*) +static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef, const void* clientInfo) { - webkitWebViewRunJavaScriptAlert(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(message)->string().utf8()); + webkitWebViewRunJavaScriptAlert(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8()); } -static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef, const void*) +static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef, const void* clientInfo) { - return webkitWebViewRunJavaScriptConfirm(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(message)->string().utf8()); + return webkitWebViewRunJavaScriptConfirm(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8()); } -static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void*) +static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void* clientInfo) { - return webkitWebViewRunJavaScriptPrompt(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(message)->string().utf8(), + return webkitWebViewRunJavaScriptPrompt(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8(), toImpl(defaultValue)->string().utf8()); } -static bool toolbarsAreVisible(WKPageRef page, const void*) +static bool toolbarsAreVisible(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_toolbar_visible(windowProperties); } -static void setToolbarsAreVisible(WKPageRef page, bool toolbarsVisible, const void*) +static void setToolbarsAreVisible(WKPageRef page, bool toolbarsVisible, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetToolbarVisible(windowProperties, toolbarsVisible); } -static bool menuBarIsVisible(WKPageRef page, const void*) +static bool menuBarIsVisible(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_menubar_visible(windowProperties); } -static void setMenuBarIsVisible(WKPageRef page, bool menuBarVisible, const void*) +static void setMenuBarIsVisible(WKPageRef page, bool menuBarVisible, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetMenubarVisible(windowProperties, menuBarVisible); } -static bool statusBarIsVisible(WKPageRef page, const void*) +static bool statusBarIsVisible(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_statusbar_visible(windowProperties); } -static void setStatusBarIsVisible(WKPageRef page, bool statusBarVisible, const void*) +static void setStatusBarIsVisible(WKPageRef page, bool statusBarVisible, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetStatusbarVisible(windowProperties, statusBarVisible); } -static bool isResizable(WKPageRef page, const void*) +static bool isResizable(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_resizable(windowProperties); } -static void setIsResizable(WKPageRef page, bool resizable, const void*) +static void setIsResizable(WKPageRef page, bool resizable, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetResizable(windowProperties, resizable); } -static WKRect getWindowFrame(WKPageRef page, const void*) +static WKRect getWindowFrame(WKPageRef page, const void* clientInfo) { GdkRectangle geometry = { 0, 0, 0, 0 }; - GtkWidget* window = gtk_widget_get_toplevel(toImpl(page)->viewWidget()); - if (gtk_widget_is_toplevel(window) && gtk_widget_get_visible(window)) { + GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(clientInfo)); + if (WebCore::widgetIsOnscreenToplevelWindow(window) && gtk_widget_get_visible(window)) { gtk_window_get_position(GTK_WINDOW(window), &geometry.x, &geometry.y); gtk_window_get_size(GTK_WINDOW(window), &geometry.width, &geometry.height); } return WKRectMake(geometry.x, geometry.y, geometry.width, geometry.height); } -static void setWindowFrame(WKPageRef page, WKRect frame, const void*) +static void setWindowFrame(WKPageRef page, WKRect frame, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); GdkRectangle geometry = { frame.origin.x, frame.origin.y, frame.size.width, frame.size.height }; webkitWindowPropertiesSetGeometry(windowProperties, &geometry); } -void webkitUIClientAttachUIClientToPage(WebKitUIClient* uiClient, WKPageRef wkPage) +void attachUIClientToView(WebKitWebView* webView) { WKPageUIClient wkUIClient = { kWKPageUIClientCurrentVersion, - uiClient, // clientInfo + webView, // clientInfo 0, // createNewPage_deprecatedForUseWithV0 showPage, closePage, @@ -174,13 +174,7 @@ void webkitUIClientAttachUIClientToPage(WebKitUIClient* uiClient, WKPageRef wkPa 0, // mouseDidMoveOverElement 0, // decidePolicyForNotificationPermissionRequest }; + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); WKPageSetPageUIClient(wkPage, &wkUIClient); } -static void webkit_ui_client_init(WebKitUIClient* client) -{ -} - -static void webkit_ui_client_class_init(WebKitUIClientClass* clientClass) -{ -} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h index 41ef3ec25..e5a1a3e0f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h @@ -20,33 +20,8 @@ #ifndef WebKitUIClient_h #define WebKitUIClient_h -#include <WebKit2/WebKit2.h> -#include <glib-object.h> +#include "WebKitWebView.h" -G_BEGIN_DECLS - -#define WEBKIT_TYPE_UI_CLIENT (webkit_ui_client_get_type()) -#define WEBKIT_UI_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_UI_CLIENT, WebKitUIClient)) -#define WEBKIT_UI_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_UI_CLIENT, WebKitUIClientClass)) -#define WEBKIT_IS_UI_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_UI_CLIENT)) -#define WEBKIT_IS_UI_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_UI_CLIENT)) -#define WEBKIT_UI_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_UI_CLIENT, WebKitUIClientClass)) - -typedef struct _WebKitUIClient WebKitUIClient; -typedef struct _WebKitUIClientClass WebKitUIClientClass; - -struct _WebKitUIClient { - GObject parent; -}; - -struct _WebKitUIClientClass { - GObjectClass parent_class; -}; - -GType webkit_ui_client_get_type (void); - -void webkitUIClientAttachUIClientToPage(WebKitUIClient*, WKPageRef); - -G_END_DECLS +void attachUIClientToView(WebKitWebView*); #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp index 154532a83..b5c2b4e74 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp @@ -21,9 +21,8 @@ #include "WebKitURIRequest.h" #include "WebKitPrivate.h" -#include "WebURLRequest.h" +#include "WebKitURIRequestPrivate.h" #include <glib/gi18n-lib.h> -#include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> enum { @@ -37,6 +36,7 @@ using namespace WebCore; G_DEFINE_TYPE(WebKitURIRequest, webkit_uri_request, G_TYPE_OBJECT) struct _WebKitURIRequestPrivate { + WebCore::ResourceRequest resourceRequest; CString uri; }; @@ -65,7 +65,7 @@ static void webkitURIRequestSetProperty(GObject* object, guint propId, const GVa switch (propId) { case PROP_URI: - request->priv->uri = g_value_get_string(value); + request->priv->resourceRequest.setURL(KURL(KURL(), g_value_get_string(value))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); @@ -117,6 +117,13 @@ WebKitURIRequest* webkit_uri_request_new(const gchar* uri) return WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, "uri", uri, NULL)); } +WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest& resourceRequest) +{ + WebKitURIRequest* uriRequest = WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, NULL)); + uriRequest->priv->resourceRequest = resourceRequest; + return uriRequest; +} + /** * webkit_uri_request_get_uri: * @request: a #WebKitURIRequest @@ -127,6 +134,7 @@ const gchar* webkit_uri_request_get_uri(WebKitURIRequest* request) { g_return_val_if_fail(WEBKIT_IS_URI_REQUEST(request), 0); + request->priv->uri = request->priv->resourceRequest.url().string().utf8(); return request->priv->uri.data(); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h new file mode 100644 index 000000000..db85242af --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebKitURIRequestPrivate_h +#define WebKitURIRequestPrivate_h + +#include "WebKitURIRequest.h" +#include <WebCore/ResourceRequest.h> + +WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest&); + +#endif // WebKitURIRequestPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp index 2a74cd03a..174bf12f8 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp @@ -22,10 +22,7 @@ #include "WebKitPrivate.h" #include "WebKitURIResponsePrivate.h" -#include "WebURLResponse.h" #include <glib/gi18n-lib.h> -#include <wtf/gobject/GOwnPtr.h> -#include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> enum { @@ -41,9 +38,8 @@ using namespace WebCore; G_DEFINE_TYPE(WebKitURIResponse, webkit_uri_response, G_TYPE_OBJECT) struct _WebKitURIResponsePrivate { + WebCore::ResourceResponse resourceResponse; CString uri; - GRefPtr<SoupMessage> message; - guint64 contentLength; }; static void webkitURIResponseFinalize(GObject* object) @@ -71,26 +67,12 @@ static void webkitURIResponseGetProperty(GObject* object, guint propId, GValue* } } -static void webkitURIResponseSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) -{ - WebKitURIResponse* response = WEBKIT_URI_RESPONSE(object); - - switch (propId) { - case PROP_URI: - response->priv->uri = g_value_get_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); - } -} - static void webkit_uri_response_class_init(WebKitURIResponseClass* responseClass) { GObjectClass* objectClass = G_OBJECT_CLASS(responseClass); objectClass->finalize = webkitURIResponseFinalize; objectClass->get_property = webkitURIResponseGetProperty; - objectClass->set_property = webkitURIResponseSetProperty; /** * WebKitURIResponse:uri: @@ -103,7 +85,7 @@ static void webkit_uri_response_class_init(WebKitURIResponseClass* responseClass _("URI"), _("The URI for which the response was made."), 0, - static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + WEBKIT_PARAM_READABLE)); /** * WebKitURIResponse:status-code: * @@ -150,6 +132,7 @@ const gchar* webkit_uri_response_get_uri(WebKitURIResponse* response) { g_return_val_if_fail(WEBKIT_IS_URI_RESPONSE(response), 0); + response->priv->uri = response->priv->resourceResponse.url().string().utf8(); return response->priv->uri.data(); } @@ -168,10 +151,7 @@ guint webkit_uri_response_get_status_code(WebKitURIResponse* response) { g_return_val_if_fail(WEBKIT_IS_URI_RESPONSE(response), SOUP_STATUS_NONE); - if (!response->priv->message) - return SOUP_STATUS_NONE; - - return response->priv->message->status_code; + return response->priv->resourceResponse.httpStatusCode(); } /** @@ -187,30 +167,17 @@ guint64 webkit_uri_response_get_content_length(WebKitURIResponse* response) { g_return_val_if_fail(WEBKIT_IS_URI_RESPONSE(response), 0); - if (response->priv->contentLength) - return response->priv->contentLength; - - if (!response->priv->message) - return 0; - - SoupMessage* message = response->priv->message.get(); - return static_cast<guint64>(soup_message_headers_get_content_length(message->response_headers)); -} - -WebKitURIResponse* webkitURIResponseCreateForSoupMessage(SoupMessage* message) -{ - GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(message), FALSE)); - WebKitURIResponse* response = WEBKIT_URI_RESPONSE(g_object_new(WEBKIT_TYPE_URI_RESPONSE, "uri", uri.get(), NULL)); - response->priv->message = message; - return response; + return response->priv->resourceResponse.expectedContentLength(); } -SoupMessage* webkitURIResponseGetSoupMessage(WebKitURIResponse* response) +WebKitURIResponse* webkitURIResponseCreateForResourceResponse(const WebCore::ResourceResponse& resourceResponse) { - return response->priv->message.get(); + WebKitURIResponse* uriResponse = WEBKIT_URI_RESPONSE(g_object_new(WEBKIT_TYPE_URI_RESPONSE, NULL)); + uriResponse->priv->resourceResponse = resourceResponse; + return uriResponse; } -void webkitURIResponseSetContentLength(WebKitURIResponse* response, guint64 contentLength) +const WebCore::ResourceResponse& webkitURIResponseGetResourceResponse(WebKitURIResponse* uriResponse) { - response->priv->contentLength = contentLength; + return uriResponse->priv->resourceResponse; } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h index fe84f8b1c..c2dc49c17 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h @@ -27,10 +27,9 @@ #define WebKitURIResponsePrivate_h #include "WebKitURIResponse.h" -#include <libsoup/soup.h> +#include <WebCore/ResourceResponse.h> -WebKitURIResponse* webkitURIResponseCreateForSoupMessage(SoupMessage*); -SoupMessage* webkitURIResponseGetSoupMessage(WebKitURIResponse*); -void webkitURIResponseSetContentLength(WebKitURIResponse*, guint64 contentLength); +WebKitURIResponse* webkitURIResponseCreateForResourceResponse(const WebCore::ResourceResponse&); +const WebCore::ResourceResponse& webkitURIResponseGetResourceResponse(WebKitURIResponse*); #endif // WebKitURIResponsePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 1f9590c52..360b0a627 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -20,15 +20,29 @@ #include "config.h" #include "WebKitWebContext.h" +#include "WebContext.h" +#include "WebKitDownloadClient.h" +#include "WebKitDownloadPrivate.h" +#include "WebKitPrivate.h" #include "WebKitWebContextPrivate.h" -#include <WebKit2/WKContext.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKType.h> +#include <wtf/HashMap.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + DOWNLOAD_STARTED, + + LAST_SIGNAL +}; struct _WebKitWebContextPrivate { WKRetainPtr<WKContextRef> context; }; +static guint signals[LAST_SIGNAL] = { 0, }; + G_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT) static void webkitWebContextFinalize(GObject* object) @@ -49,15 +63,32 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass GObjectClass* gObjectClass = G_OBJECT_CLASS(webContextClass); gObjectClass->finalize = webkitWebContextFinalize; + /** + * WebKitWebContext::download-started: + * @context: the #WebKitWebContext + * @download: the #WebKitDownload associated with this event + * + * This signal is emitted when a new download request is made. + */ + signals[DOWNLOAD_STARTED] = + g_signal_new("download-started", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + WEBKIT_TYPE_DOWNLOAD); + g_type_class_add_private(webContextClass, sizeof(WebKitWebContextPrivate)); } - static gpointer createDefaultWebContext(gpointer) { WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL)); webContext->priv->context = WKContextGetSharedProcessContext(); WKContextSetCacheModel(webContext->priv->context.get(), kWKCacheModelPrimaryWebBrowser); + attachDownloadClientToContext(webContext); + return webContext; } @@ -152,6 +183,59 @@ WebKitCacheModel webkit_web_context_get_cache_model(WebKitWebContext* context) return WEBKIT_CACHE_MODEL_WEB_BROWSER; } +typedef HashMap<WKDownloadRef, GRefPtr<WebKitDownload> > DownloadsMap; + +static DownloadsMap& downloadsMap() +{ + DEFINE_STATIC_LOCAL(DownloadsMap, downloads, ()); + return downloads; +} + +/** + * webkit_web_context_download_uri: + * @context: a #WebKitWebContext + * @uri: the URI to download + * + * Requests downloading of the specified URI string. + * + * Returns: (transfer full): a new #WebKitDownload representing the + * the download operation. + */ +WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const gchar* uri) +{ + 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); + return download; +} + +WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) +{ + GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); + if (download) + return download.get(); + + download = adoptGRef(webkitDownloadCreate(wkDownload)); + downloadsMap().set(wkDownload, download.get()); + return download.get(); +} + +void webkitWebContextRemoveDownload(WKDownloadRef wkDownload) +{ + downloadsMap().remove(wkDownload); +} + +void webkitWebContextDownloadStarted(WebKitWebContext* context, WebKitDownload* download) +{ + g_signal_emit(context, signals[DOWNLOAD_STARTED], 0, download); +} + WKContextRef webkitWebContextGetWKContext(WebKitWebContext* context) { g_assert(WEBKIT_IS_WEB_CONTEXT(context)); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index 2f38dbc25..b88bed0da 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -26,6 +26,7 @@ #include <glib-object.h> #include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitDownload.h> G_BEGIN_DECLS @@ -89,6 +90,10 @@ webkit_web_context_set_cache_model (WebKitWebContext *context, WEBKIT_API WebKitCacheModel webkit_web_context_get_cache_model (WebKitWebContext *context); +WEBKIT_API WebKitDownload * +webkit_web_context_download_uri (WebKitWebContext *context, + const gchar *uri); + G_END_DECLS #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h index 86d7dec8b..d2dd81361 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h @@ -32,6 +32,9 @@ G_BEGIN_DECLS WKContextRef webkitWebContextGetWKContext(WebKitWebContext*); +WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef); +void webkitWebContextRemoveDownload(WKDownloadRef); +void webkitWebContextDownloadStarted(WebKitWebContext*, WebKitDownload*); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h deleted file mode 100644 index c6044bc07..000000000 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 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 WebKitWebLoaderClient_h -#define WebKitWebLoaderClient_h - -#include <glib-object.h> -#include <WebKit2/WebKit2.h> - -G_BEGIN_DECLS - -#define WEBKIT_TYPE_WEB_LOADER_CLIENT (webkit_web_loader_client_get_type()) -#define WEBKIT_WEB_LOADER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClient)) -#define WEBKIT_WEB_LOADER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientClass)) -#define WEBKIT_IS_WEB_LOADER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT)) -#define WEBKIT_IS_WEB_LOADER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_LOADER_CLIENT)) -#define WEBKIT_WEB_LOADER_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientClass)) - -typedef struct _WebKitWebLoaderClient WebKitWebLoaderClient; -typedef struct _WebKitWebLoaderClientClass WebKitWebLoaderClientClass; - -struct _WebKitWebLoaderClient { - GObject parent; -}; - -struct _WebKitWebLoaderClientClass { - GObjectClass parentClass; -}; - -GType webkit_web_loader_client_get_type (void); -void webkitWebLoaderClientAttachLoaderClientToPage(WebKitWebLoaderClient*, WKPageRef); - -G_END_DECLS - -#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index fd2bb5190..fcaa2db1d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -24,20 +24,19 @@ #include "WebKitBackForwardListPrivate.h" #include "WebKitEnumTypes.h" #include "WebKitError.h" +#include "WebKitLoaderClient.h" #include "WebKitMarshal.h" +#include "WebKitPolicyClient.h" #include "WebKitSettingsPrivate.h" #include "WebKitUIClient.h" #include "WebKitWebContextPrivate.h" -#include "WebKitWebLoaderClient.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebKitPrivate.h" #include "WebPageProxy.h" #include <WebCore/DragIcon.h> -#include <WebKit2/WKBase.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKURL.h> +#include <WebCore/GtkUtilities.h> #include <glib/gi18n-lib.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> @@ -58,6 +57,8 @@ enum { SCRIPT_CONFIRM, SCRIPT_PROMPT, + DECIDE_POLICY, + LAST_SIGNAL }; @@ -79,8 +80,6 @@ struct _WebKitWebViewPrivate { CString activeURI; bool replacingContent; - GRefPtr<WebKitWebLoaderClient> loaderClient; - GRefPtr<WebKitUIClient> uiClient; GRefPtr<WebKitBackForwardList> backForwardList; GRefPtr<WebKitSettings> settings; GRefPtr<WebKitWindowProperties> windowProperties; @@ -111,7 +110,7 @@ static GtkWidget* webkitWebViewCreate(WebKitWebView*) static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* message) { GtkWidget* parent = gtk_widget_get_toplevel(GTK_WIDGET(webView)); - GtkWidget* dialog = gtk_message_dialog_new(gtk_widget_is_toplevel(parent) ? GTK_WINDOW(parent) : 0, + GtkWidget* dialog = gtk_message_dialog_new(widgetIsOnscreenToplevelWindow(parent) ? GTK_WINDOW(parent) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", message); GOwnPtr<char> title(g_strdup_printf("JavaScript - %s", webkit_web_view_get_uri(webView))); gtk_window_set_title(GTK_WINDOW(dialog), title.get()); @@ -149,10 +148,10 @@ static gboolean webkitWebViewScriptPrompt(WebKitWebView* webView, const char* me return TRUE; } -static void webkitWebViewSetLoaderClient(WebKitWebView* webView, WebKitWebLoaderClient* loaderClient, WKPageRef wkPage) +static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* decision, WebKitPolicyDecisionType) { - webView->priv->loaderClient = loaderClient; - webkitWebLoaderClientAttachLoaderClientToPage(loaderClient, wkPage); + webkit_policy_decision_use(decision); + return TRUE; } static void webkitWebViewConstructed(GObject* object) @@ -166,15 +165,11 @@ static void webkitWebViewConstructed(GObject* object) webkitWebViewBaseCreateWebPage(webViewBase, webkitWebContextGetWKContext(priv->context), 0); - WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); - - static GRefPtr<WebKitWebLoaderClient> defaultLoaderClient = adoptGRef(WEBKIT_WEB_LOADER_CLIENT(g_object_new(WEBKIT_TYPE_WEB_LOADER_CLIENT, NULL))); - webkitWebViewSetLoaderClient(webView, defaultLoaderClient.get(), toAPI(page)); - - static GRefPtr<WebKitUIClient> defaultUIClient = adoptGRef(WEBKIT_UI_CLIENT(g_object_new(WEBKIT_TYPE_UI_CLIENT, NULL))); - priv->uiClient = defaultUIClient.get(); - webkitUIClientAttachUIClientToPage(priv->uiClient.get(), toAPI(page)); + attachLoaderClientToView(webView); + attachUIClientToView(webView); + attachPolicyClientToPage(webView); + WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page)))); priv->settings = adoptGRef(webkit_settings_new()); webkitSettingsAttachSettingsToPage(priv->settings.get(), toAPI(page)); @@ -259,6 +254,7 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webViewClass->script_alert = webkitWebViewScriptAlert; webViewClass->script_confirm = webkitWebViewScriptConfirm; webViewClass->script_prompt = webkitWebViewScriptPrompt; + webViewClass->decide_policy = webkitWebViewDecidePolicy; g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate)); @@ -557,6 +553,66 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + /** + * WebKitPolicyClient::decide-policy + * @web_view: the #WebKitWebView on which the signal is emitted + * @decision: the #WebKitNavigationPolicyDecision + * @decision_type: a #WebKitPolicyDecisionType denoting the type of @decision + * + * This signal is emitted when WebKit is requesting the client to decide a policy + * decision, such as whether to navigate to a page, open a new window or whether or + * not to download a resource. The #WebKitNavigationPolicyDecision passed in the + * @decision argument is a generic type, but should be casted to a more + * specific type when making the decision. For example: + * + * <informalexample><programlisting> + * static gboolean + * decide_policy_cb (WebKitWebView *web_view, + * WebKitPolicyDecision *decision, + * WebKitPolicyDecisionType type) + * { + * switch (type) { + * case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: + * WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); + * /<!-- -->* Make a policy decision here. *<!-- -->/ + * break; + * case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: + * WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); + * /<!-- -->* Make a policy decision here. *<!-- -->/ + * break; + * case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: + * WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision); + * /<!-- -->* Make a policy decision here. *<!-- -->/ + * break; + * default: + * /<!-- -->* Making no decision results in webkit_policy_decision_use(). *<!-- -->/ + * return FALSE; + * } + * return TRUE; + * } + * </programlisting></informalexample> + * + * It is possible to make policy decision asynchronously, by simply calling g_object_ref() + * on the @decision argument and returning %TRUE to block the default signal handler. + * If the last reference is removed on a #WebKitPolicyDecision and no decision has been + * made explicitly, webkit_policy_decision_use() will be the default policy decision. The + * default signal handler will simply call webkit_policy_decision_use(). Only the first + * policy decision chosen for a given #WebKitPolicyDecision will have any affect. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + * + */ + signals[DECIDE_POLICY] = + g_signal_new("decide-policy", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, decide_policy), + g_signal_accumulator_true_handled, 0 /* accumulator data */, + webkit_marshal_BOOLEAN__OBJECT_ENUM, + G_TYPE_BOOLEAN, 2, /* number of parameters */ + WEBKIT_TYPE_POLICY_DECISION, + WEBKIT_TYPE_POLICY_DECISION_TYPE); } void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent) @@ -662,6 +718,12 @@ WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CStri return text ? WKStringCreateWithUTF8CString(text.get()) : 0; } +void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision) +{ + gboolean returnValue; + g_signal_emit(webView, signals[DECIDE_POLICY], 0, decision, type, &returnValue); +} + /** * webkit_web_view_new: * diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h index a25c438dd..697fcdc80 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h @@ -35,9 +35,44 @@ #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> +#include <webkit2/WebKitPolicyDecision.h> G_BEGIN_DECLS +/** + * WebKitPolicyDecisionType: + * @WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: This type of policy decision + * is requested when WebKit is about to navigate to a new page in either the + * main frame or a subframe. Acceptable policy decisions are either + * webkit_policy_decision_use() or webkit_policy_decision_ignore(). This + * type of policy decision is always a #WebKitNavigationPolicyDecision. + * @WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: This type of policy decision + * is requested when WebKit is about to create a new window. Acceptable policy + * decisions are either webkit_policy_decision_use() or + * webkit_policy_decision_ignore(). This type of policy decision is always + * a #WebKitNavigationPolicyDecision. These decisions are useful for implementing + * special actions for new windows, such as forcing the new window to open + * in a tab when a keyboard modifier is active or handling a special + * target attribute on <a> elements. + * @WEBKIT_POLICY_DECISION_TYPE_RESPONSE: This type of decision is used when WebKit has + * received a response for a network resource and is about to start the load. + * Note that these resources include all subresources of a page such as images + * and stylesheets as well as main documents. Appropriate policy responses to + * this decision are webkit_policy_decision_use(), webkit_policy_decision_ignore(), + * or webkit_policy_decision_download(). This type of policy decision is always + * a #WebKitResponsePolicyDecision. This decision is useful for forcing + * some types of resources to be downloaded rather than rendered in the WebView + * or to block the transfer of resources entirely. + * + * Enum values used for determining the type of a policy decision during + * WebKitWebView::decide-policy. + */ +typedef enum { + WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION, + WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION, + WEBKIT_POLICY_DECISION_TYPE_RESPONSE, +} WebKitPolicyDecisionType; + #define WEBKIT_TYPE_WEB_VIEW (webkit_web_view_get_type()) #define WEBKIT_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_VIEW, WebKitWebView)) #define WEBKIT_WEB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_VIEW, WebKitWebViewClass)) @@ -81,26 +116,29 @@ struct _WebKitWebView { struct _WebKitWebViewClass { WebKitWebViewBaseClass parent; - void (* load_changed) (WebKitWebView *web_view, - WebKitLoadEvent load_event); - gboolean (* load_failed) (WebKitWebView *web_view, - WebKitLoadEvent load_event, - const gchar *failing_uri, - GError *error); - - GtkWidget *(* create) (WebKitWebView *web_view); - void (* ready_to_show) (WebKitWebView *web_view); - void (* close) (WebKitWebView *web_view); - - gboolean (* script_alert) (WebKitWebView *web_view, - const gchar *message); - gboolean (* script_confirm) (WebKitWebView *web_view, - const gchar *message, - gboolean *confirmed); - gboolean (* script_prompt) (WebKitWebView *web_view, - const gchar *message, - const gchar *default_text, - gchar **text); + void (* load_changed) (WebKitWebView *web_view, + WebKitLoadEvent load_event); + gboolean (* load_failed) (WebKitWebView *web_view, + WebKitLoadEvent load_event, + const gchar *failing_uri, + GError *error); + + GtkWidget *(* create) (WebKitWebView *web_view); + void (* ready_to_show) (WebKitWebView *web_view); + void (* close) (WebKitWebView *web_view); + + gboolean (* script_alert) (WebKitWebView *web_view, + const gchar *message); + gboolean (* script_confirm) (WebKitWebView *web_view, + const gchar *message, + gboolean *confirmed); + gboolean (* script_prompt) (WebKitWebView *web_view, + const gchar *message, + const gchar *default_text, + gchar **text); + gboolean (* decide_policy) (WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType type); /* Padding for future expansion */ void (*_webkit_reserved0) (void); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index 86607162f..d9ccaa32a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -35,6 +35,8 @@ #include "PageClientImpl.h" #include "WebContext.h" #include "WebEventFactory.h" +#include "WebKitPrivate.h" +#include "WebKitWebViewBaseAccessible.h" #include "WebKitWebViewBasePrivate.h" #include "WebPageProxy.h" #include <WebCore/ClipboardGtk.h> @@ -50,7 +52,6 @@ #include <WebCore/PasteboardHelper.h> #include <WebCore/RefPtrCairo.h> #include <WebCore/Region.h> -#include <WebKit2/WKContext.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> @@ -69,6 +70,7 @@ struct _WebKitWebViewBasePrivate { GtkDragAndDropHelper dragAndDropHelper; DragIcon dragIcon; IntSize resizerSize; + GRefPtr<AtkObject> accessible; }; G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER) @@ -118,6 +120,7 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK @@ -139,7 +142,7 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) gtk_im_context_set_client_window(priv->imContext.get(), window); GtkWidget* toplevel = gtk_widget_get_toplevel(widget); - if (gtk_widget_is_toplevel(toplevel) && GTK_IS_WINDOW(toplevel)) { + if (widgetIsOnscreenToplevelWindow(toplevel)) { webkitWebViewBaseNotifyResizerSizeForWindow(webView, GTK_WINDOW(toplevel)); g_signal_connect(toplevel, "notify::resize-grip-visible", G_CALLBACK(toplevelWindowResizeGripVisibilityChanged), webView); @@ -211,7 +214,7 @@ static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allo priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize()); GtkWidget* toplevel = gtk_widget_get_toplevel(widget); - if (gtk_widget_is_toplevel(toplevel) && GTK_IS_WINDOW(toplevel)) + if (widgetIsOnscreenToplevelWindow(toplevel)) webkitWebViewBaseNotifyResizerSizeForWindow(webViewBase, GTK_WINDOW(toplevel)); } @@ -221,7 +224,7 @@ static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* WebKitWebViewBasePrivate* priv = webViewBase->priv; GtkWidget* toplevel = gtk_widget_get_toplevel(widget); - if (gtk_widget_is_toplevel(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) { + if (widgetIsOnscreenToplevelWindow(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) { gtk_im_context_focus_in(priv->imContext.get()); if (!priv->isPageActive) { priv->isPageActive = TRUE; @@ -374,6 +377,34 @@ static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time); } +static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget) +{ + // If the socket has already been created and embedded a plug ID, return it. + WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv; + if (priv->accessible && atk_socket_is_occupied(ATK_SOCKET(priv->accessible.get()))) + return priv->accessible.get(); + + // Create the accessible object and associate it to the widget. + if (!priv->accessible) { + priv->accessible = adoptGRef(ATK_OBJECT(webkitWebViewBaseAccessibleNew(widget))); + + // Set the parent not to break bottom-up navigation. + GtkWidget* parentWidget = gtk_widget_get_parent(widget); + AtkObject* axParent = parentWidget ? gtk_widget_get_accessible(parentWidget) : 0; + if (axParent) + atk_object_set_parent(priv->accessible.get(), axParent); + } + + // Try to embed the plug in the socket, if posssible. + String plugID = priv->pageProxy->accessibilityPlugID(); + if (plugID.isNull()) + return priv->accessible.get(); + + atk_socket_embed(ATK_SOCKET(priv->accessible.get()), const_cast<gchar*>(plugID.utf8().data())); + + return priv->accessible.get(); +} + static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time) { WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget); @@ -438,6 +469,7 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie widgetClass->drag_leave = webkitWebViewBaseDragLeave; widgetClass->drag_drop = webkitWebViewBaseDragDrop; widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived; + widgetClass->get_accessible = webkitWebViewBaseGetAccessible; GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass); gobjectClass->finalize = webkitWebViewBaseFinalize; diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp new file mode 100644 index 000000000..09a11abe6 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#include "config.h" +#include "WebKitWebViewBaseAccessible.h" + +#include <gtk/gtk.h> + +struct _WebKitWebViewBaseAccessiblePrivate { + GtkWidget* widget; +}; + +G_DEFINE_TYPE(WebKitWebViewBaseAccessible, webkit_web_view_base_accessible, ATK_TYPE_SOCKET) + +static void webkitWebViewBaseAccessibleFinalize(GObject* gobject) +{ + WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(gobject); + accessible->priv->~WebKitWebViewBaseAccessiblePrivate(); + G_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->finalize(gobject); +} + +static void webkitWebViewBaseAccessibleWidgetDestroyed(GtkWidget* widget, WebKitWebViewBaseAccessible* accessible) +{ + accessible->priv->widget = 0; + atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_DEFUNCT, TRUE); +} + +static void webkitWebViewBaseAccessibleInitialize(AtkObject* atkObject, gpointer data) +{ + if (ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->initialize) + ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->initialize(atkObject, data); + + if (data && GTK_IS_WIDGET(data)) { + WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(atkObject); + accessible->priv->widget = GTK_WIDGET(data); + + g_signal_connect_after(accessible->priv->widget, "destroy", + G_CALLBACK(webkitWebViewBaseAccessibleWidgetDestroyed), atkObject); + } + + atk_object_set_role(atkObject, ATK_ROLE_FILLER); +} + +static AtkStateSet* webkitWebViewBaseAccessibleRefStateSet(AtkObject* atkObject) +{ + WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(atkObject); + + AtkStateSet* stateSet; + if (accessible->priv->widget) { + // Use the implementation of AtkSocket if the widget is still alive. + stateSet = ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->ref_state_set(atkObject); + } else { + // If the widget is no longer alive, save some remote calls + // (because of AtkSocket's implementation of ref_state_set()) + // and just return that this AtkObject is defunct. + stateSet = atk_state_set_new(); + atk_state_set_add_state(stateSet, ATK_STATE_DEFUNCT); + } + + return stateSet; +} + +static gint webkitWebViewBaseAccessibleGetIndexInParent(AtkObject* atkObject) +{ + AtkObject* atkParent = atk_object_get_parent(atkObject); + if (!atkParent) + return -1; + + guint count = atk_object_get_n_accessible_children(atkParent); + for (guint i = 0; i < count; ++i) { + AtkObject* child = atk_object_ref_accessible_child(atkParent, i); + bool childIsObject = child == atkObject; + g_object_unref(child); + if (childIsObject) + return i; + } + + return -1; +} + +static void webkit_web_view_base_accessible_init(WebKitWebViewBaseAccessible* accessible) +{ + WebKitWebViewBaseAccessiblePrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(accessible, WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessiblePrivate); + accessible->priv = priv; + new (priv) WebKitWebViewBaseAccessiblePrivate(); +} + +static void webkit_web_view_base_accessible_class_init(WebKitWebViewBaseAccessibleClass* klass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(klass); + gObjectClass->finalize = webkitWebViewBaseAccessibleFinalize; + + // No need to implement get_n_children() and ref_child() here + // since this is a subclass of AtkSocket and all the logic related + // to those functions will be implemented by the ATK bridge. + AtkObjectClass* atkObjectClass = ATK_OBJECT_CLASS(klass); + atkObjectClass->initialize = webkitWebViewBaseAccessibleInitialize; + atkObjectClass->ref_state_set = webkitWebViewBaseAccessibleRefStateSet; + atkObjectClass->get_index_in_parent = webkitWebViewBaseAccessibleGetIndexInParent; + + g_type_class_add_private(klass, sizeof(WebKitWebViewBaseAccessiblePrivate)); +} + +WebKitWebViewBaseAccessible* webkitWebViewBaseAccessibleNew(GtkWidget* widget) +{ + AtkObject* object = ATK_OBJECT(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, NULL)); + atk_object_initialize(object, widget); + return WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(object); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.h new file mode 100644 index 000000000..3e932c3cd --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.h @@ -0,0 +1,55 @@ +/* + * 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 WebKitWebViewBaseAccessible_h +#define WebKitWebViewBaseAccessible_h + +#include <atk/atk.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE (webkit_web_view_base_accessible_get_type()) +#define WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessible)) +#define WEBKIT_WEB_VIEW_BASE_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessibleClass)) +#define WEBKIT_IS_WEB_VIEW_BASE_ACCESSIBLE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE)) +#define WEBKIT_IS_WEB_VIEW_BASE_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE)) +#define WEBKIT_WEB_VIEW_BASE_ACCESSIBLE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessibleClass)) + +typedef struct _WebKitWebViewBaseAccessible WebKitWebViewBaseAccessible; +typedef struct _WebKitWebViewBaseAccessibleClass WebKitWebViewBaseAccessibleClass; +typedef struct _WebKitWebViewBaseAccessiblePrivate WebKitWebViewBaseAccessiblePrivate; + + +struct _WebKitWebViewBaseAccessible { + AtkSocket parent; + /*< private >*/ + WebKitWebViewBaseAccessiblePrivate* priv; +}; + +struct _WebKitWebViewBaseAccessibleClass { + AtkSocketClass parentClass; +}; + +GType webkit_web_view_base_accessible_get_type(); + +WebKitWebViewBaseAccessible* webkitWebViewBaseAccessibleNew(GtkWidget*); + +G_END_DECLS + +#endif // WebKitWebViewBaseAccessible_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h index 5c8161afd..66386d028 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h @@ -42,5 +42,6 @@ void webkitWebViewClosePage(WebKitWebView*); void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message); bool webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message); WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText); +void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); #endif // WebKitWebViewPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp index c99f6d6e8..b170c82c9 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp @@ -24,10 +24,6 @@ #include "WebKitWindowPropertiesPrivate.h" #include "WebURLRequest.h" #include <WebCore/IntRect.h> -#include <WebKit2/WKDictionary.h> -#include <WebKit2/WKNumber.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKString.h> #include <glib/gi18n-lib.h> /** diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index c513959c2..c6f943ab2 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -20,6 +20,9 @@ <xi:include href="xml/WebKitURIRequest.xml"/> <xi:include href="xml/WebKitURIResponse.xml"/> <xi:include href="xml/WebKitWindowProperties.xml"/> + <xi:include href="xml/WebKitDownload.xml"/> + <xi:include href="xml/WebKitPolicyDecision.xml"/> + <xi:include href="xml/WebKitNavigationPolicyDecision.xml"/> <xi:include href="xml/WebKitError.xml"/> </chapter> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index 84468945d..ef44b2bed 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -27,6 +27,7 @@ WebKitCacheModel webkit_web_context_get_default webkit_web_context_get_cache_model webkit_web_context_set_cache_model +webkit_web_context_download_uri <SUBSECTION Standard> WebKitWebContextClass @@ -47,6 +48,7 @@ webkit_web_context_get_type <TITLE>WebKitWebView</TITLE> WebKitWebView WebKitLoadEvent +WebKitPolicyDecisionType webkit_web_view_new webkit_web_view_new_with_context webkit_web_view_get_context @@ -202,6 +204,8 @@ webkit_settings_get_enable_caret_browsing webkit_settings_set_enable_caret_browsing webkit_settings_get_enable_fullscreen webkit_settings_set_enable_fullscreen +webkit_settings_get_print_backgrounds +webkit_settings_set_print_backgrounds <SUBSECTION Standard> WebKitSettingsClass @@ -285,15 +289,87 @@ webkit_window_properties_get_type </SECTION> <SECTION> +<FILE>WebKitDownload</FILE> +WebKitDownload +webkit_download_get_destination +webkit_download_set_destination +webkit_download_get_response +webkit_download_cancel +webkit_download_get_estimated_progress +webkit_download_get_elapsed_time + +<SUBSECTION Standard> +WebKitDownloadClass +WEBKIT_TYPE_DOWNLOAD +WEBKIT_DOWNLOAD +WEBKIT_IS_DOWNLOAD +WEBKIT_DOWNLOAD_CLASS +WEBKIT_IS_DOWNLOAD_CLASS +WEBKIT_DOWNLOAD_GET_CLASS + +<SUBSECTION Private> +WebKitDownloadPrivate +webkit_download_get_type +</SECTION> + +<SECTION> +<FILE>WebKitPolicyDecision</FILE> +WebKitPolicyDecision +webkit_policy_decision_download +webkit_policy_decision_ignore +webkit_policy_decision_use + +<SUBSECTION Standard> +WebKitPolicyDecisionClass +WEBKIT_TYPE_POLICY_DECISION +WEBKIT_POLICY_DECISION +WEBKIT_IS_POLICY_DECISION +WEBKIT_POLICY_DECISION_CLASS +WEBKIT_IS_POLICY_DECISION_CLASS +WEBKIT_POLICY_DECISION_GET_CLASS + +<SUBSECTION Private> +WebKitPolicyDecisionPrivate +webkit_policy_decision_get_type +</SECTION> + +<SECTION> +<FILE>WebKitNavigationPolicyDecision</FILE> +WebKitNavigationPolicyDecision +WebKitNavigationType +webkit_navigation_policy_decision_get_frame_name +webkit_navigation_policy_decision_get_modifiers +webkit_navigation_policy_decision_get_mouse_button +webkit_navigation_policy_decision_get_navigation_type +webkit_navigation_policy_decision_get_request + +<SUBSECTION Standard> +WebKitNavigationPolicyDecisionClass +WEBKIT_TYPE_NAVIGATION_POLICY_DECISION +WEBKIT_NAVIGATION_POLICY_DECISION +WEBKIT_IS_NAVIGATION_POLICY_DECISION +WEBKIT_NAVIGATION_POLICY_DECISION_CLASS +WEBKIT_IS_NAVIGATION_POLICY_DECISION_CLASS +WEBKIT_NAVIGATION_POLICY_DECISION_GET_CLASS + +<SUBSECTION Private> +WebKitNavigationPolicyDecisionPrivate +webkit_navigation_policy_decision_get_type +</SECTION> + +<SECTION> <FILE>WebKitError</FILE> WEBKIT_NETWORK_ERROR WEBKIT_PLUGIN_ERROR WEBKIT_POLICY_ERROR +WEBKIT_DOWNLOAD_ERROR WebKitNetworkError WebKitPluginError WebKitPolicyError +WebKitDownloadError webkit_network_error_quark webkit_plugin_error_quark webkit_policy_error_quark +webkit_download_error_quark </SECTION> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types index 40a841c89..cba2df42c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types @@ -8,3 +8,5 @@ webkit_settings_get_type webkit_uri_response_get_type webkit_uri_request_get_type webkit_window_properties_get_type +webkit_download_get_type + diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp new file mode 100644 index 000000000..a8bbbc3fa --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp @@ -0,0 +1,58 @@ +/* + * 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 <gtk/gtk.h> +#include <webkit2/webkit2.h> + +static void loadChangedCallback(WebKitWebView*, WebKitLoadEvent loadEvent, gpointer) +{ + // Send a message to the parent process when we're ready. + if (loadEvent == WEBKIT_LOAD_FINISHED) + g_print("OK"); +} + +int main(int argc, char** argv) +{ + // Make sure that both GAIL and the ATK bridge are loaded. + g_setenv("GTK_MODULES", "gail:atk-bridge", TRUE); + + gtk_init(&argc, &argv); + + WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + webkit_web_view_load_html(webView, + "<html>" + " <body>" + " <h1>This is a test</h1>" + " <p>This is a paragraph with some plain text.</p>" + " <p>This paragraph contains <a href=\"http://www.webkitgtk.org\">a link</a> in the middle.</p>" + " </body>" + "</html>", + 0); + + GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(webView)); + gtk_widget_show_all(window); + + g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), 0); + g_signal_connect(webView, "load-changed", G_CALLBACK(loadChangedCallback), 0); + + gtk_main(); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index d912b657e..175a149e4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -1,13 +1,23 @@ TEST_PROGS += \ Programs/WebKit2APITests/TestWebKitWebContext \ Programs/WebKit2APITests/TestWebKitWebView \ - Programs/WebKit2APITests/TestWebKitWebLoaderClient \ + Programs/WebKit2APITests/TestLoaderClient \ Programs/WebKit2APITests/TestWebKitSettings \ - Programs/WebKit2APITests/TestBackForwardList + Programs/WebKit2APITests/TestBackForwardList \ + Programs/WebKit2APITests/TestDownloads \ + Programs/WebKit2APITests/TestWebKitPolicyClient noinst_PROGRAMS += $(TEST_PROGS) + +if HAVE_ATSPI2 +TEST_PROGS += Programs/WebKit2APITests/TestWebKitAccessibility + +noinst_PROGRAMS += Programs/WebKit2APITests/AccessibilityTestServer +endif + webkit2_tests_cppflags = \ -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs\" \ + -DWEBKIT_SRC_DIR=\"${shell pwd}/${srcdir}\" \ $(javascriptcore_cppflags) \ -I$(srcdir)/Source/JavaScriptCore \ -I$(srcdir)/Source \ @@ -58,11 +68,11 @@ Programs_WebKit2APITests_TestWebKitWebView_CPPFLAGS = $(webkit2_tests_cppflags) Programs_WebKit2APITests_TestWebKitWebView_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestWebKitWebView_LDFLAGS = $(webkit2_tests_ldflags) -Programs_WebKit2APITests_TestWebKitWebLoaderClient_SOURCES = \ - Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebLoaderClient.cpp -Programs_WebKit2APITests_TestWebKitWebLoaderClient_CPPFLAGS = $(webkit2_tests_cppflags) -Programs_WebKit2APITests_TestWebKitWebLoaderClient_LDADD = $(webkit2_tests_ldadd) -Programs_WebKit2APITests_TestWebKitWebLoaderClient_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestLoaderClient_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp +Programs_WebKit2APITests_TestLoaderClient_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestLoaderClient_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestLoaderClient_LDFLAGS = $(webkit2_tests_ldflags) Programs_WebKit2APITests_TestWebKitSettings_SOURCES = \ Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -76,3 +86,28 @@ Programs_WebKit2APITests_TestBackForwardList_CPPFLAGS = $(webkit2_tests_cppflags Programs_WebKit2APITests_TestBackForwardList_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestBackForwardList_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestWebKitPolicyClient_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp +Programs_WebKit2APITests_TestWebKitPolicyClient_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestWebKitPolicyClient_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestWebKitPolicyClient_LDFLAGS = $(webkit2_tests_ldflags) + +if HAVE_ATSPI2 +Programs_WebKit2APITests_AccessibilityTestServer_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp +Programs_WebKit2APITests_AccessibilityTestServer_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_AccessibilityTestServer_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_AccessibilityTestServer_LDFLAGS = $(webkit2_tests_ldflags) + +Programs_WebKit2APITests_TestWebKitAccessibility_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp +Programs_WebKit2APITests_TestWebKitAccessibility_CPPFLAGS = $(webkit2_tests_cppflags) $(ATSPI2_CFLAGS) +Programs_WebKit2APITests_TestWebKitAccessibility_LDADD = $(webkit2_tests_ldadd) $(ATSPI2_LIBS) +Programs_WebKit2APITests_TestWebKitAccessibility_LDFLAGS = $(webkit2_tests_ldflags) +endif + +Programs_WebKit2APITests_TestDownloads_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp +Programs_WebKit2APITests_TestDownloads_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestDownloads_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestDownloads_LDFLAGS = $(webkit2_tests_ldflags) diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp index 7581f2f6e..9eb08575d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp @@ -138,3 +138,37 @@ void LoadTrackingTest::estimatedProgressChanged() m_estimatedProgress = progress; } +void LoadTrackingTest::loadURI(const char* uri) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadURI(uri); +} + +void LoadTrackingTest::loadHtml(const char* html, const char* baseURI) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadHtml(html, baseURI); +} + +void LoadTrackingTest::loadPlainText(const char* plainText) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadPlainText(plainText); +} + +void LoadTrackingTest::loadRequest(WebKitURIRequest* request) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadRequest(request); +} + +void LoadTrackingTest::reload() +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + webkit_web_view_reload(m_webView); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h index 308aa9ce1..2d95c48f4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h @@ -39,6 +39,12 @@ public: virtual void loadFailed(const char* failingURI, GError*); virtual void estimatedProgressChanged(); + void loadURI(const char* uri); + void loadHtml(const char* html, const char* baseURI); + void loadPlainText(const char* plainText); + void loadRequest(WebKitURIRequest*); + void reload(); + void setRedirectURI(const char* uri) { m_redirectURI = uri; } enum LoadEvents { diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp index ac2a57235..cc657cc64 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp @@ -27,7 +27,7 @@ #include <webkit2/webkit2.h> // Back forward list limit is 100 by default. -static const size_t kBackForwardListLimit = 100; +static const int kBackForwardListLimit = 100; static WebKitTestServer* kServer; @@ -240,7 +240,7 @@ static void testBackForwardListNavigation(BackForwardListTest* test, gconstpoint static void testBackForwardListLimitAndCache(BackForwardListTest* test, gconstpointer) { - for (size_t i = 0; i < kBackForwardListLimit; i++) { + for (int i = 0; i < kBackForwardListLimit; i++) { GOwnPtr<char> path(g_strdup_printf("/Page%d", i)); test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem; test->loadURI(kServer->getURIForPath(path.get()).data()); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp new file mode 100644 index 000000000..461cefa0e --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp @@ -0,0 +1,410 @@ +/* + * 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. + */ + +#include "config.h" + +#include "TestMain.h" +#include "WebKitTestServer.h" +#include <glib/gstdio.h> +#include <gtk/gtk.h> +#include <libsoup/soup.h> +#include <string.h> +#include <webkit2/webkit2.h> +#include <wtf/Vector.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +static char* kTempDirectory; + +class DownloadTest: public Test { +public: + MAKE_GLIB_TEST_FIXTURE(DownloadTest); + + enum DownloadEvent { + Started, + ReceivedResponse, + CreatedDestination, + ReceivedData, + Failed, + Finished + }; + + static void receivedResponseCallback(WebKitDownload* download, GParamSpec*, DownloadTest* test) + { + g_assert(webkit_download_get_response(download)); + test->receivedResponse(download); + } + + static gboolean createdDestinationCallback(WebKitDownload* download, const gchar* destination, DownloadTest* test) + { + g_assert(webkit_download_get_destination(download)); + g_assert_cmpstr(webkit_download_get_destination(download), ==, destination); + test->createdDestination(download, destination); + return TRUE; + } + + static gboolean receivedDataCallback(WebKitDownload* download, guint64 dataLength, DownloadTest* test) + { + test->receivedData(download, dataLength); + return TRUE; + } + + static gboolean finishedCallback(WebKitDownload* download, DownloadTest* test) + { + test->finished(download); + return TRUE; + } + + static gboolean failedCallback(WebKitDownload* download, GError* error, DownloadTest* test) + { + g_assert(error); + test->failed(download, error); + return TRUE; + } + + static gboolean decideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, DownloadTest* test) + { + g_assert(suggestedFilename); + test->decideDestination(download, suggestedFilename); + return TRUE; + } + + static void downloadStartedCallback(WebKitWebContext* context, WebKitDownload* download, DownloadTest* test) + { + test->started(download); + g_signal_connect(download, "notify::response", G_CALLBACK(receivedResponseCallback), test); + g_signal_connect(download, "created-destination", G_CALLBACK(createdDestinationCallback), test); + g_signal_connect(download, "received-data", G_CALLBACK(receivedDataCallback), test); + g_signal_connect(download, "finished", G_CALLBACK(finishedCallback), test); + g_signal_connect(download, "failed", G_CALLBACK(failedCallback), test); + g_signal_connect(download, "decide-destination", G_CALLBACK(decideDestinationCallback), test); + } + + DownloadTest() + : m_webContext(webkit_web_context_get_default()) + , m_mainLoop(g_main_loop_new(0, TRUE)) + , m_downloadSize(0) + { + g_signal_connect(m_webContext, "download-started", G_CALLBACK(downloadStartedCallback), this); + } + + ~DownloadTest() + { + g_signal_handlers_disconnect_matched(m_webContext, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + g_main_loop_unref(m_mainLoop); + } + + virtual void started(WebKitDownload* download) + { + m_downloadEvents.append(Started); + } + + virtual void receivedResponse(WebKitDownload* download) + { + m_downloadEvents.append(ReceivedResponse); + } + + virtual void createdDestination(WebKitDownload* download, const char* destination) + { + m_downloadEvents.append(CreatedDestination); + } + + virtual void receivedData(WebKitDownload* download, guint64 dataLength) + { + m_downloadSize += dataLength; + if (!m_downloadEvents.contains(ReceivedData)) + m_downloadEvents.append(ReceivedData); + } + + virtual void finished(WebKitDownload* download) + { + m_downloadEvents.append(Finished); + g_main_loop_quit(m_mainLoop); + } + + virtual void failed(WebKitDownload* download, GError* error) + { + m_downloadEvents.append(Failed); + } + + virtual void decideDestination(WebKitDownload* download, const gchar* suggestedFilename) + { + GOwnPtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL)); + GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); + webkit_download_set_destination(download, destinationURI.get()); + } + + void waitUntilDownloadFinishes() + { + g_main_loop_run(m_mainLoop); + } + + void checkDestinationAndDeleteFile(WebKitDownload* download, const char* expectedName) + { + if (!webkit_download_get_destination(download)) + return; + GRefPtr<GFile> destFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(download))); + GOwnPtr<char> destBasename(g_file_get_basename(destFile.get())); + g_assert_cmpstr(destBasename.get(), ==, expectedName); + + g_file_delete(destFile.get(), 0, 0); + } + + WebKitWebContext* m_webContext; + GMainLoop* m_mainLoop; + Vector<DownloadEvent> m_downloadEvents; + guint64 m_downloadSize; +}; + +static CString getWebKit1TestResoucesDir() +{ + GOwnPtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Source", "WebKit", "gtk", "tests", "resources", NULL)); + return resourcesDir.get(); +} + +static void testDownloadLocalFile(DownloadTest* test, gconstpointer) +{ + GOwnPtr<char> sourcePath(g_build_filename(getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get())); + GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0)); + GOwnPtr<char> sourceURI(g_file_get_uri(source.get())); + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, sourceURI.get())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination); + g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData); + g_assert_cmpint(events[4], ==, DownloadTest::Finished); + + g_assert_cmpint(test->m_downloadSize, ==, g_file_info_get_size(sourceInfo.get())); + g_assert(webkit_download_get_destination(download.get())); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); + test->checkDestinationAndDeleteFile(download.get(), "test.pdf"); +} + +class DownloadErrorTest: public DownloadTest { +public: + MAKE_GLIB_TEST_FIXTURE(DownloadErrorTest); + + DownloadErrorTest() + : m_expectedError(WEBKIT_DOWNLOAD_ERROR_NETWORK) + { + } + + void receivedResponse(WebKitDownload* download) + { + DownloadTest::receivedResponse(download); + if (m_expectedError == WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER) + webkit_download_cancel(download); + } + + void createdDestination(WebKitDownload* download, const char* destination) + { + g_assert_not_reached(); + } + + void failed(WebKitDownload* download, GError* error) + { + g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, m_expectedError)); + DownloadTest::failed(download, error); + } + + void decideDestination(WebKitDownload* download, const gchar* suggestedFilename) + { + if (m_expectedError != WEBKIT_DOWNLOAD_ERROR_DESTINATION) { + DownloadTest::decideDestination(download, suggestedFilename); + return; + } + webkit_download_set_destination(download, "file:///foo/bar"); + } + + WebKitDownloadError m_expectedError; +}; + +static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) +{ + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK; + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, "file:///foo/bar")); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 3); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::Failed); + g_assert_cmpint(events[2], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; + GOwnPtr<char> path(g_build_filename(getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get())); + GOwnPtr<char> uri(g_file_get_uri(file.get())); + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), "bar"); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), "test.pdf"); +} + +static WebKitTestServer* kServer; +static const char* kServerSuggestedFilename = "webkit-downloaded-file"; + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + GOwnPtr<char> filePath(g_build_filename(getWebKit1TestResoucesDir().data(), path, NULL)); + char* contents; + gsize contentsLength; + if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) { + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); + soup_message_body_complete(message->response_body); + return; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + + GOwnPtr<char> contentDisposition(g_strdup_printf("filename=%s", kServerSuggestedFilename)); + soup_message_headers_append(message->response_headers, "Content-Disposition", contentDisposition.get()); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength); + + soup_message_body_complete(message->response_body); +} + +static void testDownloadRemoteFile(DownloadTest* test, gconstpointer) +{ + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination); + g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData); + g_assert_cmpint(events[4], ==, DownloadTest::Finished); + events.clear(); + + g_assert(webkit_download_get_destination(download.get())); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); + test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename); +} + +static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer) +{ + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK; + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, + kServer->getURIForPath("/foo").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + WebKitURIResponse* response = webkit_download_get_response(download.get()); + g_assert_cmpuint(webkit_uri_response_get_status_code(response), ==, 404); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), "bar"); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0); + g_assert(kTempDirectory); + + DownloadTest::add("Downloads", "local-file", testDownloadLocalFile); + DownloadErrorTest::add("Downloads", "local-file-error", testDownloadLocalFileError); + DownloadTest::add("Downloads", "remote-file", testDownloadRemoteFile); + DownloadErrorTest::add("Downloads", "remote-file-error", testDownloadRemoteFileError); +} + +void afterAll() +{ + delete kServer; + g_rmdir(kTempDirectory); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebLoaderClient.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp index aaa9ff873..3afa2b96f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp @@ -55,27 +55,26 @@ static void testLoadingError(LoadTrackingTest* test, gconstpointer) g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished); } -static void assertNormalLoadHappenedAndClearEvents(Vector<LoadTrackingTest::LoadEvents>& events) +static void assertNormalLoadHappened(Vector<LoadTrackingTest::LoadEvents>& events) { g_assert_cmpint(events.size(), ==, 3); g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted); g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished); - events.clear(); } static void testLoadHtml(LoadTrackingTest* test, gconstpointer) { test->loadHtml("<html><body>Hello WebKit-GTK+</body></html>", 0); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } static void testLoadPlainText(LoadTrackingTest* test, gconstpointer) { test->loadPlainText("Hello WebKit-GTK+"); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } static void testLoadRequest(LoadTrackingTest* test, gconstpointer) @@ -83,7 +82,7 @@ static void testLoadRequest(LoadTrackingTest* test, gconstpointer) GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal").data())); test->loadRequest(request.get()); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } class LoadStopTrackingTest : public LoadTrackingTest { @@ -126,16 +125,16 @@ static void testWebViewTitle(LoadTrackingTest* test, gconstpointer) static void testWebViewReload(LoadTrackingTest* test, gconstpointer) { // Check that nothing happens when there's nothing to reload. - webkit_web_view_reload(test->m_webView); + test->reload(); test->wait(0.25); // Wait for a quarter of a second. test->loadURI(kServer->getURIForPath("/normal").data()); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); - webkit_web_view_reload(test->m_webView); + test->reload(); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } static void testLoadProgress(LoadTrackingTest* test, gconstpointer) @@ -240,8 +239,8 @@ void beforeAll() kServer = new WebKitTestServer(); kServer->run(serverCallback); - LoadTrackingTest::add("WebKitWebLoaderClient", "loading-status", testLoadingStatus); - LoadTrackingTest::add("WebKitWebLoaderClient", "loading-error", testLoadingError); + LoadTrackingTest::add("WebKitWebView", "loading-status", testLoadingStatus); + LoadTrackingTest::add("WebKitWebView", "loading-error", testLoadingError); LoadTrackingTest::add("WebKitWebView", "load-html", testLoadHtml); LoadTrackingTest::add("WebKitWebView", "load-plain-text", testLoadPlainText); LoadTrackingTest::add("WebKitWebView", "load-request", testLoadRequest); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp new file mode 100644 index 000000000..3db9094a5 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp @@ -0,0 +1,230 @@ +/* + * 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 "TestMain.h" +#include "WebViewTest.h" + +// The libatspi headers don't use G_BEGIN_DECLS +extern "C" { +#include <atspi/atspi.h> +} + +#include <errno.h> +#include <fcntl.h> +#include <glib.h> +#include <signal.h> +#include <unistd.h> +#include <wtf/PassRefPtr.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> + +// Name of the test server application creating the webView object. +static const char* kTestServerAppName = "AccessibilityTestServer"; + +// Max seconds to wait for the test server before inspecting it. +static const int kMaxWaitForChild = 5; + +// The PID for the test server running, so we can kill it if needed. +static GPid kChildProcessPid = 0; + +// Whether the child has replied and it's ready. +static bool kChildIsReady = false; + +static void stopTestServer() +{ + // Do nothing if there's no server running. + if (!kChildProcessPid) + return; + + g_spawn_close_pid(kChildProcessPid); + kill(kChildProcessPid, SIGTERM); + kChildProcessPid = 0; +} + +static void sigAbortHandler(int sigNum) +{ + // Just stop the test server if SIGABRT was received. + stopTestServer(); +} + +static gpointer testServerMonitorThreadFunc(gpointer) +{ + // Wait for the specified timeout to happen. + g_usleep(kMaxWaitForChild * G_USEC_PER_SEC); + + // Kill the child process if not ready yet. + if (!kChildIsReady) + stopTestServer(); + + g_thread_exit(0); + return 0; +} + +static void startTestServerMonitor() +{ + kChildIsReady = false; + +#if (!GLIB_CHECK_VERSION(2, 31, 0)) + g_thread_create(testServerMonitorThreadFunc, 0, FALSE, 0); +#else + g_thread_new("TestServerMonitor", testServerMonitorThreadFunc, 0); +#endif +} + +static void startTestServer() +{ + // Prepare argv[] for spawning the server process. + GOwnPtr<char> testServerPath(g_build_filename(WEBKIT_EXEC_PATH, "WebKit2APITests", kTestServerAppName, NULL)); + + char* testServerArgv[2]; + testServerArgv[0] = testServerPath.get(); + testServerArgv[1] = 0; + + // Spawn the server, getting its stdout file descriptor to set a + // communication channel, so we know when it's ready. + int childStdout = 0; + if (!g_spawn_async_with_pipes(0, testServerArgv, 0, static_cast<GSpawnFlags>(0), 0, 0, + &kChildProcessPid, 0, &childStdout, 0, 0)) { + close(childStdout); + return; + } + + // Start monitoring the test server (in a separate thread) to + // ensure we don't block on the child process more than a timeout. + startTestServerMonitor(); + + char msg[2]; + GIOChannel* ioChannel = g_io_channel_unix_new(childStdout); + if (g_io_channel_read_chars(ioChannel, msg, 2, 0, 0) == G_IO_STATUS_NORMAL) { + // Check whether the server sent a message saying it's ready + // and store the result globally, so the monitor can see it. + kChildIsReady = msg[0] == 'O' && msg[1] == 'K'; + } + g_io_channel_unref(ioChannel); + close(childStdout); + + // The timeout was reached and the server is not ready yet, so + // stop it inmediately, and let the unit tests fail. + if (!kChildIsReady) + stopTestServer(); +} + +static void checkAtspiAccessible(AtspiAccessible* accessible, const char* targetName, AtspiRole targetRole) +{ + g_assert(ATSPI_IS_ACCESSIBLE(accessible)); + + GOwnPtr<char> name(atspi_accessible_get_name(accessible, 0)); + g_assert_cmpstr(targetName, ==, name.get()); + g_assert_cmpint(targetRole, ==, atspi_accessible_get_role(accessible, 0)); +} + +static GRefPtr<AtspiAccessible> findTestServerApplication() +{ + // Only one desktop is supported by ATSPI at the moment. + GRefPtr<AtspiAccessible> desktop = adoptGRef(atspi_get_desktop(0)); + + // Look for the server application in the list of apps. + GRefPtr<AtspiAccessible> current; + int childCount = atspi_accessible_get_child_count(desktop.get(), 0); + for (int i = 0; i < childCount; i++) { + current = adoptGRef(atspi_accessible_get_child_at_index(desktop.get(), i, 0)); + if (!g_strcmp0(atspi_accessible_get_name(current.get(), 0), kTestServerAppName)) + return current; + } + + return 0; +} + +static void testAtspiBasicHierarchy(WebViewTest* test, gconstpointer) +{ + // The test server's accessibility object (UI Process). + GRefPtr<AtspiAccessible> testServerApp = findTestServerApplication(); + g_assert(ATSPI_IS_ACCESSIBLE(testServerApp.get())); + checkAtspiAccessible(testServerApp.get(), "AccessibilityTestServer", ATSPI_ROLE_APPLICATION); + + // The main window's accessibility object (UI Process). + GRefPtr<AtspiAccessible> currentParent = testServerApp; + GRefPtr<AtspiAccessible> currentChild = adoptGRef(atspi_accessible_get_child_at_index(currentParent.get(), 0, 0)); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_FRAME); + + // The WebView's accessibility object (UI Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_FILLER); + + // The WebPage's accessibility object (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_FILLER); + + // HTML root element's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + + // HTML body's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_DOCUMENT_FRAME); + + // HTML H1's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "This is a test", ATSPI_ROLE_HEADING); + + // HTML first paragraph's accessible element (Web Process). + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 1, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_PARAGRAPH); + + // HTML second paragraph's accessible element (Web Process). + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 2, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_PARAGRAPH); + + // HTML link's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "a link", ATSPI_ROLE_LINK); +} + +void beforeAll() +{ + // We install a handler to ensure that we kill the child process + // if the parent dies because of whatever the reason is. + signal(SIGABRT, sigAbortHandler); + + // Start the accessibility test server and load the tests. + startTestServer(); + WebViewTest::add("WebKitAccessibility", "atspi-basic-hierarchy", testAtspiBasicHierarchy); +} + +void afterAll() +{ + // Ensure we stop the server. + stopTestServer(); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp new file mode 100644 index 000000000..7cbe4e7f9 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp @@ -0,0 +1,202 @@ +/* + * 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. + */ + +#include "config.h" + +#include "LoadTrackingTest.h" +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +class PolicyClientTest: public LoadTrackingTest { +public: + MAKE_GLIB_TEST_FIXTURE(PolicyClientTest); + + enum PolicyDecisionResponse { + Use, + Ignore, + Download, + None + }; + + PolicyClientTest() + : LoadTrackingTest() + , m_policyDecisionResponse(None) + , m_policyDecisionTypeFilter(0) + , m_respondToPolicyDecisionAsynchronously(false) + , m_haltMainLoopAfterMakingDecision(false) + { + g_signal_connect(m_webView, "decide-policy", G_CALLBACK(decidePolicyCallback), this); + } + + static gboolean quitMainLoopLater(GMainLoop* loop) + { + g_main_loop_quit(loop); + return FALSE; + } + + static void respondToPolicyDecision(PolicyClientTest* test, WebKitPolicyDecision* decision) + { + switch (test->m_policyDecisionResponse) { + case Use: + webkit_policy_decision_use(decision); + break; + case Ignore: + webkit_policy_decision_ignore(decision); + break; + case Download: + webkit_policy_decision_download(decision); + break; + case None: + break; + } + + if (test->m_haltMainLoopAfterMakingDecision) + g_idle_add(reinterpret_cast<GSourceFunc>(quitMainLoopLater), test->m_mainLoop); + } + + static gboolean respondToPolicyDecisionLater(PolicyClientTest* test) + { + respondToPolicyDecision(test, test->m_previousPolicyDecision.get()); + test->m_previousPolicyDecision = 0; + return FALSE; + } + + static gboolean decidePolicyCallback(WebKitWebView* webView, WebKitPolicyDecision* decision, WebKitPolicyDecisionType type, PolicyClientTest* test) + { + if (test->m_policyDecisionTypeFilter != type) + return FALSE; + + test->m_previousPolicyDecision = decision; + if (test->m_respondToPolicyDecisionAsynchronously) { + g_idle_add(reinterpret_cast<GSourceFunc>(respondToPolicyDecisionLater), test); + return TRUE; + } + + respondToPolicyDecision(test, decision); + + // We return FALSE here to ensure that the default policy decision + // handler doesn't override whatever we use here. + return FALSE; + } + + PolicyDecisionResponse m_policyDecisionResponse; + int m_policyDecisionTypeFilter; + bool m_respondToPolicyDecisionAsynchronously; + bool m_haltMainLoopAfterMakingDecision; + GRefPtr<WebKitPolicyDecision> m_previousPolicyDecision; +}; + +static void testNavigationPolicy(PolicyClientTest* test, gconstpointer) +{ + test->m_policyDecisionTypeFilter = WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION; + + test->m_policyDecisionResponse = PolicyClientTest::Use; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 3); + + // Ideally we'd like to have a more intensive test here, but it's still pretty tricky + // to trigger different types of navigations with the GTK+ WebKit2 API. + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(test->m_previousPolicyDecision.get()); + g_assert_cmpint(webkit_navigation_policy_decision_get_navigation_type(decision), ==, WEBKIT_NAVIGATION_TYPE_OTHER); + g_assert_cmpint(webkit_navigation_policy_decision_get_mouse_button(decision), ==, 0); + g_assert_cmpint(webkit_navigation_policy_decision_get_modifiers(decision), ==, 0); + g_assert_cmpstr(webkit_navigation_policy_decision_get_frame_name(decision), ==, 0); + WebKitURIRequest* request = webkit_navigation_policy_decision_get_request(decision); + g_assert_cmpstr(webkit_uri_request_get_uri(request), ==, "http://webkitgtk.org/"); + + test->m_policyDecisionResponse = PolicyClientTest::Use; + test->m_respondToPolicyDecisionAsynchronously = true; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 3); + + // If we are waiting until load completion, it will never complete if we ignore the + // navigation. So we tell the main loop to quit sometime later. + test->m_policyDecisionResponse = PolicyClientTest::Ignore; + test->m_respondToPolicyDecisionAsynchronously = false; + test->m_haltMainLoopAfterMakingDecision = true; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 0); + + test->m_policyDecisionResponse = PolicyClientTest::Ignore; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 0); +} + +struct CreateCallbackData { + bool triedToOpenWindow; + GMainLoop* mainLoop; +}; + +static WebKitWebView* createCallback(WebKitWebView* webView, CreateCallbackData* data) +{ + data->triedToOpenWindow = true; + g_main_loop_quit(data->mainLoop); + return 0; +} + +static void testNewWindowPolicy(PolicyClientTest* test, gconstpointer) +{ + static const char* windowOpeningHTML = + "<html><body>" + " <a id=\"link\" href=\"http://www.google.com\" target=\"_blank\">Link</a>" + " <script>" + " var event = document.createEvent('MouseEvents');" + " event.initEvent('click', true, false);" + " document.getElementById('link').dispatchEvent(event);" + " </script>" + "</body></html>"; + test->m_policyDecisionTypeFilter = WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION; + webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(test->m_webView), TRUE); + + CreateCallbackData data; + data.triedToOpenWindow = false; + data.mainLoop = test->m_mainLoop; + + g_signal_connect(test->m_webView, "create", G_CALLBACK(createCallback), &data); + test->m_policyDecisionResponse = PolicyClientTest::Use; + test->loadHtml(windowOpeningHTML, "http://webkitgtk.org/"); + test->wait(1); + g_assert(data.triedToOpenWindow); + + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(test->m_previousPolicyDecision.get()); + g_assert_cmpstr(webkit_navigation_policy_decision_get_frame_name(decision), ==, "_blank"); + + // Using a short timeout is a bit ugly here, but it's hard to get around because if we block + // the new window signal we cannot halt the main loop in the create callback. If we + // halt the main loop in the policy decision, the create callback never executes. + data.triedToOpenWindow = false; + test->m_policyDecisionResponse = PolicyClientTest::Ignore; + test->loadHtml(windowOpeningHTML, "http://webkitgtk.org/"); + test->wait(.2); + g_assert(!data.triedToOpenWindow); +} + +void beforeAll() +{ + PolicyClientTest::add("WebKitPolicyClient", "navigation-policy", testNavigationPolicy); + PolicyClientTest::add("WebKitPolicyClient", "new-window-policy", testNewWindowPolicy); +} + +void afterAll() +{ +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp index 93e9c9cd2..cce7e1fe7 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -184,6 +184,11 @@ static void testWebKitSettings(Test*, gconstpointer) webkit_settings_set_enable_fullscreen(settings, TRUE); g_assert(webkit_settings_get_enable_fullscreen(settings)); + // Print backgrounds is enabled by default + g_assert(webkit_settings_get_print_backgrounds(settings)); + webkit_settings_set_print_backgrounds(settings, FALSE); + g_assert(!webkit_settings_get_print_backgrounds(settings)); + g_object_unref(G_OBJECT(settings)); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp index dfd9da475..099eabda5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp @@ -48,7 +48,10 @@ void WebViewTest::loadURI(const char* uri) void WebViewTest::loadHtml(const char* html, const char* baseURI) { - m_activeURI = "about:blank"; + if (!baseURI) + m_activeURI = "about:blank"; + else + m_activeURI = baseURI; webkit_web_view_load_html(m_webView, html, baseURI); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h index 662354032..882e8b224 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h @@ -31,10 +31,10 @@ public: WebViewTest(); virtual ~WebViewTest(); - void loadURI(const char* uri); - void loadHtml(const char* html, const char* baseURI); - void loadPlainText(const char* plainText); - void loadRequest(WebKitURIRequest*); + virtual void loadURI(const char* uri); + virtual void loadHtml(const char* html, const char* baseURI); + virtual void loadPlainText(const char* plainText); + virtual void loadRequest(WebKitURIRequest*); void replaceContent(const char* html, const char* contentURI, const char* baseURI); void goBack(); void goForward(); diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index ab0e0a8f1..e9d892b54 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -26,6 +26,7 @@ #include <webkit2/WebKitBackForwardList.h> #include <webkit2/WebKitBackForwardListItem.h> #include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitDownload.h> #include <webkit2/WebKitEnumTypes.h> #include <webkit2/WebKitError.h> #include <webkit2/WebKitSettings.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list index 89c250e3e..5918d095a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list @@ -1,7 +1,13 @@ BOOLEAN:ENUM,STRING,POINTER +BOOLEAN:OBJECT +BOOLEAN:OBJECT,ENUM +BOOLEAN:OBJECT,STRING,POINTER +BOOLEAN:POINTER BOOLEAN:STRING BOOLEAN:STRING,POINTER BOOLEAN:STRING,STRING,POINTER +BOOLEAN:UINT64 +BOOLEAN:VOID OBJECT:VOID VOID:ENUM VOID:OBJECT,POINTER |