diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/API/gtk')
47 files changed, 4098 insertions, 121 deletions
diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp index 9fadbeab5..8fbfe73f6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp @@ -39,7 +39,9 @@ #include "WebPageProxy.h" #include "WebPopupMenuProxyGtk.h" #include <WebCore/Cursor.h> +#include <WebCore/EventNames.h> #include <WebCore/GtkUtilities.h> +#include <wtf/text/CString.h> #include <wtf/text/WTFString.h> using namespace WebCore; @@ -156,7 +158,7 @@ void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves) notImplemented(); } -void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportArguments&) +void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&) { notImplemented(); } diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h index 6a1cb2459..54ad99f8f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h @@ -69,7 +69,7 @@ private: virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void setCursor(const WebCore::Cursor&); virtual void setCursorHiddenUntilMouseMoves(bool); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp new file mode 100644 index 000000000..b993d2e83 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp @@ -0,0 +1,262 @@ +/* + * 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 "WebKitCookieManager.h" + +#include "WebKitCookieManagerPrivate.h" +#include "WebKitEnumTypes.h" +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + CHANGED, + + LAST_SIGNAL +}; + +struct _WebKitCookieManagerPrivate { + WKRetainPtr<WKCookieManagerRef> wkCookieManager; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitCookieManager, webkit_cookie_manager, G_TYPE_OBJECT) + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS, kWKHTTPCookieAcceptPolicyAlways); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_COOKIE_POLICY_ACCEPT_NEVER, kWKHTTPCookieAcceptPolicyNever); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY, kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain); + +static void webkit_cookie_manager_init(WebKitCookieManager* manager) +{ + WebKitCookieManagerPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(manager, WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManagerPrivate); + manager->priv = priv; + new (priv) WebKitCookieManagerPrivate(); +} + +static void webkitCookieManagerFinalize(GObject* object) +{ + WebKitCookieManagerPrivate* priv = WEBKIT_COOKIE_MANAGER(object)->priv; + WKCookieManagerStopObservingCookieChanges(priv->wkCookieManager.get()); + priv->~WebKitCookieManagerPrivate(); + G_OBJECT_CLASS(webkit_cookie_manager_parent_class)->finalize(object); +} + +static void webkit_cookie_manager_class_init(WebKitCookieManagerClass* findClass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass); + gObjectClass->finalize = webkitCookieManagerFinalize; + + g_type_class_add_private(findClass, sizeof(WebKitCookieManagerPrivate)); + + /** + * WebKitCookieManager::changed: + * @cookie_manager: the #WebKitCookieManager + * + * This signal is emitted when cookies are added, removed or modified. + */ + signals[CHANGED] = + g_signal_new("changed", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void cookiesDidChange(WKCookieManagerRef, const void* clientInfo) +{ + g_signal_emit(WEBKIT_COOKIE_MANAGER(clientInfo), signals[CHANGED], 0); +} + +WebKitCookieManager* webkitCookieManagerCreate(WKCookieManagerRef wkCookieManager) +{ + WebKitCookieManager* manager = WEBKIT_COOKIE_MANAGER(g_object_new(WEBKIT_TYPE_COOKIE_MANAGER, NULL)); + manager->priv->wkCookieManager = wkCookieManager; + + WKCookieManagerClient wkCookieManagerClient = { + kWKCookieManagerClientCurrentVersion, + manager, // clientInfo + cookiesDidChange + }; + WKCookieManagerSetClient(wkCookieManager, &wkCookieManagerClient); + WKCookieManagerStartObservingCookieChanges(wkCookieManager); + + return manager; +} + +/** + * webkit_cookie_manager_set_accept_policy: + * @cookie_manager: a #WebKitCookieManager + * @policy: a #WebKitCookieAcceptPolicy + * + * Set the cookie acceptance policy of @cookie_manager as @policy. + */ +void webkit_cookie_manager_set_accept_policy(WebKitCookieManager* manager, WebKitCookieAcceptPolicy policy) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + WKCookieManagerSetHTTPCookieAcceptPolicy(manager->priv->wkCookieManager.get(), policy); +} + +static void webkitCookieManagerGetAcceptPolicyCallback(WKHTTPCookieAcceptPolicy policy, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + g_simple_async_result_set_op_res_gpointer(result.get(), GUINT_TO_POINTER(policy), 0); + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_cookie_manager_get_accept_policy: + * @cookie_manager: a #WebKitCookieManager + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously get the cookie acceptance policy of @cookie_manager. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_cookie_manager_get_accept_policy_finish() to get the result of the operation. + */ +void webkit_cookie_manager_get_accept_policy(WebKitCookieManager* manager, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(manager), callback, userData, + reinterpret_cast<gpointer>(webkit_cookie_manager_get_accept_policy)); + WKCookieManagerGetHTTPCookieAcceptPolicy(manager->priv->wkCookieManager.get(), result, webkitCookieManagerGetAcceptPolicyCallback); +} + +/** + * webkit_cookie_manager_get_accept_policy_finish: + * @cookie_manager: a #WebKitCookieManager + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_cookie_manager_get_accept_policy(). + * + * Returns: the cookie acceptance policy of @cookie_manager as a #WebKitCookieAcceptPolicy. + */ +WebKitCookieAcceptPolicy webkit_cookie_manager_get_accept_policy_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_cookie_manager_get_accept_policy); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY; + + return static_cast<WebKitCookieAcceptPolicy>(GPOINTER_TO_UINT(g_simple_async_result_get_op_res_gpointer(simpleResult))); +} + +static void webkitCookieManagerGetDomainsWithCookiesCallback(WKArrayRef wkDomains, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + GPtrArray* domains = g_ptr_array_new_with_free_func(g_free); + for (size_t i = 0; i < WKArrayGetSize(wkDomains); ++i) { + WKStringRef wkDomain = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkDomains, i)); + String domain = toImpl(wkDomain)->string(); + if (domain.isEmpty()) + continue; + g_ptr_array_add(domains, g_strdup(domain.utf8().data())); + } + g_ptr_array_add(domains, 0); + g_simple_async_result_set_op_res_gpointer(result.get(), domains, reinterpret_cast<GDestroyNotify>(g_ptr_array_unref)); + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_cookie_manager_get_domains_with_cookies: + * @cookie_manager: a #WebKitCookieManager + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously get the list of domains for which @cookie_manager contains cookies. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_cookie_manager_get_domains_with_cookies_finish() to get the result of the operation. + */ +void webkit_cookie_manager_get_domains_with_cookies(WebKitCookieManager* manager, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(manager), callback, userData, + reinterpret_cast<gpointer>(webkit_cookie_manager_get_domains_with_cookies)); + WKCookieManagerGetHostnamesWithCookies(manager->priv->wkCookieManager.get(), result, webkitCookieManagerGetDomainsWithCookiesCallback); +} + +/** + * webkit_cookie_manager_get_domains_with_cookies_finish: + * @cookie_manager: a #WebKitCookieManager + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_cookie_manager_get_domains_with_cookies(). + * The return value is a %NULL terminated list of strings which should + * be released with g_strfreev(). + * + * Returns: (transfer full) (array zero-terminated=1): A %NULL terminated array of domain names + * or %NULL in case of error. + */ +gchar** webkit_cookie_manager_get_domains_with_cookies_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_cookie_manager_get_domains_with_cookies); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + GPtrArray* domains = static_cast<GPtrArray*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return reinterpret_cast<char**>(g_ptr_array_free(domains, FALSE)); +} + +/** + * webkit_cookie_manager_delete_cookies_for_domain: + * @cookie_manager: a #WebKitCookieManager + * @domain: a domain name + * + * Remove all cookies of @cookie_manager for the given @domain. + */ +void webkit_cookie_manager_delete_cookies_for_domain(WebKitCookieManager* manager, const gchar* domain) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + g_return_if_fail(domain); + + WKRetainPtr<WKStringRef> wkDomain(AdoptWK, WKStringCreateWithUTF8CString(domain)); + WKCookieManagerDeleteCookiesForHostname(manager->priv->wkCookieManager.get(), wkDomain.get()); +} + +/** + * webkit_cookie_manager_delete_all_cookies: + * @cookie_manager: a #WebKitCookieManager + * + * Delete all cookies of @cookie_manager + */ +void webkit_cookie_manager_delete_all_cookies(WebKitCookieManager* manager) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + WKCookieManagerDeleteAllCookies(manager->priv->wkCookieManager.get()); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h new file mode 100644 index 000000000..791a61d82 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitCookieManager_h +#define WebKitCookieManager_h + +#include <gio/gio.h> +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_COOKIE_MANAGER (webkit_cookie_manager_get_type()) +#define WEBKIT_COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManager)) +#define WEBKIT_IS_COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_COOKIE_MANAGER)) +#define WEBKIT_COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManagerClass)) +#define WEBKIT_IS_COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_COOKIE_MANAGER)) +#define WEBKIT_COOKIE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManagerClass)) + +typedef struct _WebKitCookieManager WebKitCookieManager; +typedef struct _WebKitCookieManagerClass WebKitCookieManagerClass; +typedef struct _WebKitCookieManagerPrivate WebKitCookieManagerPrivate; + +/** + * WebKitCookieAcceptPolicy: + * @WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS: Accept all cookies unconditionally. + * @WEBKIT_COOKIE_POLICY_ACCEPT_NEVER: Reject all cookies unconditionally. + * @WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY: Accept only cookies set by the main document loaded. + * + * Enum values used to denote the cookie acceptance policies. + */ +typedef enum { + WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS, + WEBKIT_COOKIE_POLICY_ACCEPT_NEVER, + WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY +} WebKitCookieAcceptPolicy; + +struct _WebKitCookieManager { + GObject parent; + + WebKitCookieManagerPrivate *priv; +}; + +struct _WebKitCookieManagerClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_cookie_manager_get_type (void); + +WEBKIT_API void +webkit_cookie_manager_set_accept_policy (WebKitCookieManager *cookie_manager, + WebKitCookieAcceptPolicy policy); + +WEBKIT_API void +webkit_cookie_manager_get_accept_policy (WebKitCookieManager *cookie_manager, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API WebKitCookieAcceptPolicy +webkit_cookie_manager_get_accept_policy_finish (WebKitCookieManager *cookie_manager, + GAsyncResult *result, + GError **error); + +WEBKIT_API void +webkit_cookie_manager_get_domains_with_cookies (WebKitCookieManager *cookie_manager, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API gchar ** +webkit_cookie_manager_get_domains_with_cookies_finish (WebKitCookieManager *cookie_manager, + GAsyncResult *result, + GError **error); + +WEBKIT_API void +webkit_cookie_manager_delete_cookies_for_domain (WebKitCookieManager *cookie_manager, + const gchar *domain); + +WEBKIT_API void +webkit_cookie_manager_delete_all_cookies (WebKitCookieManager *cookie_manager); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManagerPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManagerPrivate.h new file mode 100644 index 000000000..a387af907 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManagerPrivate.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 WebKitCookieManagerPrivate_h +#define WebKitCookieManagerPrivate_h + +#include "WebKitCookieManager.h" +#include "WebKitPrivate.h" + +WebKitCookieManager* webkitCookieManagerCreate(WKCookieManagerRef); + +#endif // WebKitCookieManagerPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp index 42cf0ab35..daf09ecc2 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp @@ -68,3 +68,17 @@ GQuark webkit_download_error_quark() 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); + +GQuark webkit_print_error_quark() +{ + return g_quark_from_static_string(WebCore::errorDomainPrint); +} + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_GENERAL, PrintErrorGeneral); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND, PrintErrorPrinterNotFound); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE, PrintErrorInvalidPageRange); + +GQuark webkit_javascript_error_quark() +{ + return g_quark_from_static_string("WebKitJavascriptError"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h index 9b0e630c8..c20581683 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h @@ -29,10 +29,12 @@ 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 () +#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 () +#define WEBKIT_PRINT_ERROR webkit_print_error_quark () +#define WEBKIT_JAVASCRIPT_ERROR webkit_print_error_quark () /** * WebKitNetworkError: @@ -104,17 +106,47 @@ typedef enum { WEBKIT_DOWNLOAD_ERROR_DESTINATION = 401 } WebKitDownloadError; +/** + * WebKitPrintError: + * @WEBKIT_PRINT_ERROR_GENERAL: Unspecified error during a print operation + * @WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND: Selected printer cannot be found + * @WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE: Invalid page range + * + * Enum values used to denote the various print errors. + */ +typedef enum { + WEBKIT_PRINT_ERROR_GENERAL = 599, + WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND = 500, + WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE = 501 +} WebKitPrintError; + +/** + * WebKitJavascriptError: + * @WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED: An exception was raised in Javascript execution + * + * Enum values used to denote errors happending when executing Javascript + */ +typedef enum { + WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED = 699 +} WebKitJavascriptError; + +WEBKIT_API GQuark +webkit_network_error_quark (void); + +WEBKIT_API GQuark +webkit_policy_error_quark (void); + WEBKIT_API GQuark -webkit_network_error_quark (void); +webkit_plugin_error_quark (void); WEBKIT_API GQuark -webkit_policy_error_quark (void); +webkit_download_error_quark (void); WEBKIT_API GQuark -webkit_plugin_error_quark (void); +webkit_print_error_quark (void); WEBKIT_API GQuark -webkit_download_error_quark (void); +webkit_javascript_error_quark (void); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.cpp new file mode 100644 index 000000000..96b87a3ba --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.cpp @@ -0,0 +1,385 @@ +/* + * 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 "WebKitFileChooserRequest.h" + +#include "WebKitFileChooserRequestPrivate.h" +#include "WebOpenPanelParameters.h" +#include <WebCore/FileSystem.h> +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebCore; +using namespace WebKit; + +/** + * SECTION: WebKitFileChooserRequest + * @Short_description: A request to open a file chooser + * @Title: WebKitFileChooserRequest + * @See_also: #WebKitWebView + * + * Whenever the user interacts with an <input type='file' /> + * HTML element, WebKit will need to show a dialog to choose one or + * more files to be uploaded to the server along with the rest of the + * form data. For that to happen in a general way, instead of just + * opening a #GtkFileChooserDialog (which might be not desirable in + * some cases, which could prefer to use their own file chooser + * dialog), WebKit will fire the #WebKitWebView::run-file-chooser + * signal with a #WebKitFileChooserRequest object, which will allow + * the client application to specify the files to be selected, to + * inspect the details of the request (e.g. if multiple selection + * should be allowed) and to cancel the request, in case nothing was + * selected. + * + * In case the client application does not wish to handle this signal, + * WebKit will provide a default handler which will asynchronously run + * a regular #GtkFileChooserDialog for the user to interact with. + */ +G_DEFINE_TYPE(WebKitFileChooserRequest, webkit_file_chooser_request, G_TYPE_OBJECT) + +struct _WebKitFileChooserRequestPrivate { + WKRetainPtr<WKOpenPanelParametersRef> wkParameters; + WKRetainPtr<WKOpenPanelResultListenerRef> wkListener; + GRefPtr<GtkFileFilter> filter; + GRefPtr<GPtrArray> mimeTypes; + GRefPtr<GPtrArray> selectedFiles; + bool handledRequest; +}; + +enum { + PROP_0, + PROP_FILTER, + PROP_MIME_TYPES, + PROP_SELECT_MULTIPLE, + PROP_SELECTED_FILES, +}; + +static void webkit_file_chooser_request_init(WebKitFileChooserRequest* request) +{ + request->priv = G_TYPE_INSTANCE_GET_PRIVATE(request, WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestPrivate); + new (request->priv) WebKitFileChooserRequestPrivate(); +} + +static void webkitFileChooserRequestFinalize(GObject* object) +{ + WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(object); + + // Make sure the request is always handled before finalizing. + if (!request->priv->handledRequest) + webkit_file_chooser_request_cancel(request); + + request->priv->~WebKitFileChooserRequestPrivate(); + G_OBJECT_CLASS(webkit_file_chooser_request_parent_class)->finalize(object); +} + +static void webkitFileChooserRequestGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(object); + switch (propId) { + case PROP_FILTER: + g_value_set_object(value, webkit_file_chooser_request_get_mime_types_filter(request)); + break; + case PROP_MIME_TYPES: + g_value_set_boxed(value, webkit_file_chooser_request_get_mime_types(request)); + break; + case PROP_SELECT_MULTIPLE: + g_value_set_boolean(value, webkit_file_chooser_request_get_select_multiple(request)); + break; + case PROP_SELECTED_FILES: + g_value_set_boxed(value, webkit_file_chooser_request_get_selected_files(request)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + break; + } +} + +static void webkit_file_chooser_request_class_init(WebKitFileChooserRequestClass* requestClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(requestClass); + objectClass->finalize = webkitFileChooserRequestFinalize; + objectClass->get_property = webkitFileChooserRequestGetProperty; + g_type_class_add_private(requestClass, sizeof(WebKitFileChooserRequestPrivate)); + + /** + * WebKitFileChooserRequest:filter: + * + * The filter currently associated with the request. See + * webkit_file_chooser_request_get_mime_types_filter() for more + * details. + */ + g_object_class_install_property(objectClass, + PROP_FILTER, + g_param_spec_object("filter", + _("MIME types filter"), + _("The filter currently associated with the request"), + GTK_TYPE_FILE_FILTER, + WEBKIT_PARAM_READABLE)); + /** + * WebKitFileChooserRequest:mime-types: + * + * A %NULL-terminated array of strings containing the list of MIME + * types the file chooser dialog should handle. See + * webkit_file_chooser_request_get_mime_types() for more details. + */ + g_object_class_install_property(objectClass, + PROP_MIME_TYPES, + g_param_spec_boxed("mime-types", + _("MIME types"), + _("The list of MIME types associated with the request"), + G_TYPE_STRV, + WEBKIT_PARAM_READABLE)); + /** + * WebKitFileChooserRequest:select-multiple: + * + * Whether the file chooser should allow selecting multiple + * files. See + * webkit_file_chooser_request_get_select_multiple() for + * more details. + */ + g_object_class_install_property(objectClass, + PROP_SELECT_MULTIPLE, + g_param_spec_boolean("select-multiple", + _("Select multiple files"), + _("Whether the file chooser should allow selecting multiple files"), + FALSE, + WEBKIT_PARAM_READABLE)); + /** + * WebKitFileChooserRequest:selected-files: + * + * A %NULL-terminated array of strings containing the list of + * selected files associated to the current request. See + * webkit_file_chooser_request_get_selected_files() for more details. + */ + g_object_class_install_property(objectClass, + PROP_SELECTED_FILES, + g_param_spec_boxed("selected-files", + _("Selected files"), + _("The list of selected files associated with the request"), + G_TYPE_STRV, + WEBKIT_PARAM_READABLE)); +} + +WebKitFileChooserRequest* webkitFileChooserRequestCreate(WKOpenPanelParametersRef wkParameters, WKOpenPanelResultListenerRef wkListener) +{ + WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(g_object_new(WEBKIT_TYPE_FILE_CHOOSER_REQUEST, NULL)); + request->priv->wkParameters = wkParameters; + request->priv->wkListener = wkListener; + return request; +} + +/** + * webkit_file_chooser_request_get_mime_types: + * @request: a #WebKitFileChooserRequest + * + * Get the list of MIME types the file chooser dialog should handle, + * in the format specified in RFC 2046 for "media types". Its contents + * depend on the value of the 'accept' attribute for HTML input + * elements. This function should normally be called before presenting + * the file chooser dialog to the user, to decide whether to allow the + * user to select multiple files at once or only one. + * + * Returns: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings if a list of accepted MIME types + * is defined or %NULL otherwise, meaning that any MIME type should be + * accepted. This array and its contents are owned by WebKitGTK+ and + * should not be modified or freed. + */ +const gchar* const* webkit_file_chooser_request_get_mime_types(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), 0); + if (request->priv->mimeTypes) + return reinterpret_cast<gchar**>(request->priv->mimeTypes->pdata); + + WKRetainPtr<WKArrayRef> wkMimeTypes(AdoptWK, WKOpenPanelParametersCopyAcceptedMIMETypes(request->priv->wkParameters.get())); + size_t numOfMimeTypes = WKArrayGetSize(wkMimeTypes.get()); + if (!numOfMimeTypes) + return 0; + + request->priv->mimeTypes = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + for (size_t i = 0; i < numOfMimeTypes; ++i) { + WKStringRef wkMimeType = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkMimeTypes.get(), i)); + String mimeTypeString = toImpl(wkMimeType)->string(); + if (mimeTypeString.isEmpty()) + continue; + g_ptr_array_add(request->priv->mimeTypes.get(), g_strdup(mimeTypeString.utf8().data())); + } + g_ptr_array_add(request->priv->mimeTypes.get(), 0); + + return reinterpret_cast<gchar**>(request->priv->mimeTypes->pdata); +} + +/** + * webkit_file_chooser_request_get_mime_types_filter: + * @request: a #WebKitFileChooserRequest + * + * Get the filter currently associated with the request, ready to be + * used by #GtkFileChooser. This function should normally be called + * before presenting the file chooser dialog to the user, to decide + * whether to apply a filter so the user would not be allowed to + * select files with other MIME types. + * + * See webkit_file_chooser_request_get_mime_types() if you are + * interested in getting the list of accepted MIME types. + * + * Returns: (transfer none): a #GtkFileFilter if a list of accepted + * MIME types is defined or %NULL otherwise. The returned object is + * owned by WebKitGTK+ should not be modified or freed. + */ +GtkFileFilter* webkit_file_chooser_request_get_mime_types_filter(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), 0); + if (request->priv->filter) + return request->priv->filter.get(); + + WKRetainPtr<WKArrayRef> wkMimeTypes(AdoptWK, WKOpenPanelParametersCopyAcceptedMIMETypes(request->priv->wkParameters.get())); + size_t numOfMimeTypes = WKArrayGetSize(wkMimeTypes.get()); + if (!numOfMimeTypes) + return 0; + + // Do not use adoptGRef here, since we want to sink the floating + // reference for the new instance of GtkFileFilter, so we make + // sure we keep the ownership during the lifetime of the request. + request->priv->filter = gtk_file_filter_new(); + for (size_t i = 0; i < numOfMimeTypes; ++i) { + WKStringRef wkMimeType = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkMimeTypes.get(), i)); + String mimeTypeString = toImpl(wkMimeType)->string(); + if (mimeTypeString.isEmpty()) + continue; + gtk_file_filter_add_mime_type(request->priv->filter.get(), mimeTypeString.utf8().data()); + } + + return request->priv->filter.get(); +} + +/** + * webkit_file_chooser_request_get_select_multiple: + * @request: a #WebKitFileChooserRequest + * + * Determine whether the file chooser associated to this + * #WebKitFileChooserRequest should allow selecting multiple files, + * which depends on the HTML input element having a 'multiple' + * attribute defined. + * + * Returns: %TRUE if the file chooser should allow selecting multiple files or %FALSE otherwise. + */ +gboolean webkit_file_chooser_request_get_select_multiple(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), FALSE); + return WKOpenPanelParametersGetAllowsMultipleFiles(request->priv->wkParameters.get()); +} + +/** + * webkit_file_chooser_request_select_files: + * @request: a #WebKitFileChooserRequest + * @files: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings, containing paths to local files. + * + * Ask WebKit to select local files for upload and complete the + * request. + */ +void webkit_file_chooser_request_select_files(WebKitFileChooserRequest* request, const gchar* const* files) +{ + g_return_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request)); + g_return_if_fail(files); + + GRefPtr<GPtrArray> selectedFiles = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + WKRetainPtr<WKMutableArrayRef> wkChosenFiles(AdoptWK, WKMutableArrayCreate()); + for (int i = 0; files[i]; i++) { + GRefPtr<GFile> filename = adoptGRef(g_file_new_for_path(files[i])); + + // Make sure the file path is presented as an URI (escaped + // string, with the 'file://' prefix) to WebCore otherwise the + // FileChooser won't actually choose it. + GOwnPtr<char> uri(g_file_get_uri(filename.get())); + WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(uri.get())); + WKArrayAppendItem(wkChosenFiles.get(), wkURL.get()); + + // Do not use the URI here because this won't reach WebCore. + g_ptr_array_add(selectedFiles.get(), g_strdup(files[i])); + } + g_ptr_array_add(selectedFiles.get(), 0); + + // Select the files in WebCore and update local private attributes. + WKOpenPanelResultListenerChooseFiles(request->priv->wkListener.get(), wkChosenFiles.get()); + request->priv->selectedFiles = selectedFiles; + request->priv->handledRequest = true; +} + +/** + * webkit_file_chooser_request_get_selected_files: + * @request: a #WebKitFileChooserRequest + * + * Get the list of selected files currently associated to the + * request. Initially, the return value of this method contains any + * files selected in previous file chooser requests for this HTML + * input element. Once webkit_file_chooser_request_select_files, the + * value will reflect whatever files are given. + * + * This function should normally be called only before presenting the + * file chooser dialog to the user, to decide whether to perform some + * extra action, like pre-selecting the files from a previous request. + * + * Returns: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings if there are selected files + * associated with the request or %NULL otherwise. This array and its + * contents are owned by WebKitGTK+ and should not be modified or + * freed. + */ +const gchar* const* webkit_file_chooser_request_get_selected_files(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), 0); + if (request->priv->selectedFiles) + return reinterpret_cast<gchar**>(request->priv->selectedFiles->pdata); + + const Vector<String> selectedFileNames = toImpl(request->priv->wkParameters.get())->selectedFileNames(); + size_t numOfFiles = selectedFileNames.size(); + if (!numOfFiles) + return 0; + + request->priv->selectedFiles = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + for (size_t i = 0; i < numOfFiles; ++i) { + if (selectedFileNames[i].isEmpty()) + continue; + CString filename = fileSystemRepresentation(selectedFileNames[i]); + g_ptr_array_add(request->priv->selectedFiles.get(), g_strdup(filename.data())); + } + g_ptr_array_add(request->priv->selectedFiles.get(), 0); + + return reinterpret_cast<gchar**>(request->priv->selectedFiles->pdata); +} + +/** + * webkit_file_chooser_request_cancel: + * @request: a #WebKitFileChooserRequest + * + * Ask WebKit to cancel the request. It's important to do this in case + * no selection has been made in the client, otherwise the request + * won't be properly completed and the browser will keep the request + * pending forever, which might cause the browser to hang. + */ +void webkit_file_chooser_request_cancel(WebKitFileChooserRequest* request) +{ + g_return_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request)); + WKOpenPanelResultListenerCancel(request->priv->wkListener.get()); + request->priv->handledRequest = true; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.h new file mode 100644 index 000000000..88eec9966 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.h @@ -0,0 +1,78 @@ +/* + * 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 WebKitFileChooserRequest_h +#define WebKitFileChooserRequest_h + +#include <gtk/gtk.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_FILE_CHOOSER_REQUEST (webkit_file_chooser_request_get_type()) +#define WEBKIT_FILE_CHOOSER_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequest)) +#define WEBKIT_FILE_CHOOSER_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestClass)) +#define WEBKIT_IS_FILE_CHOOSER_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST)) +#define WEBKIT_IS_FILE_CHOOSER_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_FILE_CHOOSER_REQUEST)) +#define WEBKIT_FILE_CHOOSER_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestClass)) + +typedef struct _WebKitFileChooserRequest WebKitFileChooserRequest; +typedef struct _WebKitFileChooserRequestClass WebKitFileChooserRequestClass; +typedef struct _WebKitFileChooserRequestPrivate WebKitFileChooserRequestPrivate; + +struct _WebKitFileChooserRequest { + GObject parent; + + /*< private >*/ + WebKitFileChooserRequestPrivate *priv; +}; + +struct _WebKitFileChooserRequestClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_file_chooser_request_get_type (void); + +WEBKIT_API const gchar * const * +webkit_file_chooser_request_get_mime_types (WebKitFileChooserRequest *request); + +WEBKIT_API GtkFileFilter * +webkit_file_chooser_request_get_mime_types_filter (WebKitFileChooserRequest *request); + +WEBKIT_API gboolean +webkit_file_chooser_request_get_select_multiple (WebKitFileChooserRequest *request); + +WEBKIT_API void +webkit_file_chooser_request_select_files (WebKitFileChooserRequest *request, + const gchar * const *files); + +WEBKIT_API const gchar * const * +webkit_file_chooser_request_get_selected_files (WebKitFileChooserRequest *request); + +WEBKIT_API void +webkit_file_chooser_request_cancel (WebKitFileChooserRequest *request); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequestPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequestPrivate.h new file mode 100644 index 000000000..af7224a96 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequestPrivate.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 WebKitFileChooserRequestPrivate_h +#define WebKitFileChooserRequestPrivate_h + +#include "WebKitFileChooserRequest.h" +#include "WebKitPrivate.h" + +WebKitFileChooserRequest* webkitFileChooserRequestCreate(WKOpenPanelParametersRef, WKOpenPanelResultListenerRef); + +#endif // WebKitFileChooserRequestPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.cpp new file mode 100644 index 000000000..75b51e25d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.cpp @@ -0,0 +1,48 @@ +/* + * 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 "WebKitFullscreenClient.h" + +#include "WebKitPrivate.h" +#include "WebKitWebViewPrivate.h" + +using namespace WebKit; + +static bool willEnterFullScreen(const void* clientInfo) +{ + return webkitWebViewEnterFullScreen(WEBKIT_WEB_VIEW(clientInfo)); +} + +static bool willExitFullScreen(const void* clientInfo) +{ + return webkitWebViewLeaveFullScreen(WEBKIT_WEB_VIEW(clientInfo)); +} + +void attachFullScreenClientToView(WebKitWebView* webView) +{ + WKFullScreenClientGtk wkFullScreenClient = { + kWKFullScreenClientGtkCurrentVersion, + webView, // clientInfo + willEnterFullScreen, + willExitFullScreen + }; + WKViewSetFullScreenClientGtk(toAPI(WEBKIT_WEB_VIEW_BASE(webView)), &wkFullScreenClient); +} + diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.h new file mode 100644 index 000000000..187c067af --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.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 WebKitFullscreenClient_h +#define WebKitFullscreenClient_h + +#include "WebKitWebView.h" + +void attachFullScreenClientToView(WebKitWebView*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp new file mode 100644 index 000000000..84ad04d03 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp @@ -0,0 +1,107 @@ +/* + * 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 "WebKitJavascriptResult.h" + +#include "WebKitJavascriptResultPrivate.h" +#include <wtf/gobject/GRefPtr.h> + +struct _WebKitJavascriptResult { + _WebKitJavascriptResult(WebKitWebView* view, WKSerializedScriptValueRef wkSerializedScriptValue) + : webView(view) + , referenceCount(1) + { + value = WKSerializedScriptValueDeserialize(wkSerializedScriptValue, webkit_web_view_get_javascript_global_context(view), 0); + } + + GRefPtr<WebKitWebView> webView; + JSValueRef value; + + int referenceCount; +}; + +G_DEFINE_BOXED_TYPE(WebKitJavascriptResult, webkit_javascript_result, webkit_javascript_result_ref, webkit_javascript_result_unref) + +WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView* webView, WKSerializedScriptValueRef wkSerializedScriptValue) +{ + WebKitJavascriptResult* result = g_slice_new(WebKitJavascriptResult); + new (result) WebKitJavascriptResult(webView, wkSerializedScriptValue); + return result; +} + +/** + * webkit_javascript_result_ref: + * @js_result: a #WebKitJavascriptResult + * + * Atomically increments the reference count of @js_result by one. This + * function is MT-safe and may be called from any thread. + * + * Returns: The passed in #WebKitJavascriptResult + */ +WebKitJavascriptResult* webkit_javascript_result_ref(WebKitJavascriptResult* javascriptResult) +{ + g_atomic_int_inc(&javascriptResult->referenceCount); + return javascriptResult; +} + +/** + * webkit_javascript_result_unref: + * @js_result: a #WebKitJavascriptResult + * + * Atomically decrements the reference count of @js_result by one. If the + * reference count drops to 0, all memory allocated by the #WebKitJavascriptResult is + * released. This function is MT-safe and may be called from any + * thread. + */ +void webkit_javascript_result_unref(WebKitJavascriptResult* javascriptResult) +{ + if (g_atomic_int_dec_and_test(&javascriptResult->referenceCount)) { + javascriptResult->~WebKitJavascriptResult(); + g_slice_free(WebKitJavascriptResult, javascriptResult); + } +} + +/** + * webkit_javascript_result_get_global_context: + * @js_result: a #WebKitJavascriptResult + * + * Get the global Javascript context that should be used with the + * <function>JSValueRef</function> returned by webkit_javascript_result_get_value(). + * + * Returns: the <function>JSGlobalContextRef</function> for the #WebKitJavascriptResult + */ +JSGlobalContextRef webkit_javascript_result_get_global_context(WebKitJavascriptResult* javascriptResult) +{ + return webkit_web_view_get_javascript_global_context(javascriptResult->webView.get()); +} + +/** + * webkit_javascript_result_get_value: + * @js_result: a #WebKitJavascriptResult + * + * Get the value of @js_result. You should use the <function>JSGlobalContextRef</function> + * returned by webkit_javascript_result_get_global_context() to use the <function>JSValueRef</function>. + * + * Returns: the <function>JSValueRef</function> of the #WebKitJavascriptResult + */ +JSValueRef webkit_javascript_result_get_value(WebKitJavascriptResult* javascriptResult) +{ + return javascriptResult->value; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h new file mode 100644 index 000000000..5a9f7389f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.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. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitJavascriptResult_h +#define WebKitJavascriptResult_h + +#include <JavaScriptCore/JSBase.h> +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_JAVASCRIPT_RESULT (webkit_javascript_result_get_type()) + +typedef struct _WebKitJavascriptResult WebKitJavascriptResult; + + +WEBKIT_API GType +webkit_javascript_result_get_type (void); + +WEBKIT_API WebKitJavascriptResult * +webkit_javascript_result_ref (WebKitJavascriptResult *js_result); + +WEBKIT_API void +webkit_javascript_result_unref (WebKitJavascriptResult *js_result); + +WEBKIT_API JSGlobalContextRef +webkit_javascript_result_get_global_context (WebKitJavascriptResult *js_result); + +WEBKIT_API JSValueRef +webkit_javascript_result_get_value (WebKitJavascriptResult *js_result); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h new file mode 100644 index 000000000..840ead058 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h @@ -0,0 +1,29 @@ +/* + * 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 WebKitJavascriptResultPrivate_h +#define WebKitJavascriptResultPrivate_h + +#include "WebKitJavascriptResult.h" +#include "WebKitPrivate.h" +#include "WebKitWebView.h" + +WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView*, WKSerializedScriptValueRef); + +#endif // WebKitJavascriptResultPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp index d79d40149..7da0b197a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp @@ -28,7 +28,9 @@ #include <WebCore/GtkUtilities.h> #include <WebCore/NotImplemented.h> #include <glib/gi18n-lib.h> +#include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> #ifdef HAVE_GTK_UNIX_PRINTING #include <gtk/gtkunixprint.h> @@ -46,6 +48,7 @@ enum { enum { FINISHED, + FAILED, LAST_SIGNAL }; @@ -193,6 +196,24 @@ static void webkit_print_operation_class_init(WebKitPrintOperationClass* printOp g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * WebKitPrintOperation::failed: + * @print_operation: the #WebKitPrintOperation on which the signal was emitted + * @error: the #GError that was triggered + * + * Emitted when an error occurs while printing. The given @error, of the domain + * %WEBKIT_PRINT_ERROR, contains further details of the failure. + * The #WebKitPrintOperation::finished signal is emitted after this one. + */ + signals[FAILED] = + g_signal_new("failed", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + g_type_class_add_private(printOperationClass, sizeof(WebKitPrintOperationPrivate)); } @@ -237,11 +258,19 @@ static WebKitPrintOperationResponse webkitPrintOperationRunDialog(WebKitPrintOpe } #endif -static void drawPagesForPrintingCompleted(WKErrorRef, void* context) +static void drawPagesForPrintingCompleted(WKErrorRef wkPrintError, WKErrorRef, void* context) { GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(WEBKIT_PRINT_OPERATION(context)); WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(printOperation->priv->webView)); page->endPrinting(); + + const WebCore::ResourceError& resourceError = toImpl(wkPrintError)->platformError(); + if (!resourceError.isNull()) { + GOwnPtr<GError> printError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), + resourceError.errorCode(), + resourceError.localizedDescription().utf8().data())); + g_signal_emit(printOperation.get(), signals[FAILED], 0, printError.get()); + } g_signal_emit(printOperation.get(), signals[FINISHED], 0, NULL); } @@ -249,7 +278,7 @@ static void webkitPrintOperationPrintPagesForFrame(WebKitPrintOperation* printOp { PrintInfo printInfo(printSettings, pageSetup); WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(printOperation->priv->webView)); - page->drawPagesForPrinting(webFrame, printInfo, VoidCallback::create(g_object_ref(printOperation), &drawPagesForPrintingCompleted)); + page->drawPagesForPrinting(webFrame, printInfo, PrintFinishedCallback::create(g_object_ref(printOperation), &drawPagesForPrintingCompleted)); } WebKitPrintOperationResponse webkitPrintOperationRunDialogForFrame(WebKitPrintOperation* printOperation, GtkWindow* parent, WebFrameProxy* webFrame) @@ -368,7 +397,8 @@ void webkit_print_operation_set_page_setup(WebKitPrintOperation* printOperation, * If the print dialog is cancelled %WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL * is returned. If the user clicks on the print button, %WEBKIT_PRINT_OPERATION_RESPONSE_PRINT * is returned and the print operation starts. In this case, the #WebKitPrintOperation::finished - * signal is emitted when the operation finishes. + * signal is emitted when the operation finishes. If an error occurs while printing, the signal + * #WebKitPrintOperation::failed is emitted before #WebKitPrintOperation::finished. * If the print dialog is not cancelled current print settings and page setup of @print_operation * are updated with options selected by the user when Print button is pressed in print dialog. * You can get the updated print settings and page setup by calling @@ -395,7 +425,8 @@ WebKitPrintOperationResponse webkit_print_operation_run_dialog(WebKitPrintOperat * webkit_print_operation_set_page_setup(), the default options will be used * and the print job will be sent to the default printer. * The #WebKitPrintOperation::finished signal is emitted when the printing - * operation finishes. + * operation finishes. If an error occurs while printing the signal + * #WebKitPrintOperation::failed is emitted before #WebKitPrintOperation::finished. */ void webkit_print_operation_print(WebKitPrintOperation* printOperation) { diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index e785c3638..4b7e9ad49 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -29,7 +29,9 @@ #include <WebKit2/WKAPICast.h> #include <WebKit2/WKDownload.h> #include <WebKit2/WKFindOptions.h> +#include <WebKit2/WKFullScreenClientGtk.h> #include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WKSerializedScriptValue.h> #include <WebKit2/WKString.h> #include <WebKit2/WebKit2.h> #include <glib.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp new file mode 100644 index 000000000..1cd8aaf7f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp @@ -0,0 +1,112 @@ +/* + * 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 "WebKitResourceLoadClient.h" + +#include "WebContext.h" +#include "WebKitURIRequestPrivate.h" +#include "WebKitURIResponsePrivate.h" +#include "WebKitWebResourcePrivate.h" +#include "WebKitWebViewBasePrivate.h" +#include "WebKitWebViewPrivate.h" +#include "WebURLResponse.h" +#include <WebKit2/WKString.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebCore; +using namespace WebKit; + +static void didInitiateLoadForResource(WKPageRef, WKFrameRef wkFrame, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, bool pageIsProvisionallyLoading, const void* clientInfo) +{ + GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); + webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), wkFrame, resourceIdentifier, request.get(), pageIsProvisionallyLoading); +} + +static void didSendRequestForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, WKURLResponseRef wkRedirectResponse, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); + GRefPtr<WebKitURIResponse> redirectResponse = wkRedirectResponse ? adoptGRef(webkitURIResponseCreateForResourceResponse(toImpl(wkRedirectResponse)->resourceResponse())) : 0; + webkitWebResourceSentRequest(resource.get(), request.get(), redirectResponse.get()); +} + +static void didReceiveResponseForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKURLResponseRef wkResponse, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + GRefPtr<WebKitURIResponse> response = adoptGRef(webkitURIResponseCreateForResourceResponse(toImpl(wkResponse)->resourceResponse())); + webkitWebResourceSetResponse(resource.get(), response.get()); +} + +static void didReceiveContentLengthForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, uint64_t contentLength, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + webkitWebResourceNotifyProgress(resource.get(), contentLength); +} + +static void didFinishLoadForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewResourceLoadFinished(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + webkitWebResourceFinished(resource.get()); +} + +static void didFailLoadForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKErrorRef wkError, const void* clientInfo) +{ + WebKitWebView* webView = WEBKIT_WEB_VIEW(clientInfo); + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier); + if (!resource) + return; + + const ResourceError& resourceError = toImpl(wkError)->platformError(); + GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), + resourceError.errorCode(), + resourceError.localizedDescription().utf8().data())); + webkitWebResourceFailed(resource.get(), webError.get()); + webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier); +} + +void attachResourceLoadClientToView(WebKitWebView* webView) +{ + WKPageResourceLoadClient wkResourceLoadClient = { + kWKPageResourceLoadClientCurrentVersion, + webView, // ClientInfo + didInitiateLoadForResource, + didSendRequestForResource, + didReceiveResponseForResource, + didReceiveContentLengthForResource, + didFinishLoadForResource, + didFailLoadForResource, + }; + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WKPageSetPageResourceLoadClient(wkPage, &wkResourceLoadClient); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.h new file mode 100644 index 000000000..0e6a3613c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.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 WebKitResourceLoadClient_h +#define WebKitResourceLoadClient_h + +#include "WebKitWebView.h" + +void attachResourceLoadClientToView(WebKitWebView*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index b4b267d1b..8bec722b3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -105,7 +105,8 @@ enum { PROP_PRINT_BACKGROUNDS, PROP_ENABLE_WEBAUDIO, PROP_ENABLE_WEBGL, - PROP_ZOOM_TEXT_ONLY + PROP_ZOOM_TEXT_ONLY, + PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD }; static void webKitSettingsSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -215,6 +216,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu case PROP_ZOOM_TEXT_ONLY: webkit_settings_set_zoom_text_only(settings, g_value_get_boolean(value)); break; + case PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD: + webkit_settings_set_javascript_can_access_clipboard(settings, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -328,6 +332,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val case PROP_ZOOM_TEXT_ONLY: g_value_set_boolean(value, webkit_settings_get_zoom_text_only(settings)); break; + case PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD: + g_value_set_boolean(value, webkit_settings_get_javascript_can_access_clipboard(settings)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -840,6 +847,21 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) FALSE, readWriteConstructParamFlags)); + /** + * WebKitSettings:javascript-can-access-clipboard: + * + * Whether JavaScript can access the clipboard. The default value is %FALSE. If + * set to %TRUE, document.execCommand() allows cut, copy and paste commands. + * + */ + g_object_class_install_property(gObjectClass, + PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD, + g_param_spec_boolean("javascript-can-access-clipboard", + _("JavaScript can access clipboard"), + _("Whether JavaScript can access Clipboard"), + FALSE, + readWriteConstructParamFlags)); + g_type_class_add_private(klass, sizeof(WebKitSettingsPrivate)); } @@ -2133,3 +2155,41 @@ gboolean webkit_settings_get_zoom_text_only(WebKitSettings* settings) return settings->priv->zoomTextOnly; } +/** + * webkit_settings_get_javascript_can_access_clipboard: + * @settings: a #WebKitSettings + * + * Get the #WebKitSettings:javascript-can-access-clipboard property. + * + * Returns: %TRUE If javascript-can-access-clipboard is enabled or %FALSE otherwise. + */ +gboolean webkit_settings_get_javascript_can_access_clipboard(WebKitSettings* settings) +{ + g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); + + return WKPreferencesGetJavaScriptCanAccessClipboard(settings->priv->preferences.get()) + && WKPreferencesGetDOMPasteAllowed(settings->priv->preferences.get()); +} + +/** + * webkit_settings_set_javascript_can_access_clipboard: + * @settings: a #WebKitSettings + * @enabled: Value to be set + * + * Set the #WebKitSettings:javascript-can-access-clipboard property. + */ +void webkit_settings_set_javascript_can_access_clipboard(WebKitSettings* settings, gboolean enabled) +{ + g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); + + WebKitSettingsPrivate* priv = settings->priv; + bool currentValue = WKPreferencesGetJavaScriptCanAccessClipboard(priv->preferences.get()) + && WKPreferencesGetDOMPasteAllowed(priv->preferences.get()); + if (currentValue == enabled) + return; + + WKPreferencesSetJavaScriptCanAccessClipboard(priv->preferences.get(), enabled); + WKPreferencesSetDOMPasteAllowed(priv->preferences.get(), enabled); + + g_object_notify(G_OBJECT(settings), "javascript-can-access-clipboard"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h index 25a78aca3..57bf3f17d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h @@ -314,6 +314,13 @@ webkit_settings_set_zoom_text_only (WebKitSettings * WEBKIT_API gboolean webkit_settings_get_zoom_text_only (WebKitSettings *settings); +WEBKIT_API gboolean +webkit_settings_get_javascript_can_access_clipboard (WebKitSettings *settings); + +WEBKIT_API void +webkit_settings_set_javascript_can_access_clipboard (WebKitSettings *settings, + gboolean enabled); + 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 6f0e11c82..9f78c9cbf 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp @@ -20,12 +20,14 @@ #include "config.h" #include "WebKitUIClient.h" +#include "WebKitFileChooserRequestPrivate.h" #include "WebKitPrivate.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebPageProxy.h" #include <WebCore/GtkUtilities.h> +#include <wtf/gobject/GRefPtr.h> using namespace WebKit; @@ -136,6 +138,12 @@ static void printFrame(WKPageRef page, WKFrameRef frame, const void*) webkitWebViewPrintFrame(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), frame); } +static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void *clientInfo) +{ + GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkitFileChooserRequestCreate(parameters, listener)); + webkitWebViewRunFileChooserRequest(WEBKIT_WEB_VIEW(clientInfo), request.get()); +} + void attachUIClientToView(WebKitWebView* webView) { WKPageUIClient wkUIClient = { @@ -169,7 +177,7 @@ void attachUIClientToView(WebKitWebView* webView) 0, // didDraw 0, // pageDidScroll 0, // exceededDatabaseQuota - 0, // runOpenPanel + runOpenPanel, 0, // decidePolicyForGeolocationPermissionRequest 0, // headerHeight 0, // footerHeight diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 360b0a627..0b68c086d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -21,6 +21,7 @@ #include "WebKitWebContext.h" #include "WebContext.h" +#include "WebKitCookieManagerPrivate.h" #include "WebKitDownloadClient.h" #include "WebKitDownloadPrivate.h" #include "WebKitPrivate.h" @@ -39,6 +40,8 @@ enum { struct _WebKitWebContextPrivate { WKRetainPtr<WKContextRef> context; + + GRefPtr<WebKitCookieManager> cookieManager; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -84,12 +87,11 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass static gpointer createDefaultWebContext(gpointer) { - WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL)); + static GRefPtr<WebKitWebContext> webContext = adoptGRef(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; + attachDownloadClientToContext(webContext.get()); + return webContext.get(); } /** @@ -215,6 +217,25 @@ WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const return download; } +/** + * webkit_web_context_get_cookie_manager: + * @context: a #WebKitWebContext + * + * Get the #WebKitCookieManager of @context. + * + * Returns: (transfer none): the #WebKitCookieManager of @context. + */ +WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + + WebKitWebContextPrivate* priv = context->priv; + if (!priv->cookieManager) + priv->cookieManager = adoptGRef(webkitCookieManagerCreate(WKContextGetCookieManager(priv->context.get()))); + + return priv->cookieManager.get(); +} + WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) { GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index b88bed0da..45b6e6c1d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -25,6 +25,7 @@ #define WebKitWebContext_h #include <glib-object.h> +#include <webkit2/WebKitCookieManager.h> #include <webkit2/WebKitDefines.h> #include <webkit2/WebKitDownload.h> @@ -79,20 +80,23 @@ struct _WebKitWebContextClass { }; WEBKIT_API GType -webkit_web_context_get_type (void); +webkit_web_context_get_type (void); WEBKIT_API WebKitWebContext * -webkit_web_context_get_default (void); +webkit_web_context_get_default (void); WEBKIT_API void -webkit_web_context_set_cache_model (WebKitWebContext *context, - WebKitCacheModel cache_model); +webkit_web_context_set_cache_model (WebKitWebContext *context, + WebKitCacheModel cache_model); WEBKIT_API WebKitCacheModel -webkit_web_context_get_cache_model (WebKitWebContext *context); +webkit_web_context_get_cache_model (WebKitWebContext *context); WEBKIT_API WebKitDownload * -webkit_web_context_download_uri (WebKitWebContext *context, - const gchar *uri); +webkit_web_context_download_uri (WebKitWebContext *context, + const gchar *uri); + +WEBKIT_API WebKitCookieManager * +webkit_web_context_get_cookie_manager (WebKitWebContext *context); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp new file mode 100644 index 000000000..6bd51fa08 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp @@ -0,0 +1,363 @@ +/* + * 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 "WebKitWebResource.h" + +#include "WebKitMarshal.h" +#include "WebKitURIRequest.h" +#include "WebKitWebResourcePrivate.h" +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + SENT_REQUEST, + RECEIVED_DATA, + FINISHED, + FAILED, + + LAST_SIGNAL +}; + +enum { + PROP_0, + + PROP_URI, + PROP_RESPONSE +}; + + +struct _WebKitWebResourcePrivate { + WKRetainPtr<WKFrameRef> wkFrame; + CString uri; + GRefPtr<WebKitURIResponse> response; + bool isMainResource; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitWebResource, webkit_web_resource, G_TYPE_OBJECT) + +static void webkitWebResourceFinalize(GObject* object) +{ + WEBKIT_WEB_RESOURCE(object)->priv->~WebKitWebResourcePrivate(); + G_OBJECT_CLASS(webkit_web_resource_parent_class)->finalize(object); +} + +static void webkitWebResourceGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitWebResource* resource = WEBKIT_WEB_RESOURCE(object); + + switch (propId) { + case PROP_URI: + g_value_set_string(value, webkit_web_resource_get_uri(resource)); + break; + case PROP_RESPONSE: + g_value_set_object(value, webkit_web_resource_get_response(resource)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + } +} + +static void webkit_web_resource_init(WebKitWebResource* resource) +{ + WebKitWebResourcePrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(resource, WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResourcePrivate); + resource->priv = priv; + new (priv) WebKitWebResourcePrivate(); +} + +static void webkit_web_resource_class_init(WebKitWebResourceClass* resourceClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(resourceClass); + objectClass->get_property = webkitWebResourceGetProperty; + objectClass->finalize = webkitWebResourceFinalize; + + /** + * WebKitWebResource:uri: + * + * The current active URI of the #WebKitWebResource. + * See webkit_web_resource_get_uri() for more details. + */ + g_object_class_install_property(objectClass, + PROP_URI, + g_param_spec_string("uri", + _("URI"), + _("The current active URI of the result"), + 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebResource:response: + * + * The #WebKitURIResponse associated with this resource. + */ + g_object_class_install_property(objectClass, + PROP_RESPONSE, + g_param_spec_object("response", + _("Response"), + _("The response of the resource"), + WEBKIT_TYPE_URI_RESPONSE, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebResource::sent-request: + * @resource: the #WebKitWebResource + * @request: a #WebKitURIRequest + * @redirected_response: a #WebKitURIResponse, or %NULL + * + * This signal is emitted when @request has been sent to the + * server. In case of a server redirection this signal is + * emitted again with the @request argument containing the new + * request sent to the server due to the redirection and the + * @redirected_response parameter containing the response + * received by the server for the initial request. + */ + signals[SENT_REQUEST] = + g_signal_new("sent-request", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + webkit_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, + WEBKIT_TYPE_URI_REQUEST, + WEBKIT_TYPE_URI_RESPONSE); + + /** + * WebKitWebResource::received-data: + * @resource: the #WebKitWebResource + * @data_length: the length of data received in bytes + * + * This signal is emitted after response is received, + * every time new data has been received. It's + * useful to know the progress of the resource load operation. + */ + signals[RECEIVED_DATA] = + g_signal_new("received-data", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + webkit_marshal_VOID__UINT64, + G_TYPE_NONE, 1, + G_TYPE_UINT64); + + /** + * WebKitWebResource::finished: + * @resource: the #WebKitWebResource + * + * This signal is emitted when the resource load finishes successfully + * or due to an error. In case of errors #WebKitWebResource::failed signal + * is emitted before this one. + */ + signals[FINISHED] = + g_signal_new("finished", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * WebKitWebResource::failed: + * @resource: the #WebKitWebResource + * @error: the #GError that was triggered + * + * This signal is emitted when an error occurs during the resource + * load operation. + */ + signals[FAILED] = + g_signal_new("failed", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + g_type_class_add_private(resourceClass, sizeof(WebKitWebResourcePrivate)); +} + +static void webkitWebResourceUpdateURI(WebKitWebResource* resource, const CString& requestURI) +{ + if (resource->priv->uri == requestURI) + return; + + resource->priv->uri = requestURI; + g_object_notify(G_OBJECT(resource), "uri"); +} + +WebKitWebResource* webkitWebResourceCreate(WKFrameRef wkFrame, WebKitURIRequest* request, bool isMainResource) +{ + ASSERT(wkFrame); + WebKitWebResource* resource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, NULL)); + resource->priv->wkFrame = wkFrame; + resource->priv->uri = webkit_uri_request_get_uri(request); + resource->priv->isMainResource = isMainResource; + return resource; +} + +void webkitWebResourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) +{ + webkitWebResourceUpdateURI(resource, webkit_uri_request_get_uri(request)); + g_signal_emit(resource, signals[SENT_REQUEST], 0, request, redirectResponse); +} + +void webkitWebResourceSetResponse(WebKitWebResource* resource, WebKitURIResponse* response) +{ + resource->priv->response = response; + g_object_notify(G_OBJECT(resource), "response"); +} + +void webkitWebResourceNotifyProgress(WebKitWebResource* resource, guint64 bytesReceived) +{ + g_signal_emit(resource, signals[RECEIVED_DATA], 0, bytesReceived); +} + +void webkitWebResourceFinished(WebKitWebResource* resource) +{ + g_signal_emit(resource, signals[FINISHED], 0, NULL); +} + +void webkitWebResourceFailed(WebKitWebResource* resource, GError* error) +{ + g_signal_emit(resource, signals[FAILED], 0, error); + g_signal_emit(resource, signals[FINISHED], 0, NULL); +} + +/** + * webkit_web_resource_get_uri: + * @resource: a #WebKitWebResource + * + * Returns the current active URI of @web_view. The active URI might change during + * a load operation: + * + * <orderedlist> + * <listitem><para> + * When the resource load starts, the active URI is the requested URI + * </para></listitem> + * <listitem><para> + * When the initial request is sent to the server, #WebKitWebResource::sent-request + * signal is emitted without a redirected response, the active URI is the URI of + * the request sent to the server. + * </para></listitem> + * <listitem><para> + * In case of a server redirection, #WebKitWebResource::sent-request signal + * is emitted again with a redirected response, the active URI is the URI the request + * was redirected to. + * </para></listitem> + * <listitem><para> + * When the response is received from the server, the active URI is the final + * one and it will not change again. + * </para></listitem> + * </orderedlist> + * + * You can monitor the active URI by connecting to the notify::uri + * signal of @resource. + * + * Returns: the current active URI of @resource + */ +const char* webkit_web_resource_get_uri(WebKitWebResource* resource) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0); + + return resource->priv->uri.data(); +} + +/** + * webkit_web_resource_get_response: + * @resource: a #WebKitWebResource + * + * Retrieves the #WebKitURIResponse of the resource load operation. + * 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_web_resource_get_response(WebKitWebResource* resource) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0); + + return resource->priv->response.get(); +} + +static void resourceDataCallback(WKDataRef data, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + g_simple_async_result_set_op_res_gpointer(result.get(), const_cast<OpaqueWKData*>(data), 0); + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_web_resource_get_data: + * @resource: a #WebKitWebResource + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously get the raw data for @resource. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_web_resource_get_data_finish() to get the result of the operation. + */ +void webkit_web_resource_get_data(WebKitWebResource* resource, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_WEB_RESOURCE(resource)); + + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(resource), callback, userData, + reinterpret_cast<gpointer>(webkit_web_resource_get_data)); + if (resource->priv->isMainResource) + WKFrameGetMainResourceData(resource->priv->wkFrame.get(), resourceDataCallback, result); + else { + WKRetainPtr<WKURLRef> url(AdoptWK, WKURLCreateWithUTF8CString(resource->priv->uri.data())); + WKFrameGetResourceData(resource->priv->wkFrame.get(), url.get(), resourceDataCallback, result); + } +} + +/** + * webkit_web_resource_get_data_finish: + * @resource: a #WebKitWebResource + * @result: a #GAsyncResult + * @length: (out): return location for the length of the resource data + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_web_resource_get_data(). + * + * Returns: (transfer full): a string with the data of @resource, or %NULL in case + * of error. if @length is not %NULL, the size of the data will be assigned to it. + */ +guchar* webkit_web_resource_get_data_finish(WebKitWebResource* resource, GAsyncResult* result, gsize* length, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_resource_get_data); + + if (g_simple_async_result_propagate_error(simple, error)) + return 0; + + WKDataRef wkData = static_cast<WKDataRef>(g_simple_async_result_get_op_res_gpointer(simple)); + if (length) + *length = WKDataGetSize(wkData); + return static_cast<guchar*>(g_memdup(WKDataGetBytes(wkData), WKDataGetSize(wkData))); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h new file mode 100644 index 000000000..34af76e2b --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h @@ -0,0 +1,77 @@ +/* + * 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 WebKitWebResource_h +#define WebKitWebResource_h + +#include <glib-object.h> +#include <gio/gio.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitURIResponse.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_RESOURCE (webkit_web_resource_get_type()) +#define WEBKIT_WEB_RESOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResource)) +#define WEBKIT_IS_WEB_RESOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_RESOURCE)) +#define WEBKIT_WEB_RESOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResourceClass)) +#define WEBKIT_IS_WEB_RESOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_RESOURCE)) +#define WEBKIT_WEB_RESOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResourceClass)) + +typedef struct _WebKitWebResource WebKitWebResource; +typedef struct _WebKitWebResourceClass WebKitWebResourceClass; +typedef struct _WebKitWebResourcePrivate WebKitWebResourcePrivate; + +struct _WebKitWebResource { + GObject parent; + + WebKitWebResourcePrivate *priv; +}; + +struct _WebKitWebResourceClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_web_resource_get_type (void); + +WEBKIT_API const gchar * +webkit_web_resource_get_uri (WebKitWebResource *resource); + +WEBKIT_API WebKitURIResponse * +webkit_web_resource_get_response (WebKitWebResource *resource); + +WEBKIT_API void +webkit_web_resource_get_data (WebKitWebResource *resource, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API guchar * +webkit_web_resource_get_data_finish (WebKitWebResource *resource, + GAsyncResult *result, + gsize *length, + GError **error); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h new file mode 100644 index 000000000..5011ae4dd --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h @@ -0,0 +1,34 @@ +/* + * 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 WebKitWebResourcePrivate_h +#define WebKitWebResourcePrivate_h + +#include "WebKitPrivate.h" +#include "WebKitWebResource.h" + +WebKitWebResource* webkitWebResourceCreate(WKFrameRef, WebKitURIRequest*, bool isMainResource); +void webkitWebResourceSentRequest(WebKitWebResource*, WebKitURIRequest*, WebKitURIResponse*); +void webkitWebResourceSetResponse(WebKitWebResource*, WebKitURIResponse*); +void webkitWebResourceNotifyProgress(WebKitWebResource*, guint64 bytesReceived); +void webkitWebResourceFinished(WebKitWebResource*); +void webkitWebResourceFailed(WebKitWebResource*, GError*); + + +#endif // WebKitWebResourcePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index 4f17d4669..56b21df49 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -24,20 +24,25 @@ #include "WebKitBackForwardListPrivate.h" #include "WebKitEnumTypes.h" #include "WebKitError.h" +#include "WebKitFullscreenClient.h" #include "WebKitHitTestResultPrivate.h" +#include "WebKitJavascriptResultPrivate.h" #include "WebKitLoaderClient.h" #include "WebKitMarshal.h" #include "WebKitPolicyClient.h" #include "WebKitPrintOperationPrivate.h" #include "WebKitPrivate.h" +#include "WebKitResourceLoadClient.h" #include "WebKitScriptDialogPrivate.h" #include "WebKitSettingsPrivate.h" #include "WebKitUIClient.h" #include "WebKitWebContextPrivate.h" +#include "WebKitWebResourcePrivate.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebPageProxy.h" +#include <JavaScriptCore/APICast.h> #include <WebCore/DragIcon.h> #include <WebCore/GtkUtilities.h> #include <glib/gi18n-lib.h> @@ -64,6 +69,13 @@ enum { PRINT_REQUESTED, + RESOURCE_LOAD_STARTED, + + ENTER_FULLSCREEN, + LEAVE_FULLSCREEN, + + RUN_FILE_CHOOSER, + LAST_SIGNAL }; @@ -84,6 +96,9 @@ typedef enum { DidReplaceContent } ReplaceContentStatus; +typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap; +typedef HashMap<String, GRefPtr<WebKitWebResource> > ResourcesMap; + struct _WebKitWebViewPrivate { WebKitWebContext* context; CString title; @@ -100,6 +115,11 @@ struct _WebKitWebViewPrivate { unsigned mouseTargetModifiers; GRefPtr<WebKitFindController> findController; + JSGlobalContextRef javascriptGlobalContext; + + GRefPtr<WebKitWebResource> mainResource; + LoadingResourcesMap loadingResourcesMap; + ResourcesMap subresourcesMap; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -188,6 +208,49 @@ static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* set g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView); } +static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request) +{ + GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request); + if (responseID == GTK_RESPONSE_ACCEPT) { + GOwnPtr<GSList> filesList(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog))); + GRefPtr<GPtrArray> filesArray = adoptGRef(g_ptr_array_new()); + for (GSList* file = filesList.get(); file; file = g_slist_next(file)) + g_ptr_array_add(filesArray.get(), file->data); + g_ptr_array_add(filesArray.get(), 0); + webkit_file_chooser_request_select_files(adoptedRequest.get(), reinterpret_cast<const gchar* const*>(filesArray->pdata)); + } else + webkit_file_chooser_request_cancel(adoptedRequest.get()); + + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static gboolean webkitWebViewRunFileChooser(WebKitWebView* webView, WebKitFileChooserRequest* request) +{ + GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(webView)); + if (!widgetIsOnscreenToplevelWindow(toplevel)) + toplevel = 0; + + gboolean allowsMultipleSelection = webkit_file_chooser_request_get_select_multiple(request); + GtkWidget* dialog = gtk_file_chooser_dialog_new(allowsMultipleSelection ? _("Select Files") : _("Select File"), + toplevel ? GTK_WINDOW(toplevel) : 0, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request)) + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), allowsMultipleSelection); + + if (const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request)) + gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), selectedFiles[0]); + + g_signal_connect(dialog, "response", G_CALLBACK(fileChooserDialogResponseCallback), g_object_ref(request)); + gtk_widget_show(dialog); + + return TRUE; +} + static void webkitWebViewConstructed(GObject* object) { if (G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed) @@ -202,6 +265,8 @@ static void webkitWebViewConstructed(GObject* object) attachLoaderClientToView(webView); attachUIClientToView(webView); attachPolicyClientToPage(webView); + attachResourceLoadClientToView(webView); + attachFullScreenClientToView(webView); WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page)))); @@ -255,7 +320,10 @@ static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* valu static void webkitWebViewFinalize(GObject* object) { - WEBKIT_WEB_VIEW(object)->priv->~WebKitWebViewPrivate(); + WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(object)->priv; + if (priv->javascriptGlobalContext) + JSGlobalContextRelease(priv->javascriptGlobalContext); + priv->~WebKitWebViewPrivate(); G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object); } @@ -290,6 +358,7 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webViewClass->create = webkitWebViewCreate; webViewClass->script_dialog = webkitWebViewScriptDialog; webViewClass->decide_policy = webkitWebViewDecidePolicy; + webViewClass->run_file_chooser = webkitWebViewRunFileChooser; g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate)); @@ -666,6 +735,104 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_PRINT_OPERATION); + + /** + * WebKitWebView::resource-load-started: + * @web_view: the #WebKitWebView on which the signal is emitted + * @resource: a #WebKitWebResource + * @request: a #WebKitURIRequest + * + * Emitted when a new resource is going to be loaded. The @request parameter + * contains the #WebKitURIRequest that will be sent to the server. + * You can monitor the load operation by connecting to the different signals + * of @resource. + */ + signals[RESOURCE_LOAD_STARTED] = + g_signal_new("resource-load-started", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, resource_load_started), + 0, 0, + webkit_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, + WEBKIT_TYPE_WEB_RESOURCE, + WEBKIT_TYPE_URI_REQUEST); + + /** + * WebKitWebView::enter-fullscreen: + * @web_view: the #WebKitWebView on which the signal is emitted. + * + * Emitted when JavaScript code calls + * <function>element.webkitRequestFullScreen</function>. If the + * signal is not handled the #WebKitWebView will proceed to full screen + * its top level window. This signal can be used by client code to + * request permission to the user prior doing the full screen + * transition and eventually prepare the top-level window + * (e.g. hide some widgets that would otherwise be part of the + * full screen window). + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to continue emission of the event. + */ + signals[ENTER_FULLSCREEN] = + g_signal_new("enter-fullscreen", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, enter_fullscreen), + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitWebView::leave-fullscreen: + * @web_view: the #WebKitWebView on which the signal is emitted. + * + * Emitted when the #WebKitWebView is about to restore its top level + * window out of its full screen state. This signal can be used by + * client code to restore widgets hidden during the + * #WebKitWebView::enter-fullscreen stage for instance. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to continue emission of the event. + */ + signals[LEAVE_FULLSCREEN] = + g_signal_new("leave-fullscreen", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, leave_fullscreen), + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + /** + * WebKitWebView::run-file-chooser: + * @web_view: the #WebKitWebView on which the signal is emitted + * @request: a #WebKitFileChooserRequest + * + * This signal is emitted when the user interacts with a <input + * type='file' /> HTML element, requesting from WebKit to show + * a dialog to select one or more files to be uploaded. To let the + * application know the details of the file chooser, as well as to + * allow the client application to either cancel the request or + * perform an actual selection of files, the signal will pass an + * instance of the #WebKitFileChooserRequest in the @request + * argument. + * + * The default signal handler will asynchronously run a regular + * #GtkFileChooserDialog for the user to interact with. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + * + */ + signals[RUN_FILE_CHOOSER] = + g_signal_new("run-file-chooser", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser), + g_signal_accumulator_true_handled, 0 /* accumulator data */, + webkit_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, /* number of parameters */ + WEBKIT_TYPE_FILE_CHOOSER_REQUEST); } static bool updateReplaceContentStatus(WebKitWebView* webView, WebKitLoadEvent loadEvent) @@ -689,6 +856,12 @@ static bool updateReplaceContentStatus(WebKitWebView* webView, WebKitLoadEvent l void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent) { + if (loadEvent == WEBKIT_LOAD_STARTED) { + webView->priv->loadingResourcesMap.clear(); + webView->priv->mainResource = 0; + } else if (loadEvent == WEBKIT_LOAD_COMMITTED) + webView->priv->subresourcesMap.clear(); + if (updateReplaceContentStatus(webView, loadEvent)) return; @@ -822,6 +995,77 @@ void webkitWebViewPrintFrame(WebKitWebView* webView, WKFrameRef wkFrame) g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0); } +static inline bool webkitWebViewIsReplacingContentOrDidReplaceContent(WebKitWebView* webView) +{ + return (webView->priv->replaceContentStatus == ReplacingContent || webView->priv->replaceContentStatus == DidReplaceContent); +} + +void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request, bool isMainResource) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return; + + WebKitWebViewPrivate* priv = webView->priv; + WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource); + if (WKFrameIsMainFrame(wkFrame) && isMainResource) + priv->mainResource = resource; + priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource)); + g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request); +} + +WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return 0; + + GRefPtr<WebKitWebResource> resource = webView->priv->loadingResourcesMap.get(resourceIdentifier); + ASSERT(resource.get()); + return resource.get(); +} + +void webkitWebViewRemoveLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return; + + WebKitWebViewPrivate* priv = webView->priv; + ASSERT(priv->loadingResourcesMap.contains(resourceIdentifier)); + priv->loadingResourcesMap.remove(resourceIdentifier); +} + +WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView* webView, uint64_t resourceIdentifier) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return 0; + + WebKitWebViewPrivate* priv = webView->priv; + WebKitWebResource* resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier); + if (resource != priv->mainResource) + priv->subresourcesMap.set(String::fromUTF8(webkit_web_resource_get_uri(resource)), resource); + webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier); + return resource; +} + +bool webkitWebViewEnterFullScreen(WebKitWebView* webView) +{ + gboolean returnValue; + g_signal_emit(webView, signals[ENTER_FULLSCREEN], 0, &returnValue); + return !returnValue; +} + +bool webkitWebViewLeaveFullScreen(WebKitWebView* webView) +{ + gboolean returnValue; + g_signal_emit(webView, signals[LEAVE_FULLSCREEN], 0, &returnValue); + return !returnValue; +} + +void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChooserRequest* request) +{ + gboolean returnValue; + g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue); +} + /** * webkit_web_view_new: * @@ -1466,3 +1710,179 @@ WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView return webView->priv->findController.get(); } + +/** + * webkit_web_view_get_javascript_global_context: + * @web_view: a #WebKitWebView + * + * Get the global JavaScript context used by @web_view to deserialize the + * result values of scripts executed with webkit_web_view_run_javascript(). + * + * Returns: the <function>JSGlobalContextRef</function> used by @web_view to deserialize + * the result values of scripts. + */ +JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + if (!webView->priv->javascriptGlobalContext) + webView->priv->javascriptGlobalContext = JSGlobalContextCreate(0); + return webView->priv->javascriptGlobalContext; +} + +static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSerializedScriptValue, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + if (wkSerializedScriptValue) { + GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get())))); + WebKitJavascriptResult* scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue); + g_simple_async_result_set_op_res_gpointer(result.get(), scriptResult, reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref)); + } else { + GError* error = 0; + g_set_error_literal(&error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED, _("An exception was raised in JavaScript")); + g_simple_async_result_take_error(result.get(), error); + } + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_web_view_run_javascript: + * @web_view: a #WebKitWebView + * @script: the script to run + * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously run @script in the context of the current page in @web_view. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_web_view_run_javascript_finish() to get the result of the operation. + */ +void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); + g_return_if_fail(script); + + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WKRetainPtr<WKStringRef> wkScript = adoptWK(WKStringCreateWithUTF8CString(script)); + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData, + reinterpret_cast<gpointer>(webkit_web_view_run_javascript)); + WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback); +} + +/** + * webkit_web_view_run_javascript_finish: + * @web_view: a #WebKitWebView + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_web_view_run_javascript(). + * + * This is an example of using webkit_web_view_run_javascript() with a script returning + * a string: + * + * <informalexample><programlisting> + * static void + * web_view_javascript_finished (GObject *object, + * GAsyncResult *result, + * gpointer user_data) + * { + * WebKitJavascriptResult *js_result; + * JSValueRef value; + * JSGlobalContextRef context; + * GError *error = NULL; + * + * js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error); + * if (!js_result) { + * g_warning ("Error running javascript: %s", error->message); + * g_error_free (error); + * return; + * } + * + * context = webkit_javascript_result_get_global_context (js_result); + * value = webkit_javascript_result_get_value (js_result); + * if (JSValueIsString (context, value)) { + * JSStringRef *js_str_value; + * gchar *str_value; + * gsize str_length; + * + * js_str_value = JSValueToStringCopy (context, value, NULL)); + * str_length = JSStringGetMaximumUTF8CStringSize (js_str_value); + * str_value = (gchar *)g_malloc (str_length)); + * JSStringGetUTF8CString (js_str_value, str_value, str_length); + * JSStringRelease (js_str_value); + * g_print ("Script result: %s\n", str_value); + * g_free (str_value); + * } else { + * g_warning ("Error running javascript: unexpected return value"); + * } + * webkit_javascript_result_unref (js_result); + * } + * + * static void + * web_view_get_link_url (WebKitWebView *web_view, + * const gchar *link_id) + * { + * gchar *script; + * + * script = g_strdup_printf ("window.document.getElementById('%s').href;", link_id); + * webkit_web_view_run_javascript (web_view, script, web_view_javascript_finished, NULL); + * g_free (script); + * } + * </programlisting></informalexample> + * + * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script + * or %NULL in case of error + */ +WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_view_run_javascript); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + WebKitJavascriptResult* scriptResult = static_cast<WebKitJavascriptResult*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return scriptResult ? webkit_javascript_result_ref(scriptResult) : 0; +} + +/** + * webkit_web_view_get_main_resource: + * @web_view: a #WebKitWebView + * + * Return the main resource of @web_view. + * See also webkit_web_view_get_subresources(): + * + * Returns: (transfer none): the main #WebKitWebResource of the view + * or %NULL if nothing has been loaded. + */ +WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + return webView->priv->mainResource.get(); +} + +/** + * webkit_web_view_get_subresources: + * @web_view: a #WebKitWebView + * + * Return the list of subresources of @web_view. + * See also webkit_web_view_get_main_resource(). + * + * Returns: (element-type WebKitWebResource) (transfer container): a list of #WebKitWebResource. + */ +GList* webkit_web_view_get_subresources(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + GList* subresources = 0; + WebKitWebViewPrivate* priv = webView->priv; + ResourcesMap::const_iterator end = priv->subresourcesMap.end(); + for (ResourcesMap::const_iterator it = priv->subresourcesMap.begin(); it != end; ++it) + subresources = g_list_prepend(subresources, it->second.get()); + + return g_list_reverse(subresources); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h index fb4c48a2d..c56205b96 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h @@ -28,17 +28,21 @@ #ifndef WebKitWebView_h #define WebKitWebView_h +#include <JavaScriptCore/JSBase.h> #include <webkit2/WebKitBackForwardList.h> #include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitFileChooserRequest.h> #include <webkit2/WebKitFindController.h> #include <webkit2/WebKitHitTestResult.h> +#include <webkit2/WebKitJavascriptResult.h> +#include <webkit2/WebKitPolicyDecision.h> #include <webkit2/WebKitScriptDialog.h> #include <webkit2/WebKitSettings.h> #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitWebContext.h> +#include <webkit2/WebKitWebResource.h> #include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> -#include <webkit2/WebKitPolicyDecision.h> G_BEGIN_DECLS @@ -121,28 +125,35 @@ 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_dialog) (WebKitWebView *web_view, - WebKitScriptDialog *dialog); - - gboolean (* decide_policy) (WebKitWebView *web_view, - WebKitPolicyDecision *decision, - WebKitPolicyDecisionType type); - void (* mouse_target_changed) (WebKitWebView *web_view, - WebKitHitTestResult *hit_test_result, - guint modifiers); - gboolean (* print_requested) (WebKitWebView *web_view, - WebKitPrintOperation *print_operation); + 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_dialog) (WebKitWebView *web_view, + WebKitScriptDialog *dialog); + + gboolean (* decide_policy) (WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType type); + void (* mouse_target_changed) (WebKitWebView *web_view, + WebKitHitTestResult *hit_test_result, + guint modifiers); + gboolean (* print_requested) (WebKitWebView *web_view, + WebKitPrintOperation *print_operation); + void (* resource_load_started) (WebKitWebView *web_view, + WebKitWebResource *resource, + WebKitURIRequest *request); + gboolean (* enter_fullscreen) (WebKitWebView *web_view); + gboolean (* leave_fullscreen) (WebKitWebView *web_view); + gboolean (* run_file_chooser) (WebKitWebView *web_view, + WebKitFileChooserRequest *request); /* Padding for future expansion */ void (*_webkit_reserved0) (void); @@ -267,6 +278,24 @@ webkit_web_view_execute_editing_command (WebKitWebView *w WEBKIT_API WebKitFindController * webkit_web_view_get_find_controller (WebKitWebView *web_view); +WEBKIT_API JSGlobalContextRef +webkit_web_view_get_javascript_global_context (WebKitWebView *web_view); + +WEBKIT_API void +webkit_web_view_run_javascript (WebKitWebView *web_view, + const gchar *script, + GAsyncReadyCallback callback, + gpointer user_data); +WEBKIT_API WebKitJavascriptResult * +webkit_web_view_run_javascript_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); + +WEBKIT_API WebKitWebResource * +webkit_web_view_get_main_resource (WebKitWebView *web_view); + +WEBKIT_API GList * +webkit_web_view_get_subresources (WebKitWebView *web_view); G_END_DECLS #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index adcc34ae3..b2cdde564 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -35,6 +35,7 @@ #include "PageClientImpl.h" #include "WebContext.h" #include "WebEventFactory.h" +#include "WebFullScreenClientGtk.h" #include "WebKitPrivate.h" #include "WebKitWebViewBaseAccessible.h" #include "WebKitWebViewBasePrivate.h" @@ -52,14 +53,24 @@ #include <WebCore/PasteboardHelper.h> #include <WebCore/RefPtrCairo.h> #include <WebCore/Region.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> +#include <wtf/HashMap.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> +#if ENABLE(FULLSCREEN_API) +#include "WebFullScreenManagerProxy.h" +#endif + using namespace WebKit; using namespace WebCore; +typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap; + struct _WebKitWebViewBasePrivate { + WebKitWebViewChildrenMap children; OwnPtr<PageClientImpl> pageClient; RefPtr<WebPageProxy> pageProxy; bool isPageActive; @@ -72,6 +83,10 @@ struct _WebKitWebViewBasePrivate { IntSize resizerSize; GRefPtr<AtkObject> accessible; bool needsResizeOnMap; +#if ENABLE(FULLSCREEN_API) + bool fullScreenModeActive; + WebFullScreenClientGtk fullScreenClient; +#endif }; G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER) @@ -152,9 +167,53 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget) { + WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); + WebKitWebViewBasePrivate* priv = webView->priv; + + GtkAllocation childAllocation; + gtk_widget_get_allocation(widget, &childAllocation); + priv->children.set(widget, childAllocation); + gtk_widget_set_parent(widget, GTK_WIDGET(container)); } +static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget) +{ + WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); + WebKitWebViewBasePrivate* priv = webView->priv; + GtkWidget* widgetContainer = GTK_WIDGET(container); + + ASSERT(priv->children.contains(widget)); + gboolean wasVisible = gtk_widget_get_visible(widget); + gtk_widget_unparent(widget); + + priv->children.remove(widget); + if (wasVisible && gtk_widget_get_visible(widgetContainer)) + gtk_widget_queue_resize(widgetContainer); +} + +static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData) +{ + WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); + WebKitWebViewBasePrivate* priv = webView->priv; + + WebKitWebViewChildrenMap children = priv->children; + WebKitWebViewChildrenMap::const_iterator end = children.end(); + for (WebKitWebViewChildrenMap::const_iterator current = children.begin(); current != end; ++current) + (*callback)(current->first, callbackData); +} + +void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect) +{ + const IntRect& geometry = webView->priv->children.get(child); + + if (geometry == childRect) + return; + + webView->priv->children.set(child, childRect); + gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView)); +} + static void webkitWebViewBaseFinalize(GObject* gobject) { WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(gobject); @@ -203,10 +262,27 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr) return FALSE; } -static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation) +static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData) { + if (!gtk_widget_get_visible(child)) + return; + + WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData); WebKitWebViewBasePrivate* priv = webViewBase->priv; + const IntRect& geometry = priv->children.get(child); + if (geometry.isEmpty()) + return; + + GtkAllocation childAllocation = geometry; + gtk_widget_size_allocate(child, &childAllocation); + priv->children.set(child, IntRect()); +} + +static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation) +{ + gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase); + WebKitWebViewBasePrivate* priv = webViewBase->priv; if (priv->pageProxy->drawingArea()) priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize()); @@ -239,7 +315,6 @@ static void webkitWebViewBaseMap(GtkWidget* widget) gtk_widget_get_allocation(widget, &allocation); resizeWebKitWebViewBaseFromAllocation(webViewBase, &allocation); webViewBase->priv->needsResizeOnMap = false; - } static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event) @@ -277,6 +352,20 @@ static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* e WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget); WebKitWebViewBasePrivate* priv = webViewBase->priv; +#if ENABLE(FULLSCREEN_API) + if (priv->fullScreenModeActive) { + switch (event->keyval) { + case GDK_KEY_Escape: + case GDK_KEY_f: + case GDK_KEY_F: + webkitWebViewBaseExitFullScreen(webViewBase); + return TRUE; + default: + break; + } + } +#endif + // Since WebProcess key event handling is not synchronous, handle the event in two passes. // When WebProcess processes the input event, it will call PageClientImpl::doneWithKeyEvent // with event handled status which determines whether to pass the input event to parent or not @@ -467,7 +556,8 @@ static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* con return FALSE; SandboxExtension::Handle handle; - webViewBase->priv->pageProxy->performDrag(dragData.get(), String(), handle); + SandboxExtension::HandleArray sandboxExtensionForUpload; + webViewBase->priv->pageProxy->performDrag(dragData.get(), String(), handle, sandboxExtensionForUpload); gtk_drag_finish(context, TRUE, FALSE, time); return TRUE; } @@ -501,6 +591,8 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass); containerClass->add = webkitWebViewBaseContainerAdd; + containerClass->remove = webkitWebViewBaseContainerRemove; + containerClass->forall = webkitWebViewBaseContainerForall; g_type_class_add_private(webkitWebViewBaseClass, sizeof(WebKitWebViewBasePrivate)); } @@ -528,6 +620,10 @@ void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WKCont priv->pageProxy = toImpl(context)->createWebPage(priv->pageClient.get(), toImpl(pageGroup)); priv->pageProxy->initializeWebPage(); + +#if ENABLE(FULLSCREEN_API) + priv->pageProxy->fullScreenManager()->setWebView(webkitWebViewBase); +#endif } void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip) @@ -575,3 +671,50 @@ void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase) { webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE; } + +void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase) +{ +#if ENABLE(FULLSCREEN_API) + WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv; + if (priv->fullScreenModeActive) + return; + + if (!priv->fullScreenClient.willEnterFullScreen()) + return; + + WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager(); + fullScreenManagerProxy->willEnterFullScreen(); + + GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase)); + if (gtk_widget_is_toplevel(topLevelWindow)) + gtk_window_fullscreen(GTK_WINDOW(topLevelWindow)); + fullScreenManagerProxy->didEnterFullScreen(); + priv->fullScreenModeActive = true; +#endif +} + +void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase) +{ +#if ENABLE(FULLSCREEN_API) + WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv; + if (!priv->fullScreenModeActive) + return; + + if (!priv->fullScreenClient.willExitFullScreen()) + return; + + WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager(); + fullScreenManagerProxy->willExitFullScreen(); + + GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase)); + if (gtk_widget_is_toplevel(topLevelWindow)) + gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow)); + fullScreenManagerProxy->didExitFullScreen(); + priv->fullScreenModeActive = false; +#endif +} + +void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase* webkitWebViewBase, const WKFullScreenClientGtk* wkClient) +{ + webkitWebViewBase->priv->fullScreenClient.initialize(wkClient); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h index 3a9a40b86..cd4c1a1b5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h @@ -28,28 +28,22 @@ #ifndef WebKitWebViewBasePrivate_h #define WebKitWebViewBasePrivate_h +#include "WebKitPrivate.h" #include "WebKitWebViewBase.h" #include "WebPageProxy.h" -#include <WebKit2/WebKit2.h> using namespace WebKit; -G_BEGIN_DECLS - WebKitWebViewBase* webkitWebViewBaseCreate(WebContext*, WebPageGroup*); - GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase*); - WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase*); - void webkitWebViewBaseCreateWebPage(WebKitWebViewBase*, WKContextRef, WKPageGroupRef); - void webkitWebViewBaseSetTooltipText(WebKitWebViewBase*, const char*); - void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase*); - void webkitWebViewBaseStartDrag(WebKitWebViewBase*, const WebCore::DragData&, PassRefPtr<ShareableBitmap> dragImage); - -G_END_DECLS +void webkitWebViewBaseChildMoveResize(WebKitWebViewBase*, GtkWidget*, const WebCore::IntRect&); +void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase*); +void webkitWebViewBaseExitFullScreen(WebKitWebViewBase*); +void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase*, const WKFullScreenClientGtk*); #endif // WebKitWebViewBasePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h index ad8ab2038..717d2c344 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h @@ -45,5 +45,12 @@ WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& mess void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); void webkitWebViewMouseTargetChanged(WebKitWebView*, WKHitTestResultRef, unsigned modifiers); void webkitWebViewPrintFrame(WebKitWebView*, WKFrameRef); +void webkitWebViewResourceLoadStarted(WebKitWebView*, WKFrameRef, uint64_t resourceIdentifier, WebKitURIRequest*, bool isMainResource); +void webkitWebViewRunFileChooserRequest(WebKitWebView*, WebKitFileChooserRequest*); +WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); +void webkitWebViewRemoveLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); +WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView*, uint64_t resourceIdentifier); +bool webkitWebViewEnterFullScreen(WebKitWebView*); +bool webkitWebViewLeaveFullScreen(WebKitWebView*); #endif // WebKitWebViewPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index 4a9cc798c..821127f3d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -26,8 +26,11 @@ <xi:include href="xml/WebKitResponsePolicyDecision.xml"/> <xi:include href="xml/WebKitHitTestResult.xml"/> <xi:include href="xml/WebKitPrintOperation.xml"/> + <xi:include href="xml/WebKitWebResource.xml"/> <xi:include href="xml/WebKitError.xml"/> + <xi:include href="xml/WebKitFileChooserRequest.xml"/> <xi:include href="xml/WebKitFindController.xml"/> + <xi:include href="xml/WebKitCookieManager.xml"/> </chapter> <index id="index-all"> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index a8f54083a..dc5e65ac6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -28,6 +28,7 @@ webkit_web_context_get_default webkit_web_context_get_cache_model webkit_web_context_set_cache_model webkit_web_context_download_uri +webkit_web_context_get_cookie_manager <SUBSECTION Standard> WebKitWebContextClass @@ -49,8 +50,6 @@ webkit_web_context_get_type WebKitWebView WebKitLoadEvent WebKitPolicyDecisionType -WebKitScriptDialog -WebKitScriptDialogType <SUBSECTION Editing Commands> WEBKIT_EDITING_COMMAND_CUT @@ -89,11 +88,27 @@ webkit_web_view_can_execute_editing_command webkit_web_view_can_execute_editing_command_finish webkit_web_view_execute_editing_command webkit_web_view_get_find_controller +webkit_web_view_get_javascript_global_context +webkit_web_view_run_javascript +webkit_web_view_run_javascript_finish + +<SUBSECTION WebKitJavascriptResult> +WebKitJavascriptResult +webkit_javascript_result_ref +webkit_javascript_result_unref +webkit_javascript_result_get_global_context +webkit_javascript_result_get_value + +<SUBSECTION WebKitScriptDialog> +WebKitScriptDialog +WebKitScriptDialogType webkit_script_dialog_get_dialog_type webkit_script_dialog_get_message webkit_script_dialog_confirm_set_confirmed webkit_script_dialog_prompt_get_default_text webkit_script_dialog_prompt_set_text +webkit_web_view_get_main_resource +webkit_web_view_get_subresources <SUBSECTION Standard> WebKitWebViewClass @@ -103,10 +118,12 @@ WEBKIT_TYPE_WEB_VIEW WEBKIT_WEB_VIEW_CLASS WEBKIT_IS_WEB_VIEW_CLASS WEBKIT_WEB_VIEW_GET_CLASS +WEBKIT_TYPE_JAVASCRIPT_RESULT WEBKIT_TYPE_SCRIPT_DIALOG <SUBSECTION Private> webkit_web_view_get_type +webkit_javascript_result_get_type webkit_script_dialog_get_type WebKitWebViewPrivate </SECTION> @@ -232,6 +249,8 @@ webkit_settings_get_enable_webgl webkit_settings_set_enable_webgl webkit_settings_get_zoom_text_only webkit_settings_set_zoom_text_only +webkit_settings_get_javascript_can_access_clipboard +webkit_settings_set_javascript_can_access_clipboard <SUBSECTION Standard> WebKitSettingsClass @@ -458,19 +477,71 @@ webkit_print_operation_get_type </SECTION> <SECTION> +<FILE>WebKitWebResource</FILE> +WebKitWebResource +webkit_web_resource_get_uri +webkit_web_resource_get_response +webkit_web_resource_get_data +webkit_web_resource_get_data_finish + +<SUBSECTION Standard> +WebKitWebResourceClass +WEBKIT_TYPE_WEB_RESOURCE +WEBKIT_WEB_RESOURCE +WEBKIT_IS_WEB_RESOURCE +WEBKIT_WEB_RESOURCE_CLASS +WEBKIT_IS_WEB_RESOURCE_CLASS +WEBKIT_WEB_RESOURCE_GET_CLASS + +<SUBSECTION Private> +WebKitWebResourcePrivate +webkit_web_resource_get_type +</SECTION> + +<SECTION> <FILE>WebKitError</FILE> WEBKIT_NETWORK_ERROR WEBKIT_PLUGIN_ERROR WEBKIT_POLICY_ERROR WEBKIT_DOWNLOAD_ERROR +WEBKIT_PRINT_ERROR +WEBKIT_JAVASCRIPT_ERROR WebKitNetworkError WebKitPluginError WebKitPolicyError WebKitDownloadError +WebKitPrintError +WebKitJavascriptError webkit_network_error_quark webkit_plugin_error_quark webkit_policy_error_quark webkit_download_error_quark +webkit_print_error_quark +webkit_javascript_error_quark +</SECTION> + +<SECTION> +<FILE>WebKitFileChooserRequest</FILE> +WebKitFileChooserRequest +webkit_file_chooser_request_get_mime_types +webkit_file_chooser_request_get_mime_types_filter +webkit_file_chooser_request_get_select_multiple +webkit_file_chooser_request_select_files +webkit_file_chooser_request_get_selected_files +webkit_file_chooser_request_cancel + +<SUBSECTION Standard> +WebKitFileChooserRequestClass +WEBKIT_TYPE_FILE_CHOOSER_REQUEST +WEBKIT_FILE_CHOOSER_REQUEST +WEBKIT_IS_FILE_CHOOSER_REQUEST +WEBKIT_FILE_CHOOSER_REQUEST_CLASS +WEBKIT_IS_FILE_CHOOSER_REQUEST_CLASS +WEBKIT_FILE_CHOOSER_REQUEST_GET_CLASS + +<SUBSECTION Private> +WebKitFileChooserRequestPrivate +webkit_file_chooser_request_get_type </SECTION> <SECTION> @@ -500,3 +571,29 @@ WEBKIT_FIND_CONTROLLER_GET_CLASS WebKitFindControllerPrivate webkit_find_controller_get_type </SECTION> + +<SECTION> +<FILE>WebKitCookieManager</FILE> +WebKitCookieManager +WebKitCookieAcceptPolicy +webkit_cookie_manager_set_accept_policy +webkit_cookie_manager_get_accept_policy +webkit_cookie_manager_get_accept_policy_finish +webkit_cookie_manager_get_domains_with_cookies +webkit_cookie_manager_get_domains_with_cookies_finish +webkit_cookie_manager_delete_cookies_for_domain +webkit_cookie_manager_delete_all_cookies + +<SUBSECTION Standard> +WebKitCookieManagerClass +WEBKIT_TYPE_COOKIE_MANAGER +WEBKIT_COOKIE_MANAGER +WEBKIT_IS_COOKIE_MANAGER +WEBKIT_COOKIE_MANAGER_CLASS +WEBKIT_IS_COOKIE_MANAGER_CLASS +WEBKIT_COOKIE_MANAGER_GET_CLASS + +<SUBSECTION Private> +WebKitCookieManagerPrivate +webkit_cookie_manager_get_type +</SECTION> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types index 8e8d7b13a..1ca821b47 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types @@ -9,5 +9,9 @@ webkit_uri_response_get_type webkit_uri_request_get_type webkit_window_properties_get_type webkit_download_get_type +webkit_file_chooser_request_get_type webkit_find_controller_get_type webkit_script_dialog_get_type +webkit_javascript_result_get_type +webkit_web_resource_get_type +webkit_cookie_manager_get_type diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index 6adb2d5cd..b389f4954 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -2,9 +2,11 @@ if ENABLE_WEBKIT2 TEST_PROGS += \ Programs/WebKit2APITests/TestBackForwardList \ + Programs/WebKit2APITests/TestCookieManager \ Programs/WebKit2APITests/TestDownloads \ Programs/WebKit2APITests/TestLoaderClient \ Programs/WebKit2APITests/TestPrinting \ + Programs/WebKit2APITests/TestResources \ Programs/WebKit2APITests/TestWebKitFindController \ Programs/WebKit2APITests/TestWebKitPolicyClient \ Programs/WebKit2APITests/TestWebKitSettings \ @@ -135,4 +137,16 @@ Programs_WebKit2APITests_TestWebKitFindController_CPPFLAGS = $(webkit2_tests_cpp Programs_WebKit2APITests_TestWebKitFindController_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestWebKitFindController_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestResources_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp +Programs_WebKit2APITests_TestResources_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestResources_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestResources_LDFLAGS = $(webkit2_tests_ldflags) + +Programs_WebKit2APITests_TestCookieManager_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp +Programs_WebKit2APITests_TestCookieManager_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestCookieManager_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestCookieManager_LDFLAGS = $(webkit2_tests_ldflags) + endif # ENABLE_WEBKIT2 diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp new file mode 100644 index 000000000..6d2ecf528 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp @@ -0,0 +1,239 @@ +/* + * 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 "WebKitTestServer.h" +#include "WebViewTest.h" + +static WebKitTestServer* kServer; + +static const char* kFirstPartyDomain = "127.0.0.1"; +static const char* kThirdPartyDomain = "localhost"; +static const char* kIndexHtmlFormat = + "<html><body>" + " <p>WebKitGTK+ Cookie Manager test</p>" + " <img src='http://localhost:%u/image.png' width=5 height=5></img>" + "</body></html>"; + +class CookieManagerTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(CookieManagerTest); + + static void cookiesChangedCallback(WebKitCookieManager*, CookieManagerTest* test) + { + test->m_cookiesChanged = true; + if (test->m_finishLoopWhenCookiesChange) + g_main_loop_quit(test->m_mainLoop); + } + + CookieManagerTest() + : WebViewTest() + , m_cookieManager(webkit_web_context_get_cookie_manager(webkit_web_view_get_context(m_webView))) + , m_acceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY) + , m_domains(0) + , m_cookiesChanged(false) + , m_finishLoopWhenCookiesChange(false) + { + g_signal_connect(m_cookieManager, "changed", G_CALLBACK(cookiesChangedCallback), this); + } + + ~CookieManagerTest() + { + g_strfreev(m_domains); + g_signal_handlers_disconnect_matched(m_cookieManager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + } + + static void getAcceptPolicyReadyCallback(GObject* object, GAsyncResult* result, gpointer userData) + { + GOwnPtr<GError> error; + WebKitCookieAcceptPolicy policy = webkit_cookie_manager_get_accept_policy_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr()); + g_assert(!error.get()); + + CookieManagerTest* test = static_cast<CookieManagerTest*>(userData); + test->m_acceptPolicy = policy; + g_main_loop_quit(test->m_mainLoop); + } + + WebKitCookieAcceptPolicy getAcceptPolicy() + { + m_acceptPolicy = WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY; + webkit_cookie_manager_get_accept_policy(m_cookieManager, getAcceptPolicyReadyCallback, this); + g_main_loop_run(m_mainLoop); + + return m_acceptPolicy; + } + + void setAcceptPolicy(WebKitCookieAcceptPolicy policy) + { + webkit_cookie_manager_set_accept_policy(m_cookieManager, policy); + } + + static void getDomainsReadyCallback(GObject* object, GAsyncResult* result, gpointer userData) + { + GOwnPtr<GError> error; + char** domains = webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr()); + g_assert(!error.get()); + + CookieManagerTest* test = static_cast<CookieManagerTest*>(userData); + test->m_domains = domains; + g_main_loop_quit(test->m_mainLoop); + } + + char** getDomains() + { + g_strfreev(m_domains); + m_domains = 0; + webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, getDomainsReadyCallback, this); + g_main_loop_run(m_mainLoop); + + return m_domains; + } + + void deleteCookiesForDomain(const char* domain) + { + webkit_cookie_manager_delete_cookies_for_domain(m_cookieManager, domain); + } + + void deleteAllCookies() + { + webkit_cookie_manager_delete_all_cookies(m_cookieManager); + } + + void waitUntilCookiesChanged() + { + m_cookiesChanged = false; + m_finishLoopWhenCookiesChange = true; + g_main_loop_run(m_mainLoop); + m_finishLoopWhenCookiesChange = false; + } + + WebKitCookieManager* m_cookieManager; + WebKitCookieAcceptPolicy m_acceptPolicy; + char** m_domains; + bool m_cookiesChanged; + bool m_finishLoopWhenCookiesChange; +}; + +static void testCookieManagerAcceptPolicy(CookieManagerTest* test, gconstpointer) +{ + // Default policy is NO_THIRD_PARTY. + g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + char** domains = test->getDomains(); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 1); + g_assert_cmpstr(domains[0], ==, kFirstPartyDomain); + test->deleteAllCookies(); + + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + domains = test->getDomains(); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 2); + g_assert_cmpstr(domains[0], ==, kFirstPartyDomain); + g_assert_cmpstr(domains[1], ==, kThirdPartyDomain); + test->deleteAllCookies(); + + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_NEVER); + g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NEVER); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + domains = test->getDomains(); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 0); +} + +static void testCookieManagerDeleteCookies(CookieManagerTest* test, gconstpointer) +{ + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2); + + // Delete first party cookies. + test->deleteCookiesForDomain(kFirstPartyDomain); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1); + + // Delete third party cookies. + test->deleteCookiesForDomain(kThirdPartyDomain); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0); + + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2); + + // Delete all cookies. + test->deleteAllCookies(); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0); +} + +static void testCookieManagerCookiesChanged(CookieManagerTest* test, gconstpointer) +{ + g_assert(!test->m_cookiesChanged); + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + g_assert(test->m_cookiesChanged); + + test->deleteCookiesForDomain(kFirstPartyDomain); + test->waitUntilCookiesChanged(); + g_assert(test->m_cookiesChanged); + + test->deleteAllCookies(); + test->waitUntilCookiesChanged(); + g_assert(test->m_cookiesChanged); +} + +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; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + if (g_str_equal(path, "/index.html")) { + char* indexHtml = g_strdup_printf(kIndexHtmlFormat, soup_server_get_port(server)); + soup_message_headers_replace(message->response_headers, "Set-Cookie", "foo=bar"); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, indexHtml, strlen(indexHtml)); + } else if (g_str_equal(path, "/image.png")) + soup_message_headers_replace(message->response_headers, "Set-Cookie", "baz=qux"); + else + g_assert_not_reached(); + soup_message_body_complete(message->response_body); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + CookieManagerTest::add("WebKitCookieManager", "accept-policy", testCookieManagerAcceptPolicy); + CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies); + CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged); +} + +void afterAll() +{ + delete kServer; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp index 461cefa0e..a119e4477 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp @@ -173,15 +173,9 @@ public: 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)); + GOwnPtr<char> sourcePath(g_build_filename(Test::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())); @@ -258,7 +252,7 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) 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)); + GOwnPtr<char> path(g_build_filename(Test::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())); @@ -301,7 +295,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - GOwnPtr<char> filePath(g_build_filename(getWebKit1TestResoucesDir().data(), path, NULL)); + GOwnPtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL)); char* contents; gsize contentsLength; if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) { diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h index 39a2000ac..219cb44ed 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h @@ -20,9 +20,10 @@ #ifndef TestMain_h #define TestMain_h -#include <JavaScriptCore/GOwnPtr.h> -#include <JavaScriptCore/HashSet.h> #include <glib-object.h> +#include <wtf/HashSet.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/text/CString.h> #define MAKE_GLIB_TEST_FIXTURE(ClassName) \ static void setUp(ClassName* fixture, gconstpointer data) \ @@ -45,6 +46,15 @@ public: ~Test() { + if (m_watchedObjects.isEmpty()) + return; + + g_print("Leaked objects:"); + HashSet<GObject*>::const_iterator end = m_watchedObjects.end(); + for (HashSet<GObject*>::const_iterator it = m_watchedObjects.begin(); it != end; ++it) + g_print(" %s(%p)", g_type_name_from_instance(reinterpret_cast<GTypeInstance*>(*it)), *it); + g_print("\n"); + g_assert(m_watchedObjects.isEmpty()); } @@ -59,6 +69,12 @@ public: g_object_weak_ref(object, reinterpret_cast<GWeakNotify>(objectFinalized), this); } + static CString getWebKit1TestResoucesDir() + { + GOwnPtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Source", "WebKit", "gtk", "tests", "resources", NULL)); + return resourcesDir.get(); + } + HashSet<GObject*> m_watchedObjects; }; diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp index 1ddde0858..150c31bd3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp @@ -72,37 +72,63 @@ static void testWebViewPrintRequested(WebViewTest* test, gconstpointer) } #ifdef HAVE_GTK_UNIX_PRINTING -static void testPrintOperationPrintLoadChanged(WebKitWebView*, WebKitLoadEvent loadEvent, WebViewTest* test) -{ - if (loadEvent != WEBKIT_LOAD_FINISHED) - return; - g_main_loop_quit(test->m_mainLoop); -} +class PrintTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(PrintTest); -static void testPrintOperationPrintFinished(WebKitPrintOperation* printOperation, WebViewTest* test) -{ - g_object_unref(printOperation); - g_main_loop_quit(test->m_mainLoop); -} + static void printFinishedCallback(WebKitPrintOperation*, PrintTest* test) + { + g_main_loop_quit(test->m_mainLoop); + } -static gboolean testPrintOperationPrintPrinter(GtkPrinter* printer, gpointer userData) -{ - if (strcmp(gtk_printer_get_name(printer), "Print to File")) - return FALSE; + static void printFailedCallback(WebKitPrintOperation*, GError* error, PrintTest* test) + { + g_assert(test->m_expectedError); + g_assert(error); + g_assert(g_error_matches(error, WEBKIT_PRINT_ERROR, test->m_expectedError)); + } - GtkPrinter** foundPrinter = static_cast<GtkPrinter**>(userData); - *foundPrinter = static_cast<GtkPrinter*>(g_object_ref(printer)); - return TRUE; -} + PrintTest() + : m_expectedError(0) + { + m_printOperation = adoptGRef(webkit_print_operation_new(m_webView)); + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_printOperation.get())); + g_signal_connect(m_printOperation.get(), "finished", G_CALLBACK(printFinishedCallback), this); + g_signal_connect(m_printOperation.get(), "failed", G_CALLBACK(printFailedCallback), this); + } + + static gboolean testPrintOperationPrintPrinter(GtkPrinter* printer, gpointer userData) + { + if (strcmp(gtk_printer_get_name(printer), "Print to File")) + return FALSE; + + GtkPrinter** foundPrinter = static_cast<GtkPrinter**>(userData); + *foundPrinter = static_cast<GtkPrinter*>(g_object_ref(printer)); + return TRUE; + } + + GtkPrinter* findPrintToFilePrinter() + { + GtkPrinter* printer = 0; + gtk_enumerate_printers(testPrintOperationPrintPrinter, &printer, 0, TRUE); + return printer; + } -static void testPrintOperationPrint(WebViewTest* test, gconstpointer) + void waitUntilPrintFinished() + { + g_main_loop_run(m_mainLoop); + } + + GRefPtr<WebKitPrintOperation> m_printOperation; + unsigned int m_expectedError; +}; + +static void testPrintOperationPrint(PrintTest* test, gconstpointer) { - g_signal_connect(test->m_webView, "load-changed", G_CALLBACK(testPrintOperationPrintLoadChanged), test); test->loadHtml("<html><body>WebKitGTK+ printing test</body></html>", 0); - g_main_loop_run(test->m_mainLoop); + test->waitUntilLoadFinished(); - GtkPrinter* printer = 0; - gtk_enumerate_printers(testPrintOperationPrintPrinter, &printer, 0, TRUE); + GRefPtr<GtkPrinter> printer = adoptGRef(test->findPrintToFilePrinter()); if (!printer) { g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found"); return; @@ -113,16 +139,12 @@ static void testPrintOperationPrint(WebViewTest* test, gconstpointer) GOwnPtr<char> outputURI(g_file_get_uri(outputFile.get())); GRefPtr<GtkPrintSettings> printSettings = adoptGRef(gtk_print_settings_new()); - gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer)); + gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get())); gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, outputURI.get()); - g_object_unref(printer); - GRefPtr<WebKitPrintOperation> printOperation = webkit_print_operation_new(test->m_webView); - test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(printOperation.get())); - g_signal_connect(printOperation.get(), "finished", G_CALLBACK(testPrintOperationPrintFinished), test); - webkit_print_operation_set_print_settings(printOperation.get(), printSettings.get()); - webkit_print_operation_print(printOperation.get()); - g_main_loop_run(test->m_mainLoop); + webkit_print_operation_set_print_settings(test->m_printOperation.get(), printSettings.get()); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); GRefPtr<GFileInfo> fileInfo = adoptGRef(g_file_query_info(outputFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE","G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, static_cast<GFileQueryInfoFlags>(0), 0, 0)); @@ -132,6 +154,40 @@ static void testPrintOperationPrint(WebViewTest* test, gconstpointer) g_file_delete(outputFile.get(), 0, 0); } + +static void testPrintOperationErrors(PrintTest* test, gconstpointer) +{ + test->loadHtml("<html><body>WebKitGTK+ printing errors test</body></html>", 0); + test->waitUntilLoadFinished(); + + GRefPtr<GtkPrinter> printer = adoptGRef(test->findPrintToFilePrinter()); + if (!printer) { + g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found"); + return; + } + + // General Error: invalid filename. + test->m_expectedError = WEBKIT_PRINT_ERROR_GENERAL; + GRefPtr<GtkPrintSettings> printSettings = adoptGRef(gtk_print_settings_new()); + gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get())); + gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, "file:///foo/bar"); + webkit_print_operation_set_print_settings(test->m_printOperation.get(), printSettings.get()); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); + + // Printer not found error. + test->m_expectedError = WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND; + gtk_print_settings_set_printer(printSettings.get(), "The fake WebKit printer"); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); + + // No pages to print: print even pages for a single page document. + test->m_expectedError = WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE; + gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get())); + gtk_print_settings_set_page_set(printSettings.get(), GTK_PAGE_SET_EVEN); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); +} #endif // HAVE_GTK_UNIX_PRINTING void beforeAll() @@ -142,7 +198,8 @@ void beforeAll() WebViewTest::add("WebKitPrintOperation", "printing-settings", testPrintOperationPrintSettings); WebViewTest::add("WebKitWebView", "print-requested", testWebViewPrintRequested); #ifdef HAVE_GTK_UNIX_PRINTING - WebViewTest::add("WebKitPrintOperation", "print", testPrintOperationPrint); + PrintTest::add("WebKitPrintOperation", "print", testPrintOperationPrint); + PrintTest::add("WebKitPrintOperation", "print-errors", testPrintOperationErrors); #endif } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp new file mode 100644 index 000000000..cc272c9e8 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp @@ -0,0 +1,596 @@ +/* + * 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 "WebKitTestServer.h" +#include "WebViewTest.h" +#include <wtf/gobject/GRefPtr.h> + +static WebKitTestServer* kServer; + +static const char* kIndexHtml = + "<html><head>" + " <link rel='stylesheet' href='/style.css' type='text/css'>" + " <script language='javascript' src='/javascript.js'></script>" + "</head><body>WebKitGTK+ resources test</body></html>"; + +static const char* kStyleCSS = + "body {" + " margin: 0px;" + " padding: 0px;" + " font-family: sans-serif;" + " background: url(/blank.ico) 0 0 no-repeat;" + " color: black;" + "}"; + +static const char* kJavascript = "function foo () { var a = 1; }"; + +class ResourcesTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(ResourcesTest); + + static void resourceSentRequestCallback(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse, ResourcesTest* test) + { + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + if (redirectResponse) + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(redirectResponse)); + test->resourceSentRequest(resource, request, redirectResponse); + } + + static void resourceReceivedResponseCallback(WebKitWebResource* resource, GParamSpec*, ResourcesTest* test) + { + g_assert(webkit_web_resource_get_response(resource)); + test->resourceReceivedResponse(resource); + } + + static void resourceReceivedDataCallback(WebKitWebResource* resource, guint64 bytesReceived, ResourcesTest* test) + { + test->resourceReceivedData(resource, bytesReceived); + } + + static void resourceFinishedCallback(WebKitWebResource* resource, ResourcesTest* test) + { + test->resourceFinished(resource); + } + + static void resourceFailedCallback(WebKitWebResource* resource, GError* error, ResourcesTest* test) + { + g_assert(error); + test->resourceFailed(resource, error); + } + + static void resourceLoadStartedCallback(WebKitWebView* webView, WebKitWebResource* resource, WebKitURIRequest* request, ResourcesTest* test) + { + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resource)); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + test->resourceLoadStarted(resource, request); + g_signal_connect(resource, "sent-request", G_CALLBACK(resourceSentRequestCallback), test); + g_signal_connect(resource, "notify::response", G_CALLBACK(resourceReceivedResponseCallback), test); + g_signal_connect(resource, "received-data", G_CALLBACK(resourceReceivedDataCallback), test); + g_signal_connect(resource, "finished", G_CALLBACK(resourceFinishedCallback), test); + g_signal_connect(resource, "failed", G_CALLBACK(resourceFailedCallback), test); + } + + ResourcesTest() + : WebViewTest() + , m_resourcesLoaded(0) + , m_resourcesToLoad(0) + , m_resourceDataSize(0) + { + g_signal_connect(m_webView, "resource-load-started", G_CALLBACK(resourceLoadStartedCallback), this); + } + + virtual void resourceLoadStarted(WebKitWebResource* resource, WebKitURIRequest* request) + { + } + + virtual void resourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) + { + } + + virtual void resourceReceivedResponse(WebKitWebResource* resource) + { + } + + virtual void resourceReceivedData(WebKitWebResource* resource, guint64 bytesReceived) + { + } + + virtual void resourceFinished(WebKitWebResource* resource) + { + g_signal_handlers_disconnect_matched(resource, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + if (++m_resourcesLoaded == m_resourcesToLoad) + g_main_loop_quit(m_mainLoop); + } + + virtual void resourceFailed(WebKitWebResource* resource, GError* error) + { + g_assert_not_reached(); + } + + void waitUntilResourcesLoaded(size_t resourcesCount) + { + m_resourcesLoaded = 0; + m_resourcesToLoad = resourcesCount; + g_main_loop_run(m_mainLoop); + } + + static void resourceGetDataCallback(GObject* object, GAsyncResult* result, gpointer userData) + { + size_t dataSize; + GOwnPtr<GError> error; + unsigned char* data = webkit_web_resource_get_data_finish(WEBKIT_WEB_RESOURCE(object), result, &dataSize, &error.outPtr()); + g_assert(!error.get()); + g_assert(data); + g_assert_cmpint(dataSize, >, 0); + + ResourcesTest* test = static_cast<ResourcesTest*>(userData); + test->m_resourceData.set(reinterpret_cast<char*>(data)); + test->m_resourceDataSize = dataSize; + g_main_loop_quit(test->m_mainLoop); + } + + void checkResourceData(WebKitWebResource* resource) + { + m_resourceDataSize = 0; + webkit_web_resource_get_data(resource, resourceGetDataCallback, this); + g_main_loop_run(m_mainLoop); + + const char* uri = webkit_web_resource_get_uri(resource); + if (uri == kServer->getURIForPath("/")) { + g_assert_cmpint(m_resourceDataSize, ==, strlen(kIndexHtml)); + g_assert(!strncmp(m_resourceData.get(), kIndexHtml, m_resourceDataSize)); + } else if (uri == kServer->getURIForPath("/style.css")) { + g_assert_cmpint(m_resourceDataSize, ==, strlen(kStyleCSS)); + g_assert(!strncmp(m_resourceData.get(), kStyleCSS, m_resourceDataSize)); + } else if (uri == kServer->getURIForPath("/javascript.js")) { + g_assert_cmpint(m_resourceDataSize, ==, strlen(kJavascript)); + g_assert(!strncmp(m_resourceData.get(), kJavascript, m_resourceDataSize)); + } else + g_assert_not_reached(); + m_resourceData.clear(); + } + + size_t m_resourcesLoaded; + size_t m_resourcesToLoad; + GOwnPtr<char> m_resourceData; + size_t m_resourceDataSize; +}; + +static void testWebViewResources(ResourcesTest* test, gconstpointer) +{ + // Nothing loaded yet, there shoulnd't be resources. + g_assert(!webkit_web_view_get_main_resource(test->m_webView)); + g_assert(!webkit_web_view_get_subresources(test->m_webView)); + + // Load simple page without subresources. + test->loadHtml("<html><body>Testing WebKitGTK+</body></html>", 0); + test->waitUntilLoadFinished(); + WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_view_get_uri(test->m_webView), ==, webkit_web_resource_get_uri(resource)); + g_assert(!webkit_web_view_get_subresources(test->m_webView)); + + // Load simple page with subresources. + test->loadURI(kServer->getURIForPath("/").data()); + test->waitUntilResourcesLoaded(4); + + resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_view_get_uri(test->m_webView), ==, webkit_web_resource_get_uri(resource)); + GOwnPtr<GList> subresources(webkit_web_view_get_subresources(test->m_webView)); + g_assert(subresources); + g_assert_cmpint(g_list_length(subresources.get()), ==, 3); + +#if 0 + // Load the same URI again. + // FIXME: we need a workaround for bug https://bugs.webkit.org/show_bug.cgi?id=78510. + test->loadURI(kServer->getURIForPath("/").data()); + test->waitUntilResourcesLoaded(4); +#endif + + // Reload. + webkit_web_view_reload(test->m_webView); + test->waitUntilResourcesLoaded(4); +} + +class SingleResourceLoadTest: public ResourcesTest { +public: + MAKE_GLIB_TEST_FIXTURE(SingleResourceLoadTest); + + enum LoadEvents { + Started, + SentRequest, + Redirected, + ReceivedResponse, + ReceivedData, + Finished, + Failed + }; + + SingleResourceLoadTest() + : ResourcesTest() + , m_resourceDataReceived(0) + { + m_resourcesToLoad = 2; + } + + void resourceLoadStarted(WebKitWebResource* resource, WebKitURIRequest* request) + { + if (resource == webkit_web_view_get_main_resource(m_webView)) + return; + + m_resourceDataReceived = 0; + m_resource = resource; + m_loadEvents.append(Started); + } + + void resourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) + { + if (resource != m_resource) + return; + + if (redirectResponse) + m_loadEvents.append(Redirected); + else + m_loadEvents.append(SentRequest); + } + + void resourceReceivedResponse(WebKitWebResource* resource) + { + if (resource != m_resource) + return; + + m_loadEvents.append(ReceivedResponse); + } + + void resourceReceivedData(WebKitWebResource* resource, guint64 bytesReceived) + { + if (resource != m_resource) + return; + + m_resourceDataReceived += bytesReceived; + if (!m_loadEvents.contains(ReceivedData)) + m_loadEvents.append(ReceivedData); + } + + void resourceFinished(WebKitWebResource* resource) + { + if (resource != m_resource) { + ResourcesTest::resourceFinished(resource); + return; + } + + if (!m_loadEvents.contains(Failed)) { + WebKitURIResponse* response = webkit_web_resource_get_response(m_resource.get()); + g_assert(response); + g_assert_cmpint(webkit_uri_response_get_content_length(response), ==, m_resourceDataReceived); + } + m_loadEvents.append(Finished); + ResourcesTest::resourceFinished(resource); + } + + void resourceFailed(WebKitWebResource* resource, GError* error) + { + if (resource == m_resource) + m_loadEvents.append(Failed); + } + + void waitUntilResourceLoadFinsihed() + { + m_resource = 0; + m_resourcesLoaded = 0; + g_main_loop_run(m_mainLoop); + } + + int waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse() + { + waitUntilResourceLoadFinsihed(); + g_assert(m_resource); + WebKitURIResponse* response = webkit_web_resource_get_response(m_resource.get()); + g_assert(response); + return webkit_uri_response_get_status_code(response); + } + + GRefPtr<WebKitWebResource> m_resource; + Vector<LoadEvents> m_loadEvents; + guint64 m_resourceDataReceived; +}; + +static void testWebResourceLoading(SingleResourceLoadTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/javascript.html").data()); + test->waitUntilResourceLoadFinsihed(); + g_assert(test->m_resource); + Vector<SingleResourceLoadTest::LoadEvents>& events = test->m_loadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, SingleResourceLoadTest::Started); + g_assert_cmpint(events[1], ==, SingleResourceLoadTest::SentRequest); + g_assert_cmpint(events[2], ==, SingleResourceLoadTest::ReceivedResponse); + g_assert_cmpint(events[3], ==, SingleResourceLoadTest::ReceivedData); + g_assert_cmpint(events[4], ==, SingleResourceLoadTest::Finished); + events.clear(); + + test->loadURI(kServer->getURIForPath("/redirected-css.html").data()); + test->waitUntilResourceLoadFinsihed(); + g_assert(test->m_resource); + g_assert_cmpint(events.size(), ==, 6); + g_assert_cmpint(events[0], ==, SingleResourceLoadTest::Started); + g_assert_cmpint(events[1], ==, SingleResourceLoadTest::SentRequest); + g_assert_cmpint(events[2], ==, SingleResourceLoadTest::Redirected); + g_assert_cmpint(events[3], ==, SingleResourceLoadTest::ReceivedResponse); + g_assert_cmpint(events[4], ==, SingleResourceLoadTest::ReceivedData); + g_assert_cmpint(events[5], ==, SingleResourceLoadTest::Finished); + events.clear(); + + test->loadURI(kServer->getURIForPath("/invalid-css.html").data()); + test->waitUntilResourceLoadFinsihed(); + g_assert(test->m_resource); + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, SingleResourceLoadTest::Started); + g_assert_cmpint(events[1], ==, SingleResourceLoadTest::SentRequest); + g_assert_cmpint(events[2], ==, SingleResourceLoadTest::Failed); + g_assert_cmpint(events[3], ==, SingleResourceLoadTest::Finished); + events.clear(); +} + +static void testWebResourceResponse(SingleResourceLoadTest* test, gconstpointer) +{ + // No cached resource: First load. + test->loadURI(kServer->getURIForPath("/javascript.html").data()); + gint statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // No cached resource: Second load. + test->loadURI(kServer->getURIForPath("/javascript.html").data()); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // No cached resource: Reload. + webkit_web_view_reload(test->m_webView); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // Cached resource: First load. + test->loadURI(kServer->getURIForPath("/image.html").data()); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // Cached resource: Second load. + test->loadURI(kServer->getURIForPath("/image.html").data()); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // Cached resource: Reload. + webkit_web_view_reload(test->m_webView); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_NOT_MODIFIED); +} + +class ResourceURITrackingTest: public SingleResourceLoadTest { +public: + MAKE_GLIB_TEST_FIXTURE(ResourceURITrackingTest); + + ResourceURITrackingTest() + : SingleResourceLoadTest() + { + } + + static void uriChanged(WebKitWebResource* resource, GParamSpec*, ResourceURITrackingTest* test) + { + g_assert(resource == test->m_resource.get()); + g_assert_cmpstr(test->m_activeURI.data(), !=, webkit_web_resource_get_uri(test->m_resource.get())); + test->m_activeURI = webkit_web_resource_get_uri(test->m_resource.get()); + } + + void resourceLoadStarted(WebKitWebResource* resource, WebKitURIRequest* request) + { + if (resource == webkit_web_view_get_main_resource(m_webView)) + return; + + m_resource = resource; + m_activeURI = webkit_web_resource_get_uri(resource); + checkActiveURI("/redirected.css"); + g_assert_cmpstr(m_activeURI.data(), ==, webkit_uri_request_get_uri(request)); + g_signal_connect(resource, "notify::uri", G_CALLBACK(uriChanged), this); + } + + void resourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) + { + if (resource != m_resource) + return; + + if (redirectResponse) + checkActiveURI("/simple-style.css"); + else + checkActiveURI("/redirected.css"); + g_assert_cmpstr(m_activeURI.data(), ==, webkit_uri_request_get_uri(request)); + } + + void resourceReceivedResponse(WebKitWebResource* resource) + { + if (resource != m_resource) + return; + + checkActiveURI("/simple-style.css"); + } + + void resourceReceivedData(WebKitWebResource* resource, guint64 bytesReceived) + { + } + + void resourceFinished(WebKitWebResource* resource) + { + if (resource == m_resource) + checkActiveURI("/simple-style.css"); + ResourcesTest::resourceFinished(resource); + } + + void resourceFailed(WebKitWebResource*, GError*) + { + g_assert_not_reached(); + } + + CString m_activeURI; + +private: + void checkActiveURI(const char* uri) + { + // g_assert_cmpstr is a macro, so we need to cache the temporary string. + CString serverURI = kServer->getURIForPath(uri); + g_assert_cmpstr(m_activeURI.data(), ==, serverURI.data()); + } +}; + +static void testWebResourceActiveURI(ResourceURITrackingTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/redirected-css.html").data()); + test->waitUntilResourceLoadFinsihed(); +} + +static void testWebResourceGetData(ResourcesTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/").data()); + // FIXME: this should be 4 instead of 3, but we don't get the css image resource + // due to bug https://bugs.webkit.org/show_bug.cgi?id=78510. + test->waitUntilResourcesLoaded(3); + + WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + test->checkResourceData(resource); + + GOwnPtr<GList> subresources(webkit_web_view_get_subresources(test->m_webView)); + for (GList* item = subresources.get(); item; item = g_list_next(item)) + test->checkResourceData(WEBKIT_WEB_RESOURCE(item->data)); +} + +static void replacedContentResourceLoadStartedCallback() +{ + g_assert_not_reached(); +} + +static void testWebViewResourcesReplacedContent(ResourcesTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/").data()); + // FIXME: this should be 4 instead of 3, but we don't get the css image resource + // due to bug https://bugs.webkit.org/show_bug.cgi?id=78510. + test->waitUntilResourcesLoaded(3); + + static const char* replacedHtml = + "<html><head>" + " <title>Content Replaced</title>" + " <link rel='stylesheet' href='data:text/css,body { margin: 0px; padding: 0px; }' type='text/css'>" + " <script language='javascript' src='data:application/javascript,function foo () { var a = 1; }'></script>" + "</head><body onload='document.title=\"Loaded\"'>WebKitGTK+ resources on replaced content test</body></html>"; + g_signal_connect(test->m_webView, "resource-load-started", G_CALLBACK(replacedContentResourceLoadStartedCallback), test); + test->replaceContent(replacedHtml, "http://error-page.foo", 0); + test->waitUntilTitleChangedTo("Loaded"); + + g_assert(!webkit_web_view_get_main_resource(test->m_webView)); + g_assert(!webkit_web_view_get_subresources(test->m_webView)); +} + +static void addCacheHTTPHeadersToResponse(SoupMessage* message) +{ + // The actual date doesn't really matter. + SoupDate* soupDate = soup_date_new_from_now(0); + GOwnPtr<char> date(soup_date_to_string(soupDate, SOUP_DATE_HTTP)); + soup_message_headers_append(message->response_headers, "Last-Modified", date.get()); + soup_date_free(soupDate); + soup_message_headers_append(message->response_headers, "Cache-control", "public, max-age=31536000"); + soupDate = soup_date_new_from_now(3600); + date.set(soup_date_to_string(soupDate, SOUP_DATE_HTTP)); + soup_message_headers_append(message->response_headers, "Expires", date.get()); + soup_date_free(soupDate); +} + +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; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + + if (soup_message_headers_get(message->request_headers, "If-Modified-Since")) { + soup_message_set_status(message, SOUP_STATUS_NOT_MODIFIED); + soup_message_body_complete(message->response_body); + return; + } + + if (g_str_equal(path, "/")) { + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kIndexHtml, strlen(kIndexHtml)); + } else if (g_str_equal(path, "/javascript.html")) { + static const char* javascriptHtml = "<html><head><script language='javascript' src='/javascript.js'></script></head><body></body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, javascriptHtml, strlen(javascriptHtml)); + } else if (g_str_equal(path, "/image.html")) { + static const char* imageHTML = "<html><body><img src='/blank.ico'></img></body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, imageHTML, strlen(imageHTML)); + } else if (g_str_equal(path, "/redirected-css.html")) { + static const char* redirectedCSSHtml = "<html><head><link rel='stylesheet' href='/redirected.css' type='text/css'></head><body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, redirectedCSSHtml, strlen(redirectedCSSHtml)); + } else if (g_str_equal(path, "/invalid-css.html")) { + static const char* invalidCSSHtml = "<html><head><link rel='stylesheet' href='/invalid.css' type='text/css'></head><body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, invalidCSSHtml, strlen(invalidCSSHtml)); + } else if (g_str_equal(path, "/style.css")) { + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleCSS, strlen(kStyleCSS)); + addCacheHTTPHeadersToResponse(message); + } else if (g_str_equal(path, "/javascript.js")) { + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kJavascript, strlen(kJavascript)); + } else if (g_str_equal(path, "/blank.ico")) { + GOwnPtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL)); + char* contents; + gsize contentsLength; + g_file_get_contents(filePath.get(), &contents, &contentsLength, 0); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength); + addCacheHTTPHeadersToResponse(message); + } else if (g_str_equal(path, "/simple-style.css")) { + static const char* simpleCSS = + "body {" + " margin: 0px;" + " padding: 0px;" + "}"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, simpleCSS, strlen(simpleCSS)); + } else if (g_str_equal(path, "/redirected.css")) { + soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); + soup_message_headers_append(message->response_headers, "Location", "/simple-style.css"); + } else if (g_str_equal(path, "/invalid.css")) + soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT); + soup_message_body_complete(message->response_body); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + ResourcesTest::add("WebKitWebView", "resources", testWebViewResources); + SingleResourceLoadTest::add("WebKitWebResource", "loading", testWebResourceLoading); + SingleResourceLoadTest::add("WebKitWebResource", "response", testWebResourceResponse); + ResourceURITrackingTest::add("WebKitWebResource", "active-uri", testWebResourceActiveURI); + ResourcesTest::add("WebKitWebResource", "get-data", testWebResourceGetData); + ResourcesTest::add("WebKitWebView", "replaced-content", testWebViewResourcesReplacedContent); +} + +void afterAll() +{ + delete kServer; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp index 03c5f2fe8..19491c201 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "TestMain.h" -#include <JavaScriptCore/GRefPtr.h> #include <gtk/gtk.h> #include <webkit2/webkit2.h> +#include <wtf/gobject/GRefPtr.h> static void testWebKitSettings(Test*, gconstpointer) { @@ -204,6 +204,11 @@ static void testWebKitSettings(Test*, gconstpointer) webkit_settings_set_zoom_text_only(settings, TRUE); g_assert(webkit_settings_get_zoom_text_only(settings)); + // By default, JavaScript cannot access the clipboard. + g_assert(!webkit_settings_get_javascript_can_access_clipboard(settings)); + webkit_settings_set_javascript_can_access_clipboard(settings, TRUE); + g_assert(webkit_settings_get_javascript_can_access_clipboard(settings)); + g_object_unref(G_OBJECT(settings)); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp index bfeda169f..d65e8a641 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp @@ -332,6 +332,14 @@ static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer) g_assert_cmpint(events[2], ==, UIClientTest::Close); } +static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType) +{ + GtkFileFilterInfo filterInfo; + filterInfo.contains = GTK_FILE_FILTER_MIME_TYPE; + filterInfo.mime_type = mimeType; + return gtk_file_filter_filter(filter, &filterInfo); +} + static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer) { static const char* htmlOnLoadFormat = "<html><body onLoad=\"%s\"></body></html>"; @@ -452,6 +460,252 @@ static void testWebViewZoomLevel(WebViewTest* test, gconstpointer) g_assert_cmpfloat(webkit_web_view_get_zoom_level(test->m_webView), ==, 2.5); } +static void testWebViewRunJavaScript(WebViewTest* test, gconstpointer) +{ + static const char* html = "<html><body><a id='WebKitLink' href='http://www.webkitgtk.org/' title='WebKitGTK+ Title'>WebKitGTK+ Website</a></body></html>"; + test->loadHtml(html, 0); + test->waitUntilLoadFinished(); + + GOwnPtr<GError> error; + WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').title;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + GOwnPtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Title"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').href;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.set(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "http://www.webkitgtk.org/"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').textContent", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.set(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Website"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = 25;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 25); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = 2.5;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 2.5); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = true", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(WebViewTest::javascriptResultToBoolean(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = false", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(!WebViewTest::javascriptResultToBoolean(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = null", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(WebViewTest::javascriptResultIsNull(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("function Foo() { a = 25; } Foo();", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(WebViewTest::javascriptResultIsUndefined(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("foo();", &error.outPtr()); + g_assert(!javascriptResult); + g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); +} + +class FileChooserTest: public UIClientTest { +public: + MAKE_GLIB_TEST_FIXTURE(FileChooserTest); + + FileChooserTest() + { + g_signal_connect(m_webView, "run-file-chooser", G_CALLBACK(runFileChooserCallback), this); + } + + static gboolean runFileChooserCallback(WebKitWebView*, WebKitFileChooserRequest* request, FileChooserTest* test) + { + test->runFileChooser(request); + return TRUE; + } + + void runFileChooser(WebKitFileChooserRequest* request) + { + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + m_fileChooserRequest = request; + g_main_loop_quit(m_mainLoop); + } + + WebKitFileChooserRequest* clickMouseButtonAndWaitForFileChooserRequest(int x, int y) + { + clickMouseButton(x, y); + g_main_loop_run(m_mainLoop); + return m_fileChooserRequest.get(); + } + +private: + GRefPtr<WebKitFileChooserRequest> m_fileChooserRequest; +}; + +static void testWebViewFileChooserRequest(FileChooserTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + static const char* fileChooserHTMLFormat = "<html><body><input style='position:absolute;left:0;top:0;margin:0;padding:0' type='file' %s/></body></html>"; + + // Multiple selections not allowed, no MIME filtering. + GOwnPtr<char> simpleFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "")); + test->loadHtml(simpleFileUploadHTML.get(), 0); + test->waitUntilLoadFinished(); + WebKitFileChooserRequest* fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + g_assert(!webkit_file_chooser_request_get_select_multiple(fileChooserRequest)); + + const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest); + g_assert(!mimeTypes); + GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest); + g_assert(!filter); + const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(!selectedFiles); + webkit_file_chooser_request_cancel(fileChooserRequest); + + // Multiple selections allowed, no MIME filtering, some pre-selected files. + GOwnPtr<char> multipleSelectionFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "multiple")); + test->loadHtml(multipleSelectionFileUploadHTML.get(), 0); + test->waitUntilLoadFinished(); + fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + g_assert(webkit_file_chooser_request_get_select_multiple(fileChooserRequest)); + + mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest); + g_assert(!mimeTypes); + filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest); + g_assert(!filter); + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(!selectedFiles); + + // Select some files. + const gchar* filesToSelect[4] = { "/foo", "/foo/bar", "/foo/bar/baz", 0 }; + webkit_file_chooser_request_select_files(fileChooserRequest, filesToSelect); + + // Check the files that have been just selected. + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(selectedFiles); + g_assert_cmpstr(selectedFiles[0], ==, "/foo"); + g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar"); + g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz"); + g_assert(!selectedFiles[3]); + + // Perform another request to check if the list of files selected + // in the previous step appears now as part of the new request. + fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(selectedFiles); + g_assert_cmpstr(selectedFiles[0], ==, "/foo"); + g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar"); + g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz"); + g_assert(!selectedFiles[3]); + webkit_file_chooser_request_cancel(fileChooserRequest); + + // Multiple selections not allowed, only accept images, audio and video files.. + GOwnPtr<char> mimeFilteredFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "accept='audio/*,video/*,image/*'")); + test->loadHtml(mimeFilteredFileUploadHTML.get(), 0); + test->waitUntilLoadFinished(); + fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + g_assert(!webkit_file_chooser_request_get_select_multiple(fileChooserRequest)); + + mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest); + g_assert(mimeTypes); + g_assert_cmpstr(mimeTypes[0], ==, "audio/*"); + g_assert_cmpstr(mimeTypes[1], ==, "video/*"); + g_assert_cmpstr(mimeTypes[2], ==, "image/*"); + g_assert(!mimeTypes[3]); + + filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest); + g_assert(GTK_IS_FILE_FILTER(filter)); + g_assert(checkMimeTypeForFilter(filter, "audio/*")); + g_assert(checkMimeTypeForFilter(filter, "video/*")); + g_assert(checkMimeTypeForFilter(filter, "image/*")); + + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(!selectedFiles); + webkit_file_chooser_request_cancel(fileChooserRequest); +} + +class FullScreenClientTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(FullScreenClientTest); + + enum FullScreenEvent { + None, + Enter, + Leave + }; + + static gboolean viewEnterFullScreenCallback(WebKitWebView*, FullScreenClientTest* test) + { + test->m_event = Enter; + g_main_loop_quit(test->m_mainLoop); + return FALSE; + } + + static gboolean viewLeaveFullScreenCallback(WebKitWebView*, FullScreenClientTest* test) + { + test->m_event = Leave; + g_main_loop_quit(test->m_mainLoop); + return FALSE; + } + + FullScreenClientTest() + : m_event(None) + { + webkit_settings_set_enable_fullscreen(webkit_web_view_get_settings(m_webView), TRUE); + g_signal_connect(m_webView, "enter-fullscreen", G_CALLBACK(viewEnterFullScreenCallback), this); + g_signal_connect(m_webView, "leave-fullscreen", G_CALLBACK(viewLeaveFullScreenCallback), this); + } + + ~FullScreenClientTest() + { + g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + } + + void requestFullScreenAndWaitUntilEnteredFullScreen() + { + m_event = None; + webkit_web_view_run_javascript(m_webView, "document.documentElement.webkitRequestFullScreen();", 0, 0); + g_main_loop_run(m_mainLoop); + } + + static gboolean leaveFullScreenIdle(FullScreenClientTest* test) + { + test->keyStroke(GDK_KEY_Escape); + return FALSE; + } + + void leaveFullScreenAndWaitUntilLeftFullScreen() + { + m_event = None; + g_idle_add(reinterpret_cast<GSourceFunc>(leaveFullScreenIdle), this); + g_main_loop_run(m_mainLoop); + } + + FullScreenEvent m_event; +}; + +static void testWebViewFullScreen(FullScreenClientTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + test->loadHtml("<html><body>FullScreen test</body></html>", 0); + test->waitUntilLoadFinished(); + test->requestFullScreenAndWaitUntilEnteredFullScreen(); + g_assert_cmpint(test->m_event, ==, FullScreenClientTest::Enter); + test->leaveFullScreenAndWaitUntilLeftFullScreen(); + g_assert_cmpint(test->m_event, ==, FullScreenClientTest::Leave); +} + void beforeAll() { WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext); @@ -463,6 +717,9 @@ void beforeAll() UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties); UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget); WebViewTest::add("WebKitWebView", "zoom-level", testWebViewZoomLevel); + WebViewTest::add("WebKitWebView", "run-javascript", testWebViewRunJavaScript); + FileChooserTest::add("WebKitWebView", "file-chooser-request", testWebViewFileChooserRequest); + FullScreenClientTest::add("WebKitWebView", "fullscreen", testWebViewFullScreen); } void afterAll() diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp index 31de72911..7a9e49bc6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp @@ -21,12 +21,14 @@ #include "config.h" #include "WebViewTest.h" +#include <JavaScriptCore/JSRetainPtr.h> #include <WebCore/GOwnPtrGtk.h> WebViewTest::WebViewTest() : m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new()))) , m_mainLoop(g_main_loop_new(0, TRUE)) , m_parentWindow(0) + , m_javascriptResult(0) { assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView)); } @@ -35,6 +37,8 @@ WebViewTest::~WebViewTest() { if (m_parentWindow) gtk_widget_destroy(m_parentWindow); + if (m_javascriptResult) + webkit_javascript_result_unref(m_javascriptResult); g_object_unref(m_webView); g_main_loop_unref(m_mainLoop); } @@ -74,15 +78,7 @@ void WebViewTest::loadRequest(WebKitURIRequest* request) void WebViewTest::replaceContent(const char* html, const char* contentURI, const char* baseURI) { - // FIXME: The active uri should be the contentURI, - // but WebPageProxy doesn't return the unreachableURL - // when the page has been loaded with AlternateHTML() - // See https://bugs.webkit.org/show_bug.cgi?id=75465. -#if 0 m_activeURI = contentURI; -#else - m_activeURI = "about:blank"; -#endif webkit_web_view_replace_content(m_webView, html, contentURI, baseURI); } @@ -202,3 +198,142 @@ void WebViewTest::mouseMoveTo(int x, int y, unsigned int mouseModifiers) gtk_main_do_event(event.get()); } +void WebViewTest::clickMouseButton(int x, int y, unsigned int button, unsigned int mouseModifiers) +{ + doMouseButtonEvent(GDK_BUTTON_PRESS, x, y, button, mouseModifiers); + doMouseButtonEvent(GDK_BUTTON_RELEASE, x, y, button, mouseModifiers); +} + +void WebViewTest::keyStroke(unsigned int keyVal, unsigned int keyModifiers) +{ + g_assert(m_parentWindow); + GtkWidget* viewWidget = GTK_WIDGET(m_webView); + g_assert(gtk_widget_get_realized(viewWidget)); + + GOwnPtr<GdkEvent> event(gdk_event_new(GDK_KEY_PRESS)); + event->key.keyval = keyVal; + + event->key.time = GDK_CURRENT_TIME; + event->key.window = gtk_widget_get_window(viewWidget); + g_object_ref(event->key.window); + gdk_event_set_device(event.get(), gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget)))); + event->key.state = keyModifiers; + + // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+. + GOwnPtr<GdkKeymapKey> keys; + int keysCount; + if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount)) + event->key.hardware_keycode = keys.get()[0].keycode; + + gtk_main_do_event(event.get()); + event->key.type = GDK_KEY_RELEASE; + gtk_main_do_event(event.get()); +} + +void WebViewTest::doMouseButtonEvent(GdkEventType eventType, int x, int y, unsigned int button, unsigned int mouseModifiers) +{ + g_assert(m_parentWindow); + GtkWidget* viewWidget = GTK_WIDGET(m_webView); + g_assert(gtk_widget_get_realized(viewWidget)); + + GOwnPtr<GdkEvent> event(gdk_event_new(eventType)); + event->button.window = gtk_widget_get_window(viewWidget); + g_object_ref(event->button.window); + + event->button.time = GDK_CURRENT_TIME; + event->button.x = x; + event->button.y = y; + event->button.axes = 0; + event->button.state = mouseModifiers; + event->button.button = button; + + event->button.device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget))); + + int xRoot, yRoot; + gdk_window_get_root_coords(gtk_widget_get_window(viewWidget), x, y, &xRoot, &yRoot); + event->button.x_root = xRoot; + event->button.y_root = yRoot; + gtk_main_do_event(event.get()); +} + +static void runJavaScriptReadyCallback(GObject*, GAsyncResult* result, WebViewTest* test) +{ + test->m_javascriptResult = webkit_web_view_run_javascript_finish(test->m_webView, result, test->m_javascriptError); + g_main_loop_quit(test->m_mainLoop); +} + +WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* javascript, GError** error) +{ + if (m_javascriptResult) + webkit_javascript_result_unref(m_javascriptResult); + m_javascriptResult = 0; + m_javascriptError = error; + webkit_web_view_run_javascript(m_webView, javascript, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this); + g_main_loop_run(m_mainLoop); + + return m_javascriptResult; +} + +static char* jsValueToCString(JSGlobalContextRef context, JSValueRef value) +{ + g_assert(value); + g_assert(JSValueIsString(context, value)); + + JSRetainPtr<JSStringRef> stringValue(Adopt, JSValueToStringCopy(context, value, 0)); + g_assert(stringValue); + + size_t cStringLength = JSStringGetMaximumUTF8CStringSize(stringValue.get()); + char* cString = static_cast<char*>(g_malloc(cStringLength)); + JSStringGetUTF8CString(stringValue.get(), cString, cStringLength); + return cString; +} + +char* WebViewTest::javascriptResultToCString(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + return jsValueToCString(context, webkit_javascript_result_get_value(javascriptResult)); +} + +double WebViewTest::javascriptResultToNumber(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + g_assert(JSValueIsNumber(context, value)); + + return JSValueToNumber(context, value, 0); +} + +bool WebViewTest::javascriptResultToBoolean(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + g_assert(JSValueIsBoolean(context, value)); + + return JSValueToBoolean(context, value); +} + +bool WebViewTest::javascriptResultIsNull(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + + return JSValueIsNull(context, value); +} + +bool WebViewTest::javascriptResultIsUndefined(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + + return JSValueIsUndefined(context, value); +} + diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h index 01f468562..92e123630 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h @@ -47,12 +47,28 @@ public: void showInWindowAndWaitUntilMapped(); void mouseMoveTo(int x, int y, unsigned int mouseModifiers = 0); + void clickMouseButton(int x, int y, unsigned int button = 1, unsigned int mouseModifiers = 0); + void keyStroke(unsigned int keyVal, unsigned int keyModifiers = 0); + + WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**); + + // Javascript result helpers. + static char* javascriptResultToCString(WebKitJavascriptResult*); + static double javascriptResultToNumber(WebKitJavascriptResult*); + static bool javascriptResultToBoolean(WebKitJavascriptResult*); + static bool javascriptResultIsNull(WebKitJavascriptResult*); + static bool javascriptResultIsUndefined(WebKitJavascriptResult*); WebKitWebView* m_webView; GMainLoop* m_mainLoop; CString m_activeURI; GtkWidget* m_parentWindow; CString m_expectedTitle; + WebKitJavascriptResult* m_javascriptResult; + GError** m_javascriptError; + +private: + void doMouseButtonEvent(GdkEventType, int, int, unsigned int, unsigned int); }; #endif // WebViewTest_h diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index 0a807bc3d..c5460f333 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -25,21 +25,25 @@ #include <webkit2/WebKitBackForwardList.h> #include <webkit2/WebKitBackForwardListItem.h> +#include <webkit2/WebKitCookieManager.h> #include <webkit2/WebKitDefines.h> #include <webkit2/WebKitDownload.h> #include <webkit2/WebKitEditingCommands.h> #include <webkit2/WebKitEnumTypes.h> #include <webkit2/WebKitError.h> +#include <webkit2/WebKitFileChooserRequest.h> #include <webkit2/WebKitFindController.h> #include <webkit2/WebKitHitTestResult.h> +#include <webkit2/WebKitJavascriptResult.h> #include <webkit2/WebKitPrintOperation.h> #include <webkit2/WebKitScriptDialog.h> #include <webkit2/WebKitSettings.h> #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitURIResponse.h> #include <webkit2/WebKitWebContext.h> -#include <webkit2/WebKitWebViewBase.h> +#include <webkit2/WebKitWebResource.h> #include <webkit2/WebKitWebView.h> +#include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> #undef __WEBKIT2_H_INSIDE__ diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list index 5f7356039..de3032819 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list @@ -3,8 +3,10 @@ BOOLEAN:ENUM,STRING,POINTER BOOLEAN:OBJECT BOOLEAN:OBJECT,ENUM BOOLEAN:STRING +BOOLEAN:VOID OBJECT:VOID VOID:OBJECT,UINT +VOID:OBJECT,OBJECT VOID:OBJECT,POINTER VOID:UINT64 |