diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
commit | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch) | |
tree | 8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/WebKit2/UIProcess | |
parent | d11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff) | |
download | qtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz |
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/WebKit2/UIProcess')
149 files changed, 4765 insertions, 721 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKNotificationManager.cpp b/Source/WebKit2/UIProcess/API/C/WKNotificationManager.cpp index 6ddfa4cc8..60671a7e1 100644 --- a/Source/WebKit2/UIProcess/API/C/WKNotificationManager.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKNotificationManager.cpp @@ -55,3 +55,13 @@ void WKNotificationManagerProviderDidCloseNotifications(WKNotificationManagerRef { toImpl(managerRef)->providerDidCloseNotifications(toImpl(notificationIDs)); } + +void WKNotificationManagerProviderDidUpdateNotificationPolicy(WKNotificationManagerRef managerRef, WKSecurityOriginRef origin, bool allowed) +{ + toImpl(managerRef)->providerDidUpdateNotificationPolicy(toImpl(origin), allowed); +} + +void WKNotificationManagerProviderDidRemoveNotificationPolicies(WKNotificationManagerRef managerRef, WKArrayRef origins) +{ + toImpl(managerRef)->providerDidRemoveNotificationPolicies(toImpl(origins)); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKNotificationManager.h b/Source/WebKit2/UIProcess/API/C/WKNotificationManager.h index 7360dad01..7074a2186 100644 --- a/Source/WebKit2/UIProcess/API/C/WKNotificationManager.h +++ b/Source/WebKit2/UIProcess/API/C/WKNotificationManager.h @@ -39,6 +39,8 @@ WK_EXPORT void WKNotificationManagerSetProvider(WKNotificationManagerRef manager WK_EXPORT void WKNotificationManagerProviderDidShowNotification(WKNotificationManagerRef managerRef, uint64_t notificationID); WK_EXPORT void WKNotificationManagerProviderDidClickNotification(WKNotificationManagerRef managerRef, uint64_t notificationID); WK_EXPORT void WKNotificationManagerProviderDidCloseNotifications(WKNotificationManagerRef managerRef, WKArrayRef notificationIDs); +WK_EXPORT void WKNotificationManagerProviderDidUpdateNotificationPolicy(WKNotificationManagerRef managerRef, WKSecurityOriginRef origin, bool allowed); +WK_EXPORT void WKNotificationManagerProviderDidRemoveNotificationPolicies(WKNotificationManagerRef managerRef, WKArrayRef origins); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/C/WKNotificationProvider.h b/Source/WebKit2/UIProcess/API/C/WKNotificationProvider.h index 580608ccf..42a4beb92 100644 --- a/Source/WebKit2/UIProcess/API/C/WKNotificationProvider.h +++ b/Source/WebKit2/UIProcess/API/C/WKNotificationProvider.h @@ -35,9 +35,9 @@ extern "C" { typedef void (*WKNotificationProviderShowCallback)(WKPageRef page, WKNotificationRef notification, const void* clientInfo); typedef void (*WKNotificationProviderCancelCallback)(WKNotificationRef notification, const void* clientInfo); typedef void (*WKNotificationProviderDidDestroyNotificationCallback)(WKNotificationRef notification, const void* clientInfo); -typedef int (*WKNotificationProviderPolicyForNotificationPermissionAtOriginCallback)(WKSecurityOriginRef origin, const void *clientInfo); typedef void (*WKNotificationProviderAddNotificationManagerCallback)(WKNotificationManagerRef manager, const void* clientInfo); typedef void (*WKNotificationProviderRemoveNotificationManagerCallback)(WKNotificationManagerRef manager, const void* clientInfo); +typedef WKDictionaryRef (*WKNotificationProviderNotificationPermissionsCallback)(const void* clientInfo); struct WKNotificationProvider { int version; @@ -45,9 +45,9 @@ struct WKNotificationProvider { WKNotificationProviderShowCallback show; WKNotificationProviderCancelCallback cancel; WKNotificationProviderDidDestroyNotificationCallback didDestroyNotification; - WKNotificationProviderPolicyForNotificationPermissionAtOriginCallback policyForNotificationPermissionAtOrigin; WKNotificationProviderAddNotificationManagerCallback addNotificationManager; WKNotificationProviderRemoveNotificationManagerCallback removeNotificationManager; + WKNotificationProviderNotificationPermissionsCallback notificationPermissions; }; typedef struct WKNotificationProvider WKNotificationProvider; diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.cpp b/Source/WebKit2/UIProcess/API/C/WKPage.cpp index 9c7a02916..3010016c3 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPage.cpp @@ -379,6 +379,16 @@ WKPaginationMode WKPageGetPaginationMode(WKPageRef pageRef) return kWKPaginationModeUnpaginated; } +void WKPageSetPaginationBehavesLikeColumns(WKPageRef pageRef, bool behavesLikeColumns) +{ + toImpl(pageRef)->setPaginationBehavesLikeColumns(behavesLikeColumns); +} + +bool WKPageGetPaginationBehavesLikeColumns(WKPageRef pageRef) +{ + return toImpl(pageRef)->paginationBehavesLikeColumns(); +} + void WKPageSetPageLength(WKPageRef pageRef, double pageLength) { toImpl(pageRef)->setPageLength(pageLength); @@ -661,3 +671,8 @@ void WKPageSetShouldSendEventsSynchronously(WKPageRef page, bool sync) { toImpl(page)->setShouldSendEventsSynchronously(sync); } + +void WKPageSetMediaVolume(WKPageRef page, float volume) +{ + toImpl(page)->setMediaVolume(volume); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.h b/Source/WebKit2/UIProcess/API/C/WKPage.h index 1de70628c..ea8049dd5 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.h +++ b/Source/WebKit2/UIProcess/API/C/WKPage.h @@ -70,6 +70,7 @@ typedef void (*WKPageDidReceiveAuthenticationChallengeInFrameCallback)(WKPageRef typedef void (*WKPageDidChangeBackForwardListCallback)(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void *clientInfo); typedef bool (*WKPageShouldGoToBackForwardListItemCallback)(WKPageRef page, WKBackForwardListItemRef item, const void *clientInfo); typedef void (*WKPageDidFailToInitializePluginCallback)(WKPageRef page, WKStringRef mimeType, const void* clientInfo); +typedef void (*WKPageDidNewFirstVisuallyNonEmptyLayoutCallback)(WKPageRef page, WKTypeRef userData, const void *clientInfo); struct WKPageLoaderClient { int version; @@ -106,6 +107,9 @@ struct WKPageLoaderClient { // Version 1 WKPageDidDetectXSSForFrameCallback didDetectXSSForFrame; + + // FIXME: didFirstVisuallyNonEmptyLayoutForFrame and didNewFirstVisuallyNonEmptyLayout should be merged. + WKPageDidNewFirstVisuallyNonEmptyLayoutCallback didNewFirstVisuallyNonEmptyLayout; }; typedef struct WKPageLoaderClient WKPageLoaderClient; diff --git a/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h b/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h index d378adef6..097aabfe1 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPagePrivate.h @@ -61,6 +61,8 @@ typedef uint32_t WKPaginationMode; WK_EXPORT void WKPageSetPaginationMode(WKPageRef page, WKPaginationMode paginationMode); WK_EXPORT WKPaginationMode WKPageGetPaginationMode(WKPageRef page); +WK_EXPORT void WKPageSetPaginationBehavesLikeColumns(WKPageRef page, bool behavesLikeColumns); +WK_EXPORT bool WKPageGetPaginationBehavesLikeColumns(WKPageRef page); WK_EXPORT void WKPageSetPageLength(WKPageRef page, double pagesPerView); WK_EXPORT double WKPageGetPageLength(WKPageRef page); WK_EXPORT void WKPageSetGapBetweenPages(WKPageRef page, double gap); @@ -87,6 +89,8 @@ WK_EXPORT WKImageRef WKPageCreateSnapshotOfVisibleContent(WKPageRef page); WK_EXPORT void WKPageSetShouldSendEventsSynchronously(WKPageRef page, bool sync); +WK_EXPORT void WKPageSetMediaVolume(WKPageRef page, float volume); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp index 35eb5d923..60e7b7264 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp @@ -382,6 +382,16 @@ bool WKPreferencesGetCompositingRepaintCountersVisible(WKPreferencesRef preferen return toImpl(preferencesRef)->compositingRepaintCountersVisible(); } +void WKPreferencesSetCSSCustomFilterEnabled(WKPreferencesRef preferencesRef, bool flag) +{ + toImpl(preferencesRef)->setCSSCustomFilterEnabled(flag); +} + +bool WKPreferencesGetCSSCustomFilterEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->cssCustomFilterEnabled(); +} + void WKPreferencesSetWebGLEnabled(WKPreferencesRef preferencesRef, bool flag) { toImpl(preferencesRef)->setWebGLEnabled(flag); @@ -711,3 +721,20 @@ bool WKPreferencesGetShouldDisplayTextDescriptions(WKPreferencesRef preferencesR { return toImpl(preferencesRef)->shouldDisplayTextDescriptions(); } + +void WKPreferencesSetNotificationsEnabled(WKPreferencesRef preferencesRef, bool enabled) +{ + toImpl(preferencesRef)->setNotificationsEnabled(enabled); +} + +bool WKPreferencesGetNotificationsEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->notificationsEnabled(); +} + +void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef) +{ + // Currently we reset the overrides on the web process when preferencesDidChange() is called. Since WTR preferences + // are usually always the same (in the UI process), they are not sent to web process, not triggering the reset. + toImpl(preferencesRef)->forceUpdate(); +} diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.h b/Source/WebKit2/UIProcess/API/C/WKPreferences.h index 00fc89df8..f13559acb 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.h @@ -193,6 +193,10 @@ WK_EXPORT bool WKPreferencesGetShouldDisplayCaptions(WKPreferencesRef preference WK_EXPORT void WKPreferencesSetShouldDisplayTextDescriptions(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetShouldDisplayTextDescriptions(WKPreferencesRef preferencesRef); +// Defaults to false +WK_EXPORT void WKPreferencesSetNotificationsEnabled(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetNotificationsEnabled(WKPreferencesRef preferencesRef); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h index f11fb3af2..3208c6ea3 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h @@ -80,6 +80,10 @@ WK_EXPORT bool WKPreferencesGetCompositingBordersVisible(WKPreferencesRef); WK_EXPORT void WKPreferencesSetCompositingRepaintCountersVisible(WKPreferencesRef, bool); WK_EXPORT bool WKPreferencesGetCompositingRepaintCountersVisible(WKPreferencesRef); +// Defaults to true. +WK_EXPORT void WKPreferencesSetCSSCustomFilterEnabled(WKPreferencesRef, bool flag); +WK_EXPORT bool WKPreferencesGetCSSCustomFilterEnabled(WKPreferencesRef); + // Defaults to false. WK_EXPORT void WKPreferencesSetWebGLEnabled(WKPreferencesRef, bool); WK_EXPORT bool WKPreferencesGetWebGLEnabled(WKPreferencesRef); @@ -156,6 +160,8 @@ WK_EXPORT bool WKPreferencesGetMockScrollbarsEnabled(WKPreferencesRef preference WK_EXPORT void WKPreferencesSetApplicationChromeModeEnabled(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetApplicationChromeModeEnabled(WKPreferencesRef preferencesRef); +WK_EXPORT void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp index aaee9563d..a56265adb 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp @@ -32,13 +32,14 @@ #include "WebContext.h" #include "WebContextMenuProxy.h" #include "WebPageProxy.h" +#include "ewk_private.h" using namespace WebCore; namespace WebKit { -PageClientImpl::PageClientImpl(WebContext* context, WebPageGroup* pageGroup, Evas_Object* viewObject) - : m_viewObject(viewObject) +PageClientImpl::PageClientImpl(WebContext* context, WebPageGroup* pageGroup, Evas_Object* viewWidget) + : m_viewWidget(viewWidget) { m_page = context->createWebPage(this, pageGroup); m_page->initializeWebPage(); @@ -56,7 +57,7 @@ PassOwnPtr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy() void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect) { - evas_object_image_data_update_add(m_viewObject, rect.x(), rect.y(), rect.width(), rect.height()); + ewk_view_display(m_viewWidget, rect); } void PageClientImpl::displayView() @@ -72,7 +73,7 @@ void PageClientImpl::scrollView(const WebCore::IntRect& scrollRect, const WebCor WebCore::IntSize PageClientImpl::viewSize() { int width, height; - evas_object_geometry_get(m_viewObject, 0, 0, &width, &height); + evas_object_geometry_get(m_viewWidget, 0, 0, &width, &height); return IntSize(width, height); } diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h index 01a2483c7..2522153d4 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h @@ -33,13 +33,13 @@ namespace WebKit { class PageClientImpl : public PageClient { public: - static PassOwnPtr<PageClientImpl> create(WebContext* context, WebPageGroup* pageGroup, Evas_Object* viewObject) + static PassOwnPtr<PageClientImpl> create(WebContext* context, WebPageGroup* pageGroup, Evas_Object* viewWidget) { - return adoptPtr(new PageClientImpl(context, pageGroup, viewObject)); + return adoptPtr(new PageClientImpl(context, pageGroup, viewWidget)); } ~PageClientImpl(); - Evas_Object* viewObject() const { return m_viewObject; } + Evas_Object* viewWidget() const { return m_viewWidget; } WebPageProxy* page() const { return m_page.get(); } @@ -100,7 +100,7 @@ private: private: RefPtr<WebPageProxy> m_page; - Evas_Object* m_viewObject; + Evas_Object* m_viewWidget; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_private.h new file mode 100644 index 000000000..d331d996f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/efl/ewk_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 ewk_private_h +#define ewk_private_h + +#include <Evas.h> + +namespace WebCore { +class IntRect; +class IntSize; +} + +void ewk_view_display(Evas_Object* ewkView, const WebCore::IntRect& rect); +void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const WebCore::IntSize& size); + +#endif // ewk_private_h diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp index 592f58034..269c072d6 100644 --- a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp +++ b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp @@ -479,7 +479,7 @@ Evas_Object* ewk_view_add(Evas* canvas, WKContextRef contextRef, WKPageGroupRef return 0; } - priv->pageClient = PageClientImpl::create(toImpl(contextRef), toImpl(pageGroupRef), smartData->image); + priv->pageClient = PageClientImpl::create(toImpl(contextRef), toImpl(pageGroupRef), ewkView); return ewkView; } @@ -491,3 +491,23 @@ WKPageRef ewk_view_page_get(Evas_Object* ewkView) return toAPI(priv->pageClient->page()); } + +void ewk_view_display(Evas_Object* ewkView, const IntRect& rect) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + if (!smartData->image) + return; + + evas_object_image_data_update_add(smartData->image, rect.x(), rect.y(), rect.width(), rect.height()); +} + +void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const IntSize& size) +{ + EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData); + if (!imageData || !smartData->image) + return; + + evas_object_resize(smartData->image, size.width(), size.height()); + evas_object_image_size_set(smartData->image, size.width(), size.height()); + evas_object_image_data_copy_set(smartData->image, imageData); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp index fab54fb21..1caca868e 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp @@ -22,7 +22,7 @@ #include "WebKitBackForwardListPrivate.h" #include "WebKitMarshal.h" -#include <WebKit2/WKBackForwardList.h> +#include "WebKitPrivate.h" #include <wtf/gobject/GRefPtr.h> /** diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp index ed44f1f1e..c6a4b598c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardListItem.cpp @@ -21,8 +21,7 @@ #include "WebKitBackForwardListItem.h" #include "WebKitBackForwardListPrivate.h" -#include <WebKit2/WKBackForwardListItem.h> -#include <WebKit2/WKRetainPtr.h> +#include "WebKitPrivate.h" #include <wtf/HashMap.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp new file mode 100644 index 000000000..4d4eba18d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.cpp @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitDownload.h" + +#include "WebKitDownloadPrivate.h" +#include "WebKitMarshal.h" +#include "WebKitURIResponsePrivate.h" +#include <WebCore/ErrorsGtk.h> +#include <WebCore/ResourceResponse.h> +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> + +using namespace WebKit; +using namespace WebCore; + +enum { + RECEIVED_DATA, + FINISHED, + FAILED, + DECIDE_DESTINATION, + CREATED_DESTINATION, + + LAST_SIGNAL +}; + +enum { + PROP_0, + + PROP_DESTINATION, + PROP_RESPONSE, + PROP_ESTIMATED_PROGRESS +}; + +struct _WebKitDownloadPrivate { + WKRetainPtr<WKDownloadRef> wkDownload; + + GRefPtr<WebKitURIResponse> response; + CString destinationURI; + guint64 currentSize; + bool isCancelled; + GOwnPtr<GTimer> timer; + gdouble lastProgress; + gdouble lastElapsed; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitDownload, webkit_download, G_TYPE_OBJECT) + +static void webkitDownloadFinalize(GObject* object) +{ + WEBKIT_DOWNLOAD(object)->priv->~WebKitDownloadPrivate(); + G_OBJECT_CLASS(webkit_download_parent_class)->finalize(object); +} + +static void webkitDownloadGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitDownload* download = WEBKIT_DOWNLOAD(object); + + switch (propId) { + case PROP_DESTINATION: + g_value_set_string(value, webkit_download_get_destination(download)); + break; + case PROP_RESPONSE: + g_value_set_object(value, webkit_download_get_response(download)); + break; + case PROP_ESTIMATED_PROGRESS: + g_value_set_double(value, webkit_download_get_estimated_progress(download)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + } +} + +static gboolean webkitDownloadDecideDestination(WebKitDownload* download, const gchar* suggestedFilename) +{ + if (!download->priv->destinationURI.isNull()) + return FALSE; + GOwnPtr<char> destination(g_build_filename(g_get_user_special_dir(G_USER_DIRECTORY_DOWNLOAD), suggestedFilename, NULL)); + GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); + download->priv->destinationURI = destinationURI.get(); + g_object_notify(G_OBJECT(download), "destination"); + return TRUE; +} + +static void webkit_download_init(WebKitDownload* download) +{ + WebKitDownloadPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(download, WEBKIT_TYPE_DOWNLOAD, WebKitDownloadPrivate); + download->priv = priv; + new (priv) WebKitDownloadPrivate(); +} + +static void webkit_download_class_init(WebKitDownloadClass* downloadClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(downloadClass); + objectClass->get_property = webkitDownloadGetProperty; + objectClass->finalize = webkitDownloadFinalize; + + downloadClass->decide_destination = webkitDownloadDecideDestination; + + /** + * WebKitDownload:destination: + * + * The local URI to where the download will be saved. + */ + g_object_class_install_property(objectClass, + PROP_DESTINATION, + g_param_spec_string("destination", + _("Destination"), + _("The local URI to where the download will be saved"), + 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:response: + * + * The #WebKitURIResponse associated with this download. + */ + g_object_class_install_property(objectClass, + PROP_RESPONSE, + g_param_spec_object("response", + _("Response"), + _("The response of the download"), + WEBKIT_TYPE_URI_RESPONSE, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload:estimated-progress: + * + * An estimate of the percent completion for the download operation. + * This value will range from 0.0 to 1.0. The value is an estimate + * based on the total number of bytes expected to be received for + * a download. + * If you need a more accurate progress information you can connect to + * #WebKitDownload::received-data signal to track the progress. + */ + g_object_class_install_property(objectClass, + PROP_ESTIMATED_PROGRESS, + g_param_spec_double("estimated-progress", + _("Estimated Progress"), + _("Determines the current progress of the download"), + 0.0, 1.0, 1.0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitDownload::received-data: + * @download: the #WebKitDownload + * @data_length: the length of data received in bytes + * + * This signal is emitted after response is received, + * every time new data has been written to the destination. It's + * useful to know the progress of the download operation. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[RECEIVED_DATA] = + g_signal_new("received-data", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, received_data), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__UINT64, + G_TYPE_BOOLEAN, 1, + G_TYPE_UINT64); + + /** + * WebKitDownload::finished: + * @download: the #WebKitDownload + * + * This signal is emitted when download finishes successfully or due to an error. + * In case of errors #WebKitDownload::failed signal is emitted before this one. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[FINISHED] = + g_signal_new("finished", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, finished), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitDownload::failed: + * @download: the #WebKitDownload + * @error: the #GError that was triggered + * + * This signal is emitted when an error occurs during the download + * operation. The given @error, of the domain %WEBKIT_DOWNLOAD_ERROR, + * contains further details of the failure. If the download is cancelled + * with webkit_download_cancel(), this signal is emitted with error + * %WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER. The download operation finishes + * after an error and #WebKitDownload::finished signal is emitted after this one. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[FAILED] = + g_signal_new("failed", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, failed), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + /** + * WebKitDownload::decide-destination: + * @download: the #WebKitDownload + * @suggested_filename: the filename suggested for the download + * + * This signal is emitted after response is received to + * decide a destination URI for the download. If this signal is not + * handled the file will be downloaded to %G_USER_DIRECTORY_DOWNLOAD + * directory using @suggested_filename. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[DECIDE_DESTINATION] = + g_signal_new("decide-destination", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, decide_destination), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + /** + * WebKitDownload::created-destination: + * @download: the #WebKitDownload + * @destination: the destination URI + * + * This signal is emitted after #WebKitDownload::decide-destination and before + * #WebKitDownload::received-data to notify that destination file has been + * created successfully at @destination. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[CREATED_DESTINATION] = + g_signal_new("created-destination", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitDownloadClass, created_destination), + g_signal_accumulator_true_handled, NULL, + webkit_marshal_BOOLEAN__STRING, + G_TYPE_BOOLEAN, 1, + G_TYPE_STRING); + + g_type_class_add_private(downloadClass, sizeof(WebKitDownloadPrivate)); +} + +WebKitDownload* webkitDownloadCreate(WKDownloadRef wkDownload) +{ + ASSERT(wkDownload); + WebKitDownload* download = WEBKIT_DOWNLOAD(g_object_new(WEBKIT_TYPE_DOWNLOAD, NULL)); + download->priv->wkDownload = wkDownload; + return download; +} + +void webkitDownloadSetResponse(WebKitDownload* download, WebKitURIResponse* response) +{ + download->priv->response = response; + g_object_notify(G_OBJECT(download), "response"); +} + +bool webkitDownloadIsCancelled(WebKitDownload* download) +{ + return download->priv->isCancelled; +} + +void webkitDownloadNotifyProgress(WebKitDownload* download, guint64 bytesReceived) +{ + WebKitDownloadPrivate* priv = download->priv; + if (priv->isCancelled) + return; + + if (!download->priv->timer) + download->priv->timer.set(g_timer_new()); + + priv->currentSize += bytesReceived; + gboolean returnValue; + g_signal_emit(download, signals[RECEIVED_DATA], 0, bytesReceived, &returnValue); + + // Throttle progress notification to not consume high amounts of + // CPU on fast links, except when the last notification occured + // more than 0.016 secs ago (60 FPS), or the last notified progress + // is passed in 1% or we reached the end. + gdouble currentElapsed = g_timer_elapsed(priv->timer.get(), 0); + gdouble currentProgress = webkit_download_get_estimated_progress(download); + + if (priv->lastElapsed + && priv->lastProgress + && (currentElapsed - priv->lastElapsed) < 0.016 + && (currentProgress - priv->lastProgress) < 0.01 + && currentProgress < 1.0) { + return; + } + priv->lastElapsed = currentElapsed; + priv->lastProgress = currentProgress; + g_object_notify(G_OBJECT(download), "estimated-progress"); +} + +void webkitDownloadFailed(WebKitDownload* download, const ResourceError& resourceError) +{ + GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), + resourceError.errorCode(), + resourceError.localizedDescription().utf8().data())); + if (download->priv->timer) + g_timer_stop(download->priv->timer.get()); + gboolean returnValue; + g_signal_emit(download, signals[FAILED], 0, webError.get(), &returnValue); + g_signal_emit(download, signals[FINISHED], 0, &returnValue); +} + +void webkitDownloadCancelled(WebKitDownload* download) +{ + WebKitDownloadPrivate* priv = download->priv; + webkitDownloadFailed(download, downloadCancelledByUserError(priv->response ? webkitURIResponseGetResourceResponse(priv->response.get()) : ResourceResponse())); +} + +void webkitDownloadFinished(WebKitDownload* download) +{ + if (download->priv->isCancelled) { + // Since cancellation is asynchronous, didFinish might be called even + // if the download was cancelled. User cancelled the download, + // so we should fail with cancelled error even if the download + // actually finished successfully. + webkitDownloadCancelled(download); + return; + } + if (download->priv->timer) + g_timer_stop(download->priv->timer.get()); + gboolean returnValue; + g_signal_emit(download, signals[FINISHED], 0, &returnValue); +} + +CString webkitDownloadDecideDestinationWithSuggestedFilename(WebKitDownload* download, const CString& suggestedFilename) +{ + if (download->priv->isCancelled) + return ""; + gboolean returnValue; + g_signal_emit(download, signals[DECIDE_DESTINATION], 0, suggestedFilename.data(), &returnValue); + return download->priv->destinationURI; +} + +void webkitDownloadDestinationCreated(WebKitDownload* download, const CString& destinationURI) +{ + if (download->priv->isCancelled) + return; + gboolean returnValue; + g_signal_emit(download, signals[CREATED_DESTINATION], 0, destinationURI.data(), &returnValue); +} + +/** + * webkit_download_get_destination: + * @download: a #WebKitDownload + * + * Obtains the URI to which the downloaded file will be written. You + * can connect to #WebKitDownload::created-destination to make + * sure this method returns a valid destination. + * + * Returns: the destination URI or %NULL + */ +const gchar* webkit_download_get_destination(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + return download->priv->destinationURI.data(); +} + +/** + * webkit_download_set_destination: + * @download: a #WebKitDownload + * @uri: the destination URI + * + * Sets the URI to which the downloaded file will be written. + * This method should be called before the download transfer + * starts or it will not have any effect on the ongoing download + * operation. To set the destination using the filename suggested + * by the server connect to #WebKitDownload::decide-destination + * signal and call webkit_download_set_destination(). If you want to + * set a fixed destination URI that doesn't depend on the suggested + * filename you can connect to notify::response signal and call + * webkit_download_set_destination(). + * If #WebKitDownload::decide-destination signal is not handled + * and destination URI is not set when the download tranfer starts, + * the file will be saved with the filename suggested by the server in + * %G_USER_DIRECTORY_DOWNLOAD directory. + */ +void webkit_download_set_destination(WebKitDownload* download, const gchar* uri) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + g_return_if_fail(uri); + + WebKitDownloadPrivate* priv = download->priv; + if (priv->destinationURI == uri) + return; + + priv->destinationURI = uri; + g_object_notify(G_OBJECT(download), "destination"); +} + +/** + * webkit_download_get_response: + * @download: a #WebKitDownload + * + * Retrieves the #WebKitURIResponse object that backs the download + * process. This method returns %NULL if called before the response + * is received from the server. You can connect to notify::response + * signal to be notified when the response is received. + * + * Returns: (transfer none): the #WebKitURIResponse, or %NULL if + * the response hasn't been received yet. + */ +WebKitURIResponse* webkit_download_get_response(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + return download->priv->response.get(); +} + +/** + * webkit_download_cancel: + * @download: a #WebKitDownload + * + * Cancels the download. When the ongoing download + * operation is effectively cancelled the signal + * #WebKitDownload::failed is emitted with + * %WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER error. + */ +void webkit_download_cancel(WebKitDownload* download) +{ + g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); + + download->priv->isCancelled = true; + WKDownloadCancel(download->priv->wkDownload.get()); +} + +/** + * webkit_download_get_estimated_progress: + * @download: a #WebKitDownload + * + * Gets the value of the #WebKitDownload:estimated-progress property. + * You can monitor the estimated progress of the download operation by + * connecting to the notify::estimated-progress signal of @download. + * + * Returns: an estimate of the of the percent complete for a download + * as a range from 0.0 to 1.0. + */ +gdouble webkit_download_get_estimated_progress(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + WebKitDownloadPrivate* priv = download->priv; + if (!priv->response) + return 0; + + guint64 contentLength = webkit_uri_response_get_content_length(priv->response.get()); + if (!contentLength) + return 0; + + return static_cast<gdouble>(priv->currentSize) / static_cast<gdouble>(contentLength); +} + +/** + * webkit_download_get_elapsed_time: + * @download: a #WebKitDownload + * + * Gets the elapsed time in seconds, including any fractional part. + * If the download finished, had an error or was cancelled this is + * the time between its start and the event. + * + * Returns: seconds since the download was started + */ +gdouble webkit_download_get_elapsed_time(WebKitDownload* download) +{ + g_return_val_if_fail(WEBKIT_IS_DOWNLOAD(download), 0); + + WebKitDownloadPrivate* priv = download->priv; + if (!priv->timer) + return 0; + + return g_timer_elapsed(priv->timer.get(), 0); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.h new file mode 100644 index 000000000..e200fec53 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownload.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitDownload_h +#define WebKitDownload_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitURIResponse.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_DOWNLOAD (webkit_download_get_type()) +#define WEBKIT_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownload)) +#define WEBKIT_IS_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOWNLOAD)) +#define WEBKIT_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadClass)) +#define WEBKIT_IS_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOWNLOAD)) +#define WEBKIT_DOWNLOAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadClass)) + +typedef struct _WebKitDownload WebKitDownload; +typedef struct _WebKitDownloadClass WebKitDownloadClass; +typedef struct _WebKitDownloadPrivate WebKitDownloadPrivate; + +struct _WebKitDownload { + GObject parent; + + WebKitDownloadPrivate *priv; +}; + +struct _WebKitDownloadClass { + GObjectClass parent_class; + + gboolean (* received_data) (WebKitDownload *download, + guint64 data_length); + gboolean (* finished) (WebKitDownload *download); + gboolean (* failed) (WebKitDownload *download, + GError *error); + gboolean (* decide_destination) (WebKitDownload *download, + const gchar *suggested_filename); + gboolean (* created_destination) (WebKitDownload *download, + const gchar *destination); +}; + +WEBKIT_API GType +webkit_download_get_type (void); + +WEBKIT_API const gchar * +webkit_download_get_destination (WebKitDownload *download); + +WEBKIT_API void +webkit_download_set_destination (WebKitDownload *download, + const gchar *uri); + +WEBKIT_API WebKitURIResponse* +webkit_download_get_response (WebKitDownload *download); + +WEBKIT_API void +webkit_download_cancel (WebKitDownload *download); + +WEBKIT_API gdouble +webkit_download_get_estimated_progress (WebKitDownload *download); + +WEBKIT_API gdouble +webkit_download_get_elapsed_time (WebKitDownload *download); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp new file mode 100644 index 000000000..6e72496ef --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitDownloadClient.h" + +#include "WebContext.h" +#include "WebKitDownloadPrivate.h" +#include "WebKitURIResponsePrivate.h" +#include "WebKitWebContextPrivate.h" +#include "WebURLResponse.h" +#include <WebKit2/WKString.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebCore; +using namespace WebKit; + +static void didStart(WKContextRef, WKDownloadRef wkDownload, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitWebContextDownloadStarted(WEBKIT_WEB_CONTEXT(clientInfo), download.get()); +} + +static void didReceiveResponse(WKContextRef, WKDownloadRef wkDownload, WKURLResponseRef wkResponse, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + if (webkitDownloadIsCancelled(download.get())) + return; + + GRefPtr<WebKitURIResponse> response = adoptGRef(webkitURIResponseCreateForResourceResponse(toImpl(wkResponse)->resourceResponse())); + webkitDownloadSetResponse(download.get(), response.get()); +} + +static void didReceiveData(WKContextRef, WKDownloadRef wkDownload, uint64_t length, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadNotifyProgress(download.get(), length); +} + +static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownloadRef wkDownload, WKStringRef filename, bool* allowOverwrite, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + CString destinationURI = webkitDownloadDecideDestinationWithSuggestedFilename(download.get(), + toImpl(filename)->string().utf8()); + return WKStringCreateWithUTF8CString(destinationURI.data()); +} + +static void didCreateDestination(WKContextRef, WKDownloadRef wkDownload, WKStringRef path, const void* clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadDestinationCreated(download.get(), toImpl(path)->string().utf8()); +} + +static void didFail(WKContextRef, WKDownloadRef wkDownload, WKErrorRef error, const void *clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + if (webkitDownloadIsCancelled(download.get())) { + // Cancellation takes precedence over other errors. + webkitDownloadCancelled(download.get()); + } else + webkitDownloadFailed(download.get(), toImpl(error)->platformError()); + webkitWebContextRemoveDownload(wkDownload); +} + +static void didCancel(WKContextRef, WKDownloadRef wkDownload, const void *clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadCancelled(download.get()); + webkitWebContextRemoveDownload(wkDownload); +} + +static void didFinish(WKContextRef wkContext, WKDownloadRef wkDownload, const void *clientInfo) +{ + GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(wkDownload); + webkitDownloadFinished(download.get()); + webkitWebContextRemoveDownload(wkDownload); +} + +void attachDownloadClientToContext(WebKitWebContext* webContext) +{ + WKContextDownloadClient wkDownloadClient = { + kWKContextDownloadClientCurrentVersion, + webContext, // ClientInfo + didStart, + 0, // didReceiveAuthenticationChallenge + didReceiveResponse, + didReceiveData, + 0, // shouldDecodeSourceDataOfMIMEType + decideDestinationWithSuggestedFilename, + didCreateDestination, + didFinish, + didFail, + didCancel, + 0, // processDidCrash + }; + WKContextSetDownloadClient(webkitWebContextGetWKContext(webContext), &wkDownloadClient); +} + diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.h new file mode 100644 index 000000000..c2566e897 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadClient.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitDownloadClient_h +#define WebKitDownloadClient_h + +#include "WebKitWebContext.h" + +void attachDownloadClientToContext(WebKitWebContext*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadPrivate.h new file mode 100644 index 000000000..6f4b5363c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDownloadPrivate.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitDownloadPrivate_h +#define WebKitDownloadPrivate_h + +#include "WebKitDownload.h" +#include "WebKitPrivate.h" +#include <WebCore/ResourceError.h> +#include <wtf/text/CString.h> + +WebKitDownload* webkitDownloadCreate(WKDownloadRef); +bool webkitDownloadIsCancelled(WebKitDownload*); +void webkitDownloadSetResponse(WebKitDownload*, WebKitURIResponse*); +void webkitDownloadNotifyProgress(WebKitDownload*, guint64 bytesReceived); +void webkitDownloadFailed(WebKitDownload*, const WebCore::ResourceError&); +void webkitDownloadCancelled(WebKitDownload*); +void webkitDownloadFinished(WebKitDownload*); +CString webkitDownloadDecideDestinationWithSuggestedFilename(WebKitDownload*, const CString& suggestedFilename); +void webkitDownloadDestinationCreated(WebKitDownload*, const CString& destinationURI); + +#endif // WebKitDownloadPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp index 6c24aa12e..42cf0ab35 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp @@ -24,6 +24,8 @@ #include "WebKitPrivate.h" #include <WebCore/ErrorsGtk.h> +using namespace WebCore; + GQuark webkit_network_error_quark() { return g_quark_from_static_string(WebCore::errorDomainNetwork); @@ -57,3 +59,12 @@ COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_CANNOT_LOAD_PLUGIN, PluginError COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_JAVA_UNAVAILABLE, PluginErrorJavaUnavailable); COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_CONNECTION_CANCELLED, PluginErrorConnectionCancelled); COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD, PluginErrorWillHandleLoad); + +GQuark webkit_download_error_quark() +{ + return g_quark_from_static_string(WebCore::errorDomainDownload); +} + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_NETWORK, DownloadErrorNetwork); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER, DownloadErrorCancelledByUser); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_DESTINATION, DownloadErrorDestination); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h index 3ce0e20f1..9b0e630c8 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h @@ -32,6 +32,7 @@ G_BEGIN_DECLS #define WEBKIT_NETWORK_ERROR webkit_network_error_quark () #define WEBKIT_POLICY_ERROR webkit_policy_error_quark () #define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () +#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () /** * WebKitNetworkError: @@ -89,14 +90,31 @@ typedef enum { WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD = 204, } WebKitPluginError; +/** + * WebKitDownloadError: + * @WEBKIT_DOWNLOAD_ERROR_NETWORK: Download failure due to network error + * @WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER: Download was cancelled by user + * @WEBKIT_DOWNLOAD_ERROR_DESTINATION: Download failure due to destination error + * + * Enum values used to denote the various download errors. + */ +typedef enum { + WEBKIT_DOWNLOAD_ERROR_NETWORK = 499, + WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER = 400, + WEBKIT_DOWNLOAD_ERROR_DESTINATION = 401 +} WebKitDownloadError; + +WEBKIT_API GQuark +webkit_network_error_quark (void); + WEBKIT_API GQuark -webkit_network_error_quark (void); +webkit_policy_error_quark (void); WEBKIT_API GQuark -webkit_policy_error_quark (void); +webkit_plugin_error_quark (void); WEBKIT_API GQuark -webkit_plugin_error_quark (void); +webkit_download_error_quark (void); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp index d27560f53..6d1133941 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp @@ -19,9 +19,10 @@ */ #include "config.h" -#include "WebKitWebLoaderClient.h" +#include "WebKitLoaderClient.h" #include "WebKitBackForwardListPrivate.h" +#include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include <wtf/gobject/GOwnPtr.h> #include <wtf/text/CString.h> @@ -29,14 +30,12 @@ using namespace WebKit; using namespace WebCore; -G_DEFINE_TYPE(WebKitWebLoaderClient, webkit_web_loader_client, G_TYPE_OBJECT) - static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) { if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_STARTED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_STARTED); } static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) @@ -44,7 +43,7 @@ static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, W if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_REDIRECTED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_REDIRECTED); } static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void* clientInfo) @@ -56,7 +55,7 @@ static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef f GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), resourceError.errorCode(), resourceError.localizedDescription().utf8().data())); - webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_STARTED, + webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_STARTED, resourceError.failingURL().utf8().data(), webError.get()); } @@ -65,7 +64,7 @@ static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_COMMITTED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_COMMITTED); } static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) @@ -73,7 +72,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_FINISHED); + webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_FINISHED); } static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef, const void* clientInfo) @@ -85,43 +84,41 @@ static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErr GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), resourceError.errorCode(), resourceError.localizedDescription().utf8().data())); - webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), WEBKIT_LOAD_COMMITTED, + webkitWebViewLoadFailed(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_COMMITTED, resourceError.failingURL().utf8().data(), webError.get()); } -static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType, WKTypeRef, const void*) +static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType, WKTypeRef, const void* clientInfo) { if (!WKFrameIsMainFrame(frame)) return; - webkitWebViewUpdateURI(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + webkitWebViewUpdateURI(WEBKIT_WEB_VIEW(clientInfo)); } -static void didReceiveTitleForFrame(WKPageRef page, WKStringRef titleRef, WKFrameRef frameRef, WKTypeRef, const void*) +static void didReceiveTitleForFrame(WKPageRef page, WKStringRef titleRef, WKFrameRef frameRef, WKTypeRef, const void* clientInfo) { if (!WKFrameIsMainFrame(frameRef)) return; - webkitWebViewSetTitle(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(titleRef)->string().utf8()); + webkitWebViewSetTitle(WEBKIT_WEB_VIEW(clientInfo), toImpl(titleRef)->string().utf8()); } static void didChangeProgress(WKPageRef page, const void* clientInfo) { - WebKitWebView* webView = WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()); - webkitWebViewSetEstimatedLoadProgress(webView, WKPageGetEstimatedProgress(page)); + webkitWebViewSetEstimatedLoadProgress(WEBKIT_WEB_VIEW(clientInfo), WKPageGetEstimatedProgress(page)); } static void didChangeBackForwardList(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void* clientInfo) { - WebKitWebView* webView = WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()); - webkitBackForwardListChanged(webkit_web_view_get_back_forward_list(webView), addedItem, removedItems); + webkitBackForwardListChanged(webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(clientInfo)), addedItem, removedItems); } -void webkitWebLoaderClientAttachLoaderClientToPage(WebKitWebLoaderClient* loaderClient, WKPageRef wkPage) +void attachLoaderClientToView(WebKitWebView* webView) { WKPageLoaderClient wkLoaderClient = { kWKPageLoaderClientCurrentVersion, - loaderClient, // clientInfo + webView, // clientInfo didStartProvisionalLoadForFrame, didReceiveServerRedirectForProvisionalLoadForFrame, didFailProvisionalLoadWithErrorForFrame, @@ -149,13 +146,7 @@ void webkitWebLoaderClientAttachLoaderClientToPage(WebKitWebLoaderClient* loader 0, // didFailToInitializePlugin 0 // didDetectXSSForFrame }; + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); WKPageSetPageLoaderClient(wkPage, &wkLoaderClient); } -static void webkit_web_loader_client_init(WebKitWebLoaderClient*) -{ -} - -static void webkit_web_loader_client_class_init(WebKitWebLoaderClientClass*) -{ -} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h new file mode 100644 index 000000000..dfac3c86f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitLoaderClient_h +#define WebKitLoaderClient_h + +#include "WebKitWebView.h" + +void attachLoaderClientToView(WebKitWebView*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.cpp new file mode 100644 index 000000000..fcd57b4a6 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitNavigationPolicyDecision.h" + +#include "WebKitEnumTypes.h" +#include "WebKitPolicyDecisionPrivate.h" +#include "WebKitPrivate.h" +#include "WebKitURIRequestPrivate.h" +#include "WebURLRequest.h" +#include <gdk/gdk.h> +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +/** + * SECTION: WebKitNavigationPolicyDecision + * @Short_description: A policy decision for navigation actions + * @Title: WebKitNavigationPolicyDecision + * @See_also: #WebKitPolicyDecision, #WebKitWebView + * + * WebKitNavigationPolicyDecision represents a policy decision for events associated with + * navigations. If the value of WebKitNavigationPolicyDecision:mouse-button is not 0, then + * the navigation was triggered by a mouse event. + */ + +G_DEFINE_TYPE(WebKitNavigationPolicyDecision, webkit_navigation_policy_decision, WEBKIT_TYPE_POLICY_DECISION) + +struct _WebKitNavigationPolicyDecisionPrivate { + WebKitNavigationType navigationType; + unsigned modifiers; + unsigned mouseButton; + GRefPtr<WebKitURIRequest> request; + CString frameName; +}; + +enum { + PROP_0, + PROP_NAVIGATION_TYPE, + PROP_MOUSE_BUTTON, + PROP_MODIFIERS, + PROP_REQUEST, + PROP_FRAME_NAME, +}; + +static void webkit_navigation_policy_decision_init(WebKitNavigationPolicyDecision* decision) +{ + decision->priv = G_TYPE_INSTANCE_GET_PRIVATE(decision, WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecisionPrivate); + new (decision->priv) WebKitNavigationPolicyDecisionPrivate(); +} + +static void webkitNavigationPolicyDecisionFinalize(GObject* object) +{ + WEBKIT_NAVIGATION_POLICY_DECISION(object)->priv->~WebKitNavigationPolicyDecisionPrivate(); + G_OBJECT_CLASS(webkit_navigation_policy_decision_parent_class)->finalize(object); +} + +static void webkitNavigationPolicyDecisionGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(object); + switch (propId) { + case PROP_NAVIGATION_TYPE: + g_value_set_enum(value, webkit_navigation_policy_decision_get_navigation_type(decision)); + break; + case PROP_MOUSE_BUTTON: + g_value_set_enum(value, webkit_navigation_policy_decision_get_mouse_button(decision)); + break; + case PROP_MODIFIERS: + g_value_set_uint(value, webkit_navigation_policy_decision_get_modifiers(decision)); + break; + case PROP_REQUEST: + g_value_set_object(value, webkit_navigation_policy_decision_get_request(decision)); + break; + case PROP_FRAME_NAME: + g_value_set_string(value, webkit_navigation_policy_decision_get_frame_name(decision)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + break; + } +} + +static void webkit_navigation_policy_decision_class_init(WebKitNavigationPolicyDecisionClass* decisionClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(decisionClass); + objectClass->finalize = webkitNavigationPolicyDecisionFinalize; + objectClass->get_property = webkitNavigationPolicyDecisionGetProperty; + g_type_class_add_private(decisionClass, sizeof(WebKitNavigationPolicyDecisionPrivate)); + + /** + * WebKitNavigationPolicyDecision:navigation-type: + * + * The type of navigation that triggered this policy decision. This is + * useful for enacting different policies depending on what type of user + * action caused the navigation. + */ + g_object_class_install_property(objectClass, + PROP_NAVIGATION_TYPE, + g_param_spec_enum("navigation-type", + _("Navigation type"), + _("The type of navigation triggering this decision"), + WEBKIT_TYPE_NAVIGATION_TYPE, + WEBKIT_NAVIGATION_TYPE_LINK_CLICKED, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:mouse-button: + * + * If the navigation associated with this policy decision was originally + * triggered by a mouse event, this property contains non-zero button number + * of the button triggering that event. The button numbers match those from GDK. + * If the navigation was not triggered by a mouse event, the value of this + * property will be 0. + */ + g_object_class_install_property(objectClass, + PROP_MOUSE_BUTTON, + g_param_spec_uint("mouse-button", + _("Mouse button"), + _("The mouse button used if this decision was triggered by a mouse event"), + 0, G_MAXUINT, 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:modifiers: + * + * If the navigation associated with this policy decision was originally + * triggered by a mouse event, this property contains a bitmask of various + * GdkModifierType values describing the modifiers used for that click. + * If the navigation was not triggered by a mouse event or no modifiers + * were active, the value of this property will be zero. + */ + g_object_class_install_property(objectClass, + PROP_MODIFIERS, + g_param_spec_uint("modifiers", + _("Mouse event modifiers"), + _("The modifiers active if this decision was triggered by a mouse event"), + 0, G_MAXUINT, 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:request: + * + * This property contains the #WebKitURIRequest associated with this + * navigation. + */ + g_object_class_install_property(objectClass, + PROP_REQUEST, + g_param_spec_object("request", + _("Navigation URI request"), + _("The URI request that is associated with this navigation"), + WEBKIT_TYPE_URI_REQUEST, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitNavigationPolicyDecision:frame-name: + * + * If this navigation request targets a new frame, this property contains + * the name of that frame. For example if the decision was triggered by clicking a + * link with a target attribute equal to "_blank", this property will contain the + * value of that attribute. In all other cases, this value will be %NULL. + */ + g_object_class_install_property(objectClass, + PROP_FRAME_NAME, + g_param_spec_string("frame-name", + _("Frame name"), + _("The name of the new frame this navigation action targets"), + 0, + WEBKIT_PARAM_READABLE)); +} + +/** + * webkit_navigation_policy_decision_get_navigation_type: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:navigation-type property. + * + * Returns: The type of navigation triggering this policy decision. + */ +WebKitNavigationType webkit_navigation_policy_decision_get_navigation_type(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), WEBKIT_NAVIGATION_TYPE_OTHER); + return decision->priv->navigationType; +} + +/** + * webkit_navigation_policy_decision_get_mouse_button: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:mouse-button property. + * + * Returns: The mouse button used if this decision was triggered by a mouse event or 0 otherwise + */ +guint webkit_navigation_policy_decision_get_mouse_button(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->mouseButton; +} + +/** + * webkit_navigation_policy_decision_get_modifiers: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:modifiers property. + * + * Returns: The modifiers active if this decision was triggered by a mouse event + */ +unsigned webkit_navigation_policy_decision_get_modifiers(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->modifiers; +} + +/** + * webkit_navigation_policy_decision_get_request: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:request property. + * + * Returns: (transfer none): The URI request that is associated with this navigation + */ +WebKitURIRequest* webkit_navigation_policy_decision_get_request(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->request.get(); +} + +/** + * webkit_navigation_policy_decision_get_frame_name: + * @decision: a #WebKitNavigationPolicyDecision + * + * Gets the value of the #WebKitNavigationPolicyDecision:frame-name property. + * + * Returns: The name of the new frame this navigation action targets or %NULL + */ +const char* webkit_navigation_policy_decision_get_frame_name(WebKitNavigationPolicyDecision* decision) +{ + g_return_val_if_fail(WEBKIT_IS_NAVIGATION_POLICY_DECISION(decision), 0); + return decision->priv->frameName.data(); +} + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_LINK_CLICKED, kWKFrameNavigationTypeLinkClicked); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED, kWKFrameNavigationTypeFormSubmitted); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_BACK_FORWARD, kWKFrameNavigationTypeBackForward); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_RELOAD, kWKFrameNavigationTypeReload); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED, kWKFrameNavigationTypeFormResubmitted); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_NAVIGATION_TYPE_OTHER, kWKFrameNavigationTypeOther); + +static unsigned wkEventMouseButtonToWebKitMouseButton(WKEventMouseButton wkButton) +{ + switch (wkButton) { + case kWKEventMouseButtonNoButton: + return 0; + case kWKEventMouseButtonLeftButton: + return 1; + case kWKEventMouseButtonMiddleButton: + return 2; + case kWKEventMouseButtonRightButton: + return 3; + } + ASSERT_NOT_REACHED(); + return 0; +} + +unsigned wkEventModifiersToUnsigned(WKEventModifiers wkModifiers) +{ + unsigned modifiers = 0; + if (wkModifiers & kWKEventModifiersShiftKey) + modifiers |= GDK_SHIFT_MASK; + if (wkModifiers & kWKEventModifiersControlKey) + modifiers |= GDK_CONTROL_MASK; + if (wkModifiers & kWKEventModifiersAltKey) + modifiers |= GDK_MOD1_MASK; + if (wkModifiers & kWKEventModifiersMetaKey) + modifiers |= GDK_META_MASK; + return modifiers; +} + +WebKitNavigationPolicyDecision* webkitNavigationPolicyDecisionCreate(WKFrameNavigationType navigationType, WKEventMouseButton mouseButton, WKEventModifiers modifiers, WKURLRequestRef request, const char* frameName, WKFramePolicyListenerRef listener) +{ + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(g_object_new(WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, NULL)); + decision->priv->navigationType = static_cast<WebKitNavigationType>(navigationType); + decision->priv->mouseButton = wkEventMouseButtonToWebKitMouseButton(mouseButton); + decision->priv->modifiers = wkEventModifiersToUnsigned(modifiers); + decision->priv->request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(request)->resourceRequest())); + decision->priv->frameName = frameName; + webkitPolicyDecisionSetListener(WEBKIT_POLICY_DECISION(decision), listener); + return decision; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h new file mode 100644 index 000000000..bbf241268 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitNavigationPolicyDecision_h +#define WebKitNavigationPolicyDecision_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitPolicyDecision.h> +#include <webkit2/WebKitURIRequest.h> + +G_BEGIN_DECLS + +/** + * WebKitNavigationType: + * @WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: The navigation was triggered by clicking a link. + * @WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: The navigation was triggered by submitting a form. + * @WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: The navigation was triggered by navigating forward or backward. + * @WEBKIT_NAVIGATION_TYPE_RELOAD: The navigation was triggered by reloading. + * @WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED: The navigation was triggered by resubmitting a form. + * @WEBKIT_NAVIGATION_TYPE_OTHER: The navigation was triggered by some other action. + * + * Enum values used to denote the various navigation types. + */ +typedef enum { + WEBKIT_NAVIGATION_TYPE_LINK_CLICKED, + WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED, + WEBKIT_NAVIGATION_TYPE_BACK_FORWARD, + WEBKIT_NAVIGATION_TYPE_RELOAD, + WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED, + WEBKIT_NAVIGATION_TYPE_OTHER, +} WebKitNavigationType; + +#define WEBKIT_TYPE_NAVIGATION_POLICY_DECISION (webkit_navigation_policy_decision_get_type()) +#define WEBKIT_NAVIGATION_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecision)) +#define WEBKIT_NAVIGATION_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecisionClass)) +#define WEBKIT_IS_NAVIGATION_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION)) +#define WEBKIT_IS_NAVIGATION_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION)) +#define WEBKIT_NAVIGATION_POLICY_DECISION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_NAVIGATION_POLICY_DECISION, WebKitNavigationPolicyDecisionClass)) + +typedef struct _WebKitNavigationPolicyDecision WebKitNavigationPolicyDecision; +typedef struct _WebKitNavigationPolicyDecisionClass WebKitNavigationPolicyDecisionClass; +typedef struct _WebKitNavigationPolicyDecisionPrivate WebKitNavigationPolicyDecisionPrivate; + +struct _WebKitNavigationPolicyDecision { + WebKitPolicyDecision parent; + + /*< private >*/ + WebKitNavigationPolicyDecisionPrivate *priv; +}; + +struct _WebKitNavigationPolicyDecisionClass { + WebKitPolicyDecisionClass parent_class; +}; + +WEBKIT_API GType +webkit_navigation_policy_decision_get_type (void); + +WEBKIT_API WebKitNavigationType +webkit_navigation_policy_decision_get_navigation_type (WebKitNavigationPolicyDecision *decision); +WEBKIT_API guint +webkit_navigation_policy_decision_get_mouse_button (WebKitNavigationPolicyDecision *decision); +WEBKIT_API guint +webkit_navigation_policy_decision_get_modifiers (WebKitNavigationPolicyDecision *decision); +WEBKIT_API WebKitURIRequest * +webkit_navigation_policy_decision_get_request (WebKitNavigationPolicyDecision *decision); +WEBKIT_API const gchar * +webkit_navigation_policy_decision_get_frame_name (WebKitNavigationPolicyDecision *decision); +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecisionPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecisionPrivate.h new file mode 100644 index 000000000..f3c0e1f50 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitNavigationPolicyDecisionPrivate.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitNavigationPolicyDecisionPrivate_h +#define WebKitNavigationPolicyDecisionPrivate_h + +#include "WebKitNavigationPolicyDecision.h" +#include "WebKitPrivate.h" + +WebKitNavigationPolicyDecision* webkitNavigationPolicyDecisionCreate(WKFrameNavigationType, WKEventMouseButton, WKEventModifiers, WKURLRequestRef, const char* frameName, WKFramePolicyListenerRef); + +#endif // WebKitNavigationPolicyDecisionPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.cpp new file mode 100644 index 000000000..61757d428 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitPolicyClient.h" + +#include "WebKitNavigationPolicyDecisionPrivate.h" +#include "WebKitPolicyDecision.h" +#include "WebKitPrivate.h" +#include "WebKitWebViewBasePrivate.h" +#include "WebKitWebViewPrivate.h" +#include <wtf/gobject/GRefPtr.h> + +using namespace WebKit; + +static void decidePolicyForNavigationActionCallback(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) +{ + GRefPtr<WebKitNavigationPolicyDecision> decision = + adoptGRef(webkitNavigationPolicyDecisionCreate(navigationType, + mouseButton, + modifiers, + request, + 0, /* frame name */ + listener)); + webkitWebViewMakePolicyDecision(WEBKIT_WEB_VIEW(clientInfo), + WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION, + WEBKIT_POLICY_DECISION(decision.get())); +} + +static void decidePolicyForNewWindowActionCallback(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKStringRef frameName, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) +{ + GRefPtr<WebKitNavigationPolicyDecision> decision = + adoptGRef(webkitNavigationPolicyDecisionCreate(navigationType, + mouseButton, + modifiers, + request, + toImpl(frameName)->string().utf8().data(), + listener)); + webkitWebViewMakePolicyDecision(WEBKIT_WEB_VIEW(clientInfo), + WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION, + WEBKIT_POLICY_DECISION(decision.get())); +} + +void attachPolicyClientToPage(WebKitWebView* webView) +{ + WKPagePolicyClient policyClient = { + kWKPagePolicyClientCurrentVersion, + webView, // clientInfo + decidePolicyForNavigationActionCallback, + decidePolicyForNewWindowActionCallback, + 0, // decidePolicyForResponseCallback, + 0, // unableToImplementPolicy + }; + WKPageSetPagePolicyClient(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))), &policyClient); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.h new file mode 100644 index 000000000..90d8d62cc --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyClient.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitPolicyClient_h +#define WebKitPolicyClient_h + +#include "WebKitWebView.h" + +void attachPolicyClientToPage(WebKitWebView*); + +#endif // WebKitPolicyClient_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.cpp new file mode 100644 index 000000000..6b6759012 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitPolicyDecision.h" + +#include "WebKitPolicyDecisionPrivate.h" +#include "WebKitPrivate.h" + + +/** + * SECTION: WebKitPolicyDecision + * @Short_description: A pending policy decision + * @Title: WebKitPolicyDecision + * @See_also: #WebKitWebView + * + * Often WebKit allows the client to decide the policy for certain + * operations. For instance, a client may want to open a link in a new + * tab, block a navigation entirely, query the user or trigger a download + * instead of a navigation. In these cases WebKit will fire the + * #WebKitWebView::decide-policy signal with a #WebKitPolicyDecision + * object. If the signal handler does nothing, WebKit will act as if + * webkit_policy_decision_use() was called as soon as signal handling + * completes. To make a policy decision asynchronously, simply increment + * the reference count of the #WebKitPolicyDecision object. + */ +G_DEFINE_ABSTRACT_TYPE(WebKitPolicyDecision, webkit_policy_decision, G_TYPE_OBJECT) + +struct _WebKitPolicyDecisionPrivate { + WKRetainPtr<WKFramePolicyListenerRef> listener; + bool madePolicyDecision; +}; + +static void webkit_policy_decision_init(WebKitPolicyDecision* decision) +{ + decision->priv = G_TYPE_INSTANCE_GET_PRIVATE(decision, WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecisionPrivate); + new (decision->priv) WebKitPolicyDecisionPrivate(); + decision->priv->madePolicyDecision = false; +} + +static void webkitPolicyDecisionFinalize(GObject* object) +{ + WebKitPolicyDecisionPrivate* priv = WEBKIT_POLICY_DECISION(object)->priv; + + // This is the default choice for all policy decisions in WebPageProxy.cpp. + if (!priv->madePolicyDecision) + WKFramePolicyListenerUse(priv->listener.get()); + + priv->~WebKitPolicyDecisionPrivate(); + G_OBJECT_CLASS(webkit_policy_decision_parent_class)->finalize(object); +} + +void webkitPolicyDecisionSetListener(WebKitPolicyDecision* decision, WKFramePolicyListenerRef listener) +{ + decision->priv->listener = listener; +} + +static void webkit_policy_decision_class_init(WebKitPolicyDecisionClass* decisionClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(decisionClass); + objectClass->finalize = webkitPolicyDecisionFinalize; + g_type_class_add_private(decisionClass, sizeof(WebKitPolicyDecisionPrivate)); +} + +/** + * webkit_policy_decision_use: + * @decision: a #WebKitPolicyDecision + * + * Accept the action which triggerd this decision. + */ +void webkit_policy_decision_use(WebKitPolicyDecision* decision) +{ + g_return_if_fail(WEBKIT_IS_POLICY_DECISION(decision)); + WKFramePolicyListenerUse(decision->priv->listener.get()); + decision->priv->madePolicyDecision = true; +} + +/** + * webkit_policy_decision_ignore: + * @decision: a #WebKitPolicyDecision + * + * Ignore the action which triggerd this decision. For instance, for a + * #WebKitResponsePolicyDecision, this would cancel the request. + */ +void webkit_policy_decision_ignore(WebKitPolicyDecision* decision) +{ + g_return_if_fail(WEBKIT_IS_POLICY_DECISION(decision)); + WKFramePolicyListenerIgnore(decision->priv->listener.get()); + decision->priv->madePolicyDecision = true; +} + +/** + * webkit_policy_decision_download: + * @decision: a #WebKitPolicyDecision + * + * Spawn a download from this decision. + */ +void webkit_policy_decision_download(WebKitPolicyDecision* decision) +{ + g_return_if_fail(WEBKIT_IS_POLICY_DECISION(decision)); + WKFramePolicyListenerDownload(decision->priv->listener.get()); + decision->priv->madePolicyDecision = true; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.h new file mode 100644 index 000000000..ecca5f9c3 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecision.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitPolicyDecision_h +#define WebKitPolicyDecision_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_POLICY_DECISION (webkit_policy_decision_get_type()) +#define WEBKIT_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecision)) +#define WEBKIT_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecisionClass)) +#define WEBKIT_IS_POLICY_DECISION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_POLICY_DECISION)) +#define WEBKIT_IS_POLICY_DECISION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_POLICY_DECISION)) +#define WEBKIT_POLICY_DECISION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_POLICY_DECISION, WebKitPolicyDecisionClass)) + +typedef struct _WebKitPolicyDecision WebKitPolicyDecision; +typedef struct _WebKitPolicyDecisionClass WebKitPolicyDecisionClass; +typedef struct _WebKitPolicyDecisionPrivate WebKitPolicyDecisionPrivate; + +struct _WebKitPolicyDecision { + GObject parent; + + /*< private >*/ + WebKitPolicyDecisionPrivate *priv; +}; + +struct _WebKitPolicyDecisionClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_policy_decision_get_type (void); + +WEBKIT_API void +webkit_policy_decision_use (WebKitPolicyDecision *decision); + +WEBKIT_API void +webkit_policy_decision_ignore (WebKitPolicyDecision *decision); + +WEBKIT_API void +webkit_policy_decision_download (WebKitPolicyDecision *decision); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h new file mode 100644 index 000000000..62580c83e --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPolicyDecisionPrivate.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitPolicyDecisionPrivate_h +#define WebKitPolicyDecisionPrivate_h + +#include "WebKitPolicyDecision.h" +#include <WebKit2/WebKit2.h> + +void webkitPolicyDecisionSetListener(WebKitPolicyDecision*, WKFramePolicyListenerRef); + +#endif // WebKitResponsePolicyDecisionPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index 423c464b0..13280d600 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -26,18 +26,18 @@ #ifndef WebKitPrivate_h #define WebKitPrivate_h +#include <WebKit2/WKAPICast.h> +#include <WebKit2/WKDownload.h> +#include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WebKit2.h> #include <glib.h> #include <wtf/Assertions.h> -G_BEGIN_DECLS - #define WEBKIT_PARAM_READABLE (static_cast<GParamFlags>(G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)) #define WEBKIT_PARAM_WRITABLE (static_cast<GParamFlags>(G_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)) #define WEBKIT_PARAM_READWRITE (static_cast<GParamFlags>(G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)) #define COMPILE_ASSERT_MATCHING_ENUM(webkitName, webcoreName) \ - COMPILE_ASSERT(int(webkitName) == int(WebCore::webcoreName), mismatchingEnums) - -G_END_DECLS + COMPILE_ASSERT(int(webkitName) == int(webcoreName), mismatchingEnums) #endif // WebKitPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index 837a9a1e5..06418613d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -33,9 +33,6 @@ #include "WebKitPrivate.h" #include "WebKitSettingsPrivate.h" -#include <WebKit2/WKAPICast.h> -#include <WebKit2/WKString.h> -#include <WebKit2/WKRetainPtr.h> #include <glib/gi18n-lib.h> #include <wtf/text/CString.h> @@ -103,7 +100,8 @@ enum { PROP_ENABLE_TABS_TO_LINKS, PROP_ENABLE_DNS_PREFETCHING, PROP_ENABLE_CARET_BROWSING, - PROP_ENABLE_FULLSCREEN + PROP_ENABLE_FULLSCREEN, + PROP_PRINT_BACKGROUNDS }; static void webKitSettingsSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -201,6 +199,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu case PROP_ENABLE_FULLSCREEN: webkit_settings_set_enable_fullscreen(settings, g_value_get_boolean(value)); break; + case PROP_PRINT_BACKGROUNDS: + webkit_settings_set_print_backgrounds(settings, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -302,6 +303,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val case PROP_ENABLE_FULLSCREEN: g_value_set_boolean(value, webkit_settings_get_enable_fullscreen(settings)); break; + case PROP_PRINT_BACKGROUNDS: + g_value_set_boolean(value, webkit_settings_get_print_backgrounds(settings)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -751,6 +755,19 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) FALSE, readWriteConstructParamFlags)); + /** + * WebKitSettings:print-backgrounds: + * + * Whether background images should be drawn during printing. + */ + g_object_class_install_property(gObjectClass, + PROP_PRINT_BACKGROUNDS, + g_param_spec_boolean("print-backgrounds", + _("Print Backgrounds"), + _("Whether background images should be drawn during printing"), + TRUE, + readWriteConstructParamFlags)); + g_type_class_add_private(klass, sizeof(WebKitSettingsPrivate)); } @@ -1885,7 +1902,7 @@ gboolean webkit_settings_get_enable_fullscreen(WebKitSettings* settings) } /** - * webkit_settings_set_enable_fullscreen + * webkit_settings_set_enable_fullscreen: * @settings: a #WebKitSettings * @enabled: Value to be set * @@ -1903,3 +1920,38 @@ void webkit_settings_set_enable_fullscreen(WebKitSettings* settings, gboolean en WKPreferencesSetFullScreenEnabled(priv->preferences.get(), enabled); g_object_notify(G_OBJECT(settings), "enable-fullscreen"); } + +/** + * webkit_settings_get_print_backgrounds: + * @settings: a #WebKitSettings + * + * Get the #WebKitSettings:print-backgrounds property. + * + * Returns: %TRUE If background images should be printed or %FALSE otherwise. + */ +gboolean webkit_settings_get_print_backgrounds(WebKitSettings* settings) +{ + g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); + + return WKPreferencesGetShouldPrintBackgrounds(settings->priv->preferences.get()); +} + +/** + * webkit_settings_set_print_backgrounds: + * @settings: a #WebKitSettings + * @print_backgrounds: Value to be set + * + * Set the #WebKitSettings:print-backgrounds property. + */ +void webkit_settings_set_print_backgrounds(WebKitSettings* settings, gboolean printBackgrounds) +{ + g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); + + WebKitSettingsPrivate* priv = settings->priv; + bool currentValue = WKPreferencesGetShouldPrintBackgrounds(priv->preferences.get()); + if (currentValue == printBackgrounds) + return; + + WKPreferencesSetShouldPrintBackgrounds(priv->preferences.get(), printBackgrounds); + g_object_notify(G_OBJECT(settings), "print-backgrounds"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h index 8b19a465b..a6769fc0e 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h @@ -286,6 +286,13 @@ WEBKIT_API void webkit_settings_set_enable_fullscreen (WebKitSettings *settings, gboolean enabled); +WEBKIT_API gboolean +webkit_settings_get_print_backgrounds (WebKitSettings *settings); + +WEBKIT_API void +webkit_settings_set_print_backgrounds (WebKitSettings *settings, + gboolean print_backgrounds); + G_END_DECLS #endif /* WebKitSettings_h */ diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp index fcfdddb53..a659ad314 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Igalia S.L. + * Copyright (C) 2011, 2012 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,117 +20,117 @@ #include "config.h" #include "WebKitUIClient.h" +#include "WebKitPrivate.h" +#include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebPageProxy.h" -#include <WebKit2/WKBase.h> +#include <WebCore/GtkUtilities.h> using namespace WebKit; -G_DEFINE_TYPE(WebKitUIClient, webkit_ui_client, G_TYPE_OBJECT) - -static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef, WKDictionaryRef wkWindowFeatures, WKEventModifiers, WKEventMouseButton, const void*) +static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef, WKDictionaryRef wkWindowFeatures, WKEventModifiers, WKEventMouseButton, const void* clientInfo) { - return webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), wkWindowFeatures); + return webkitWebViewCreateNewPage(WEBKIT_WEB_VIEW(clientInfo), wkWindowFeatures); } -static void showPage(WKPageRef page, const void*) +static void showPage(WKPageRef page, const void* clientInfo) { - webkitWebViewReadyToShowPage(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + webkitWebViewReadyToShowPage(WEBKIT_WEB_VIEW(clientInfo)); } -static void closePage(WKPageRef page, const void*) +static void closePage(WKPageRef page, const void* clientInfo) { - webkitWebViewClosePage(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + webkitWebViewClosePage(WEBKIT_WEB_VIEW(clientInfo)); } -static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef, const void*) +static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef, const void* clientInfo) { - webkitWebViewRunJavaScriptAlert(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(message)->string().utf8()); + webkitWebViewRunJavaScriptAlert(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8()); } -static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef, const void*) +static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef, const void* clientInfo) { - return webkitWebViewRunJavaScriptConfirm(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(message)->string().utf8()); + return webkitWebViewRunJavaScriptConfirm(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8()); } -static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void*) +static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void* clientInfo) { - return webkitWebViewRunJavaScriptPrompt(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), toImpl(message)->string().utf8(), + return webkitWebViewRunJavaScriptPrompt(WEBKIT_WEB_VIEW(clientInfo), toImpl(message)->string().utf8(), toImpl(defaultValue)->string().utf8()); } -static bool toolbarsAreVisible(WKPageRef page, const void*) +static bool toolbarsAreVisible(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_toolbar_visible(windowProperties); } -static void setToolbarsAreVisible(WKPageRef page, bool toolbarsVisible, const void*) +static void setToolbarsAreVisible(WKPageRef page, bool toolbarsVisible, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetToolbarVisible(windowProperties, toolbarsVisible); } -static bool menuBarIsVisible(WKPageRef page, const void*) +static bool menuBarIsVisible(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_menubar_visible(windowProperties); } -static void setMenuBarIsVisible(WKPageRef page, bool menuBarVisible, const void*) +static void setMenuBarIsVisible(WKPageRef page, bool menuBarVisible, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetMenubarVisible(windowProperties, menuBarVisible); } -static bool statusBarIsVisible(WKPageRef page, const void*) +static bool statusBarIsVisible(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_statusbar_visible(windowProperties); } -static void setStatusBarIsVisible(WKPageRef page, bool statusBarVisible, const void*) +static void setStatusBarIsVisible(WKPageRef page, bool statusBarVisible, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetStatusbarVisible(windowProperties, statusBarVisible); } -static bool isResizable(WKPageRef page, const void*) +static bool isResizable(WKPageRef page, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); return webkit_window_properties_get_resizable(windowProperties); } -static void setIsResizable(WKPageRef page, bool resizable, const void*) +static void setIsResizable(WKPageRef page, bool resizable, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); webkitWindowPropertiesSetResizable(windowProperties, resizable); } -static WKRect getWindowFrame(WKPageRef page, const void*) +static WKRect getWindowFrame(WKPageRef page, const void* clientInfo) { GdkRectangle geometry = { 0, 0, 0, 0 }; - GtkWidget* window = gtk_widget_get_toplevel(toImpl(page)->viewWidget()); - if (gtk_widget_is_toplevel(window) && gtk_widget_get_visible(window)) { + GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(clientInfo)); + if (WebCore::widgetIsOnscreenToplevelWindow(window) && gtk_widget_get_visible(window)) { gtk_window_get_position(GTK_WINDOW(window), &geometry.x, &geometry.y); gtk_window_get_size(GTK_WINDOW(window), &geometry.width, &geometry.height); } return WKRectMake(geometry.x, geometry.y, geometry.width, geometry.height); } -static void setWindowFrame(WKPageRef page, WKRect frame, const void*) +static void setWindowFrame(WKPageRef page, WKRect frame, const void* clientInfo) { - WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget())); + WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(clientInfo)); GdkRectangle geometry = { frame.origin.x, frame.origin.y, frame.size.width, frame.size.height }; webkitWindowPropertiesSetGeometry(windowProperties, &geometry); } -void webkitUIClientAttachUIClientToPage(WebKitUIClient* uiClient, WKPageRef wkPage) +void attachUIClientToView(WebKitWebView* webView) { WKPageUIClient wkUIClient = { kWKPageUIClientCurrentVersion, - uiClient, // clientInfo + webView, // clientInfo 0, // createNewPage_deprecatedForUseWithV0 showPage, closePage, @@ -174,13 +174,7 @@ void webkitUIClientAttachUIClientToPage(WebKitUIClient* uiClient, WKPageRef wkPa 0, // mouseDidMoveOverElement 0, // decidePolicyForNotificationPermissionRequest }; + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); WKPageSetPageUIClient(wkPage, &wkUIClient); } -static void webkit_ui_client_init(WebKitUIClient* client) -{ -} - -static void webkit_ui_client_class_init(WebKitUIClientClass* clientClass) -{ -} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h index 41ef3ec25..e5a1a3e0f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.h @@ -20,33 +20,8 @@ #ifndef WebKitUIClient_h #define WebKitUIClient_h -#include <WebKit2/WebKit2.h> -#include <glib-object.h> +#include "WebKitWebView.h" -G_BEGIN_DECLS - -#define WEBKIT_TYPE_UI_CLIENT (webkit_ui_client_get_type()) -#define WEBKIT_UI_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_UI_CLIENT, WebKitUIClient)) -#define WEBKIT_UI_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_UI_CLIENT, WebKitUIClientClass)) -#define WEBKIT_IS_UI_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_UI_CLIENT)) -#define WEBKIT_IS_UI_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_UI_CLIENT)) -#define WEBKIT_UI_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_UI_CLIENT, WebKitUIClientClass)) - -typedef struct _WebKitUIClient WebKitUIClient; -typedef struct _WebKitUIClientClass WebKitUIClientClass; - -struct _WebKitUIClient { - GObject parent; -}; - -struct _WebKitUIClientClass { - GObjectClass parent_class; -}; - -GType webkit_ui_client_get_type (void); - -void webkitUIClientAttachUIClientToPage(WebKitUIClient*, WKPageRef); - -G_END_DECLS +void attachUIClientToView(WebKitWebView*); #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp index 154532a83..b5c2b4e74 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequest.cpp @@ -21,9 +21,8 @@ #include "WebKitURIRequest.h" #include "WebKitPrivate.h" -#include "WebURLRequest.h" +#include "WebKitURIRequestPrivate.h" #include <glib/gi18n-lib.h> -#include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> enum { @@ -37,6 +36,7 @@ using namespace WebCore; G_DEFINE_TYPE(WebKitURIRequest, webkit_uri_request, G_TYPE_OBJECT) struct _WebKitURIRequestPrivate { + WebCore::ResourceRequest resourceRequest; CString uri; }; @@ -65,7 +65,7 @@ static void webkitURIRequestSetProperty(GObject* object, guint propId, const GVa switch (propId) { case PROP_URI: - request->priv->uri = g_value_get_string(value); + request->priv->resourceRequest.setURL(KURL(KURL(), g_value_get_string(value))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); @@ -117,6 +117,13 @@ WebKitURIRequest* webkit_uri_request_new(const gchar* uri) return WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, "uri", uri, NULL)); } +WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest& resourceRequest) +{ + WebKitURIRequest* uriRequest = WEBKIT_URI_REQUEST(g_object_new(WEBKIT_TYPE_URI_REQUEST, NULL)); + uriRequest->priv->resourceRequest = resourceRequest; + return uriRequest; +} + /** * webkit_uri_request_get_uri: * @request: a #WebKitURIRequest @@ -127,6 +134,7 @@ const gchar* webkit_uri_request_get_uri(WebKitURIRequest* request) { g_return_val_if_fail(WEBKIT_IS_URI_REQUEST(request), 0); + request->priv->uri = request->priv->resourceRequest.url().string().utf8(); return request->priv->uri.data(); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h new file mode 100644 index 000000000..db85242af --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIRequestPrivate.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebKitURIRequestPrivate_h +#define WebKitURIRequestPrivate_h + +#include "WebKitURIRequest.h" +#include <WebCore/ResourceRequest.h> + +WebKitURIRequest* webkitURIRequestCreateForResourceRequest(const WebCore::ResourceRequest&); + +#endif // WebKitURIRequestPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp index 2a74cd03a..174bf12f8 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponse.cpp @@ -22,10 +22,7 @@ #include "WebKitPrivate.h" #include "WebKitURIResponsePrivate.h" -#include "WebURLResponse.h" #include <glib/gi18n-lib.h> -#include <wtf/gobject/GOwnPtr.h> -#include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> enum { @@ -41,9 +38,8 @@ using namespace WebCore; G_DEFINE_TYPE(WebKitURIResponse, webkit_uri_response, G_TYPE_OBJECT) struct _WebKitURIResponsePrivate { + WebCore::ResourceResponse resourceResponse; CString uri; - GRefPtr<SoupMessage> message; - guint64 contentLength; }; static void webkitURIResponseFinalize(GObject* object) @@ -71,26 +67,12 @@ static void webkitURIResponseGetProperty(GObject* object, guint propId, GValue* } } -static void webkitURIResponseSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) -{ - WebKitURIResponse* response = WEBKIT_URI_RESPONSE(object); - - switch (propId) { - case PROP_URI: - response->priv->uri = g_value_get_string(value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); - } -} - static void webkit_uri_response_class_init(WebKitURIResponseClass* responseClass) { GObjectClass* objectClass = G_OBJECT_CLASS(responseClass); objectClass->finalize = webkitURIResponseFinalize; objectClass->get_property = webkitURIResponseGetProperty; - objectClass->set_property = webkitURIResponseSetProperty; /** * WebKitURIResponse:uri: @@ -103,7 +85,7 @@ static void webkit_uri_response_class_init(WebKitURIResponseClass* responseClass _("URI"), _("The URI for which the response was made."), 0, - static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + WEBKIT_PARAM_READABLE)); /** * WebKitURIResponse:status-code: * @@ -150,6 +132,7 @@ const gchar* webkit_uri_response_get_uri(WebKitURIResponse* response) { g_return_val_if_fail(WEBKIT_IS_URI_RESPONSE(response), 0); + response->priv->uri = response->priv->resourceResponse.url().string().utf8(); return response->priv->uri.data(); } @@ -168,10 +151,7 @@ guint webkit_uri_response_get_status_code(WebKitURIResponse* response) { g_return_val_if_fail(WEBKIT_IS_URI_RESPONSE(response), SOUP_STATUS_NONE); - if (!response->priv->message) - return SOUP_STATUS_NONE; - - return response->priv->message->status_code; + return response->priv->resourceResponse.httpStatusCode(); } /** @@ -187,30 +167,17 @@ guint64 webkit_uri_response_get_content_length(WebKitURIResponse* response) { g_return_val_if_fail(WEBKIT_IS_URI_RESPONSE(response), 0); - if (response->priv->contentLength) - return response->priv->contentLength; - - if (!response->priv->message) - return 0; - - SoupMessage* message = response->priv->message.get(); - return static_cast<guint64>(soup_message_headers_get_content_length(message->response_headers)); -} - -WebKitURIResponse* webkitURIResponseCreateForSoupMessage(SoupMessage* message) -{ - GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(message), FALSE)); - WebKitURIResponse* response = WEBKIT_URI_RESPONSE(g_object_new(WEBKIT_TYPE_URI_RESPONSE, "uri", uri.get(), NULL)); - response->priv->message = message; - return response; + return response->priv->resourceResponse.expectedContentLength(); } -SoupMessage* webkitURIResponseGetSoupMessage(WebKitURIResponse* response) +WebKitURIResponse* webkitURIResponseCreateForResourceResponse(const WebCore::ResourceResponse& resourceResponse) { - return response->priv->message.get(); + WebKitURIResponse* uriResponse = WEBKIT_URI_RESPONSE(g_object_new(WEBKIT_TYPE_URI_RESPONSE, NULL)); + uriResponse->priv->resourceResponse = resourceResponse; + return uriResponse; } -void webkitURIResponseSetContentLength(WebKitURIResponse* response, guint64 contentLength) +const WebCore::ResourceResponse& webkitURIResponseGetResourceResponse(WebKitURIResponse* uriResponse) { - response->priv->contentLength = contentLength; + return uriResponse->priv->resourceResponse; } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h index fe84f8b1c..c2dc49c17 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitURIResponsePrivate.h @@ -27,10 +27,9 @@ #define WebKitURIResponsePrivate_h #include "WebKitURIResponse.h" -#include <libsoup/soup.h> +#include <WebCore/ResourceResponse.h> -WebKitURIResponse* webkitURIResponseCreateForSoupMessage(SoupMessage*); -SoupMessage* webkitURIResponseGetSoupMessage(WebKitURIResponse*); -void webkitURIResponseSetContentLength(WebKitURIResponse*, guint64 contentLength); +WebKitURIResponse* webkitURIResponseCreateForResourceResponse(const WebCore::ResourceResponse&); +const WebCore::ResourceResponse& webkitURIResponseGetResourceResponse(WebKitURIResponse*); #endif // WebKitURIResponsePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 1f9590c52..360b0a627 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -20,15 +20,29 @@ #include "config.h" #include "WebKitWebContext.h" +#include "WebContext.h" +#include "WebKitDownloadClient.h" +#include "WebKitDownloadPrivate.h" +#include "WebKitPrivate.h" #include "WebKitWebContextPrivate.h" -#include <WebKit2/WKContext.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKType.h> +#include <wtf/HashMap.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + DOWNLOAD_STARTED, + + LAST_SIGNAL +}; struct _WebKitWebContextPrivate { WKRetainPtr<WKContextRef> context; }; +static guint signals[LAST_SIGNAL] = { 0, }; + G_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT) static void webkitWebContextFinalize(GObject* object) @@ -49,15 +63,32 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass GObjectClass* gObjectClass = G_OBJECT_CLASS(webContextClass); gObjectClass->finalize = webkitWebContextFinalize; + /** + * WebKitWebContext::download-started: + * @context: the #WebKitWebContext + * @download: the #WebKitDownload associated with this event + * + * This signal is emitted when a new download request is made. + */ + signals[DOWNLOAD_STARTED] = + g_signal_new("download-started", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + WEBKIT_TYPE_DOWNLOAD); + g_type_class_add_private(webContextClass, sizeof(WebKitWebContextPrivate)); } - static gpointer createDefaultWebContext(gpointer) { WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL)); webContext->priv->context = WKContextGetSharedProcessContext(); WKContextSetCacheModel(webContext->priv->context.get(), kWKCacheModelPrimaryWebBrowser); + attachDownloadClientToContext(webContext); + return webContext; } @@ -152,6 +183,59 @@ WebKitCacheModel webkit_web_context_get_cache_model(WebKitWebContext* context) return WEBKIT_CACHE_MODEL_WEB_BROWSER; } +typedef HashMap<WKDownloadRef, GRefPtr<WebKitDownload> > DownloadsMap; + +static DownloadsMap& downloadsMap() +{ + DEFINE_STATIC_LOCAL(DownloadsMap, downloads, ()); + return downloads; +} + +/** + * webkit_web_context_download_uri: + * @context: a #WebKitWebContext + * @uri: the URI to download + * + * Requests downloading of the specified URI string. + * + * Returns: (transfer full): a new #WebKitDownload representing the + * the download operation. + */ +WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const gchar* uri) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + g_return_val_if_fail(uri, 0); + + WebKitWebContextPrivate* priv = context->priv; + WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(uri)); + WKRetainPtr<WKURLRequestRef> wkRequest(AdoptWK, WKURLRequestCreateWithWKURL(wkURL.get())); + WKRetainPtr<WKDownloadRef> wkDownload = WKContextDownloadURLRequest(priv->context.get(), wkRequest.get()); + WebKitDownload* download = webkitDownloadCreate(wkDownload.get()); + downloadsMap().set(wkDownload.get(), download); + return download; +} + +WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) +{ + GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); + if (download) + return download.get(); + + download = adoptGRef(webkitDownloadCreate(wkDownload)); + downloadsMap().set(wkDownload, download.get()); + return download.get(); +} + +void webkitWebContextRemoveDownload(WKDownloadRef wkDownload) +{ + downloadsMap().remove(wkDownload); +} + +void webkitWebContextDownloadStarted(WebKitWebContext* context, WebKitDownload* download) +{ + g_signal_emit(context, signals[DOWNLOAD_STARTED], 0, download); +} + WKContextRef webkitWebContextGetWKContext(WebKitWebContext* context) { g_assert(WEBKIT_IS_WEB_CONTEXT(context)); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index 2f38dbc25..b88bed0da 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -26,6 +26,7 @@ #include <glib-object.h> #include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitDownload.h> G_BEGIN_DECLS @@ -89,6 +90,10 @@ webkit_web_context_set_cache_model (WebKitWebContext *context, WEBKIT_API WebKitCacheModel webkit_web_context_get_cache_model (WebKitWebContext *context); +WEBKIT_API WebKitDownload * +webkit_web_context_download_uri (WebKitWebContext *context, + const gchar *uri); + G_END_DECLS #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h index 86d7dec8b..d2dd81361 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h @@ -32,6 +32,9 @@ G_BEGIN_DECLS WKContextRef webkitWebContextGetWKContext(WebKitWebContext*); +WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef); +void webkitWebContextRemoveDownload(WKDownloadRef); +void webkitWebContextDownloadStarted(WebKitWebContext*, WebKitDownload*); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h deleted file mode 100644 index c6044bc07..000000000 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebLoaderClient.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 Igalia S.L. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef WebKitWebLoaderClient_h -#define WebKitWebLoaderClient_h - -#include <glib-object.h> -#include <WebKit2/WebKit2.h> - -G_BEGIN_DECLS - -#define WEBKIT_TYPE_WEB_LOADER_CLIENT (webkit_web_loader_client_get_type()) -#define WEBKIT_WEB_LOADER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClient)) -#define WEBKIT_WEB_LOADER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientClass)) -#define WEBKIT_IS_WEB_LOADER_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT)) -#define WEBKIT_IS_WEB_LOADER_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_LOADER_CLIENT)) -#define WEBKIT_WEB_LOADER_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_LOADER_CLIENT, WebKitWebLoaderClientClass)) - -typedef struct _WebKitWebLoaderClient WebKitWebLoaderClient; -typedef struct _WebKitWebLoaderClientClass WebKitWebLoaderClientClass; - -struct _WebKitWebLoaderClient { - GObject parent; -}; - -struct _WebKitWebLoaderClientClass { - GObjectClass parentClass; -}; - -GType webkit_web_loader_client_get_type (void); -void webkitWebLoaderClientAttachLoaderClientToPage(WebKitWebLoaderClient*, WKPageRef); - -G_END_DECLS - -#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index fd2bb5190..fcaa2db1d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -24,20 +24,19 @@ #include "WebKitBackForwardListPrivate.h" #include "WebKitEnumTypes.h" #include "WebKitError.h" +#include "WebKitLoaderClient.h" #include "WebKitMarshal.h" +#include "WebKitPolicyClient.h" #include "WebKitSettingsPrivate.h" #include "WebKitUIClient.h" #include "WebKitWebContextPrivate.h" -#include "WebKitWebLoaderClient.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebKitPrivate.h" #include "WebPageProxy.h" #include <WebCore/DragIcon.h> -#include <WebKit2/WKBase.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKURL.h> +#include <WebCore/GtkUtilities.h> #include <glib/gi18n-lib.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> @@ -58,6 +57,8 @@ enum { SCRIPT_CONFIRM, SCRIPT_PROMPT, + DECIDE_POLICY, + LAST_SIGNAL }; @@ -79,8 +80,6 @@ struct _WebKitWebViewPrivate { CString activeURI; bool replacingContent; - GRefPtr<WebKitWebLoaderClient> loaderClient; - GRefPtr<WebKitUIClient> uiClient; GRefPtr<WebKitBackForwardList> backForwardList; GRefPtr<WebKitSettings> settings; GRefPtr<WebKitWindowProperties> windowProperties; @@ -111,7 +110,7 @@ static GtkWidget* webkitWebViewCreate(WebKitWebView*) static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* message) { GtkWidget* parent = gtk_widget_get_toplevel(GTK_WIDGET(webView)); - GtkWidget* dialog = gtk_message_dialog_new(gtk_widget_is_toplevel(parent) ? GTK_WINDOW(parent) : 0, + GtkWidget* dialog = gtk_message_dialog_new(widgetIsOnscreenToplevelWindow(parent) ? GTK_WINDOW(parent) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", message); GOwnPtr<char> title(g_strdup_printf("JavaScript - %s", webkit_web_view_get_uri(webView))); gtk_window_set_title(GTK_WINDOW(dialog), title.get()); @@ -149,10 +148,10 @@ static gboolean webkitWebViewScriptPrompt(WebKitWebView* webView, const char* me return TRUE; } -static void webkitWebViewSetLoaderClient(WebKitWebView* webView, WebKitWebLoaderClient* loaderClient, WKPageRef wkPage) +static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* decision, WebKitPolicyDecisionType) { - webView->priv->loaderClient = loaderClient; - webkitWebLoaderClientAttachLoaderClientToPage(loaderClient, wkPage); + webkit_policy_decision_use(decision); + return TRUE; } static void webkitWebViewConstructed(GObject* object) @@ -166,15 +165,11 @@ static void webkitWebViewConstructed(GObject* object) webkitWebViewBaseCreateWebPage(webViewBase, webkitWebContextGetWKContext(priv->context), 0); - WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); - - static GRefPtr<WebKitWebLoaderClient> defaultLoaderClient = adoptGRef(WEBKIT_WEB_LOADER_CLIENT(g_object_new(WEBKIT_TYPE_WEB_LOADER_CLIENT, NULL))); - webkitWebViewSetLoaderClient(webView, defaultLoaderClient.get(), toAPI(page)); - - static GRefPtr<WebKitUIClient> defaultUIClient = adoptGRef(WEBKIT_UI_CLIENT(g_object_new(WEBKIT_TYPE_UI_CLIENT, NULL))); - priv->uiClient = defaultUIClient.get(); - webkitUIClientAttachUIClientToPage(priv->uiClient.get(), toAPI(page)); + attachLoaderClientToView(webView); + attachUIClientToView(webView); + attachPolicyClientToPage(webView); + WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page)))); priv->settings = adoptGRef(webkit_settings_new()); webkitSettingsAttachSettingsToPage(priv->settings.get(), toAPI(page)); @@ -259,6 +254,7 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webViewClass->script_alert = webkitWebViewScriptAlert; webViewClass->script_confirm = webkitWebViewScriptConfirm; webViewClass->script_prompt = webkitWebViewScriptPrompt; + webViewClass->decide_policy = webkitWebViewDecidePolicy; g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate)); @@ -557,6 +553,66 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_BOOLEAN, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + /** + * WebKitPolicyClient::decide-policy + * @web_view: the #WebKitWebView on which the signal is emitted + * @decision: the #WebKitNavigationPolicyDecision + * @decision_type: a #WebKitPolicyDecisionType denoting the type of @decision + * + * This signal is emitted when WebKit is requesting the client to decide a policy + * decision, such as whether to navigate to a page, open a new window or whether or + * not to download a resource. The #WebKitNavigationPolicyDecision passed in the + * @decision argument is a generic type, but should be casted to a more + * specific type when making the decision. For example: + * + * <informalexample><programlisting> + * static gboolean + * decide_policy_cb (WebKitWebView *web_view, + * WebKitPolicyDecision *decision, + * WebKitPolicyDecisionType type) + * { + * switch (type) { + * case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: + * WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); + * /<!-- -->* Make a policy decision here. *<!-- -->/ + * break; + * case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: + * WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision); + * /<!-- -->* Make a policy decision here. *<!-- -->/ + * break; + * case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: + * WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision); + * /<!-- -->* Make a policy decision here. *<!-- -->/ + * break; + * default: + * /<!-- -->* Making no decision results in webkit_policy_decision_use(). *<!-- -->/ + * return FALSE; + * } + * return TRUE; + * } + * </programlisting></informalexample> + * + * It is possible to make policy decision asynchronously, by simply calling g_object_ref() + * on the @decision argument and returning %TRUE to block the default signal handler. + * If the last reference is removed on a #WebKitPolicyDecision and no decision has been + * made explicitly, webkit_policy_decision_use() will be the default policy decision. The + * default signal handler will simply call webkit_policy_decision_use(). Only the first + * policy decision chosen for a given #WebKitPolicyDecision will have any affect. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + * + */ + signals[DECIDE_POLICY] = + g_signal_new("decide-policy", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, decide_policy), + g_signal_accumulator_true_handled, 0 /* accumulator data */, + webkit_marshal_BOOLEAN__OBJECT_ENUM, + G_TYPE_BOOLEAN, 2, /* number of parameters */ + WEBKIT_TYPE_POLICY_DECISION, + WEBKIT_TYPE_POLICY_DECISION_TYPE); } void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent) @@ -662,6 +718,12 @@ WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CStri return text ? WKStringCreateWithUTF8CString(text.get()) : 0; } +void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision) +{ + gboolean returnValue; + g_signal_emit(webView, signals[DECIDE_POLICY], 0, decision, type, &returnValue); +} + /** * webkit_web_view_new: * diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h index a25c438dd..697fcdc80 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h @@ -35,9 +35,44 @@ #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> +#include <webkit2/WebKitPolicyDecision.h> G_BEGIN_DECLS +/** + * WebKitPolicyDecisionType: + * @WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: This type of policy decision + * is requested when WebKit is about to navigate to a new page in either the + * main frame or a subframe. Acceptable policy decisions are either + * webkit_policy_decision_use() or webkit_policy_decision_ignore(). This + * type of policy decision is always a #WebKitNavigationPolicyDecision. + * @WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION: This type of policy decision + * is requested when WebKit is about to create a new window. Acceptable policy + * decisions are either webkit_policy_decision_use() or + * webkit_policy_decision_ignore(). This type of policy decision is always + * a #WebKitNavigationPolicyDecision. These decisions are useful for implementing + * special actions for new windows, such as forcing the new window to open + * in a tab when a keyboard modifier is active or handling a special + * target attribute on <a> elements. + * @WEBKIT_POLICY_DECISION_TYPE_RESPONSE: This type of decision is used when WebKit has + * received a response for a network resource and is about to start the load. + * Note that these resources include all subresources of a page such as images + * and stylesheets as well as main documents. Appropriate policy responses to + * this decision are webkit_policy_decision_use(), webkit_policy_decision_ignore(), + * or webkit_policy_decision_download(). This type of policy decision is always + * a #WebKitResponsePolicyDecision. This decision is useful for forcing + * some types of resources to be downloaded rather than rendered in the WebView + * or to block the transfer of resources entirely. + * + * Enum values used for determining the type of a policy decision during + * WebKitWebView::decide-policy. + */ +typedef enum { + WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION, + WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION, + WEBKIT_POLICY_DECISION_TYPE_RESPONSE, +} WebKitPolicyDecisionType; + #define WEBKIT_TYPE_WEB_VIEW (webkit_web_view_get_type()) #define WEBKIT_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_VIEW, WebKitWebView)) #define WEBKIT_WEB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_VIEW, WebKitWebViewClass)) @@ -81,26 +116,29 @@ struct _WebKitWebView { struct _WebKitWebViewClass { WebKitWebViewBaseClass parent; - void (* load_changed) (WebKitWebView *web_view, - WebKitLoadEvent load_event); - gboolean (* load_failed) (WebKitWebView *web_view, - WebKitLoadEvent load_event, - const gchar *failing_uri, - GError *error); - - GtkWidget *(* create) (WebKitWebView *web_view); - void (* ready_to_show) (WebKitWebView *web_view); - void (* close) (WebKitWebView *web_view); - - gboolean (* script_alert) (WebKitWebView *web_view, - const gchar *message); - gboolean (* script_confirm) (WebKitWebView *web_view, - const gchar *message, - gboolean *confirmed); - gboolean (* script_prompt) (WebKitWebView *web_view, - const gchar *message, - const gchar *default_text, - gchar **text); + void (* load_changed) (WebKitWebView *web_view, + WebKitLoadEvent load_event); + gboolean (* load_failed) (WebKitWebView *web_view, + WebKitLoadEvent load_event, + const gchar *failing_uri, + GError *error); + + GtkWidget *(* create) (WebKitWebView *web_view); + void (* ready_to_show) (WebKitWebView *web_view); + void (* close) (WebKitWebView *web_view); + + gboolean (* script_alert) (WebKitWebView *web_view, + const gchar *message); + gboolean (* script_confirm) (WebKitWebView *web_view, + const gchar *message, + gboolean *confirmed); + gboolean (* script_prompt) (WebKitWebView *web_view, + const gchar *message, + const gchar *default_text, + gchar **text); + gboolean (* decide_policy) (WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType type); /* Padding for future expansion */ void (*_webkit_reserved0) (void); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index 86607162f..d9ccaa32a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -35,6 +35,8 @@ #include "PageClientImpl.h" #include "WebContext.h" #include "WebEventFactory.h" +#include "WebKitPrivate.h" +#include "WebKitWebViewBaseAccessible.h" #include "WebKitWebViewBasePrivate.h" #include "WebPageProxy.h" #include <WebCore/ClipboardGtk.h> @@ -50,7 +52,6 @@ #include <WebCore/PasteboardHelper.h> #include <WebCore/RefPtrCairo.h> #include <WebCore/Region.h> -#include <WebKit2/WKContext.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> @@ -69,6 +70,7 @@ struct _WebKitWebViewBasePrivate { GtkDragAndDropHelper dragAndDropHelper; DragIcon dragIcon; IntSize resizerSize; + GRefPtr<AtkObject> accessible; }; G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER) @@ -118,6 +120,7 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK @@ -139,7 +142,7 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) gtk_im_context_set_client_window(priv->imContext.get(), window); GtkWidget* toplevel = gtk_widget_get_toplevel(widget); - if (gtk_widget_is_toplevel(toplevel) && GTK_IS_WINDOW(toplevel)) { + if (widgetIsOnscreenToplevelWindow(toplevel)) { webkitWebViewBaseNotifyResizerSizeForWindow(webView, GTK_WINDOW(toplevel)); g_signal_connect(toplevel, "notify::resize-grip-visible", G_CALLBACK(toplevelWindowResizeGripVisibilityChanged), webView); @@ -211,7 +214,7 @@ static void webkitWebViewBaseSizeAllocate(GtkWidget* widget, GtkAllocation* allo priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize()); GtkWidget* toplevel = gtk_widget_get_toplevel(widget); - if (gtk_widget_is_toplevel(toplevel) && GTK_IS_WINDOW(toplevel)) + if (widgetIsOnscreenToplevelWindow(toplevel)) webkitWebViewBaseNotifyResizerSizeForWindow(webViewBase, GTK_WINDOW(toplevel)); } @@ -221,7 +224,7 @@ static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* WebKitWebViewBasePrivate* priv = webViewBase->priv; GtkWidget* toplevel = gtk_widget_get_toplevel(widget); - if (gtk_widget_is_toplevel(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) { + if (widgetIsOnscreenToplevelWindow(toplevel) && gtk_window_has_toplevel_focus(GTK_WINDOW(toplevel))) { gtk_im_context_focus_in(priv->imContext.get()); if (!priv->isPageActive) { priv->isPageActive = TRUE; @@ -374,6 +377,34 @@ static void webkitWebViewBaseDragDataReceived(GtkWidget* widget, GdkDragContext* gdk_drag_status(context, dragOperationToSingleGdkDragAction(operation), time); } +static AtkObject* webkitWebViewBaseGetAccessible(GtkWidget* widget) +{ + // If the socket has already been created and embedded a plug ID, return it. + WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv; + if (priv->accessible && atk_socket_is_occupied(ATK_SOCKET(priv->accessible.get()))) + return priv->accessible.get(); + + // Create the accessible object and associate it to the widget. + if (!priv->accessible) { + priv->accessible = adoptGRef(ATK_OBJECT(webkitWebViewBaseAccessibleNew(widget))); + + // Set the parent not to break bottom-up navigation. + GtkWidget* parentWidget = gtk_widget_get_parent(widget); + AtkObject* axParent = parentWidget ? gtk_widget_get_accessible(parentWidget) : 0; + if (axParent) + atk_object_set_parent(priv->accessible.get(), axParent); + } + + // Try to embed the plug in the socket, if posssible. + String plugID = priv->pageProxy->accessibilityPlugID(); + if (plugID.isNull()) + return priv->accessible.get(); + + atk_socket_embed(ATK_SOCKET(priv->accessible.get()), const_cast<gchar*>(plugID.utf8().data())); + + return priv->accessible.get(); +} + static gboolean webkitWebViewBaseDragMotion(GtkWidget* widget, GdkDragContext* context, gint x, gint y, guint time) { WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget); @@ -438,6 +469,7 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie widgetClass->drag_leave = webkitWebViewBaseDragLeave; widgetClass->drag_drop = webkitWebViewBaseDragDrop; widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived; + widgetClass->get_accessible = webkitWebViewBaseGetAccessible; GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass); gobjectClass->finalize = webkitWebViewBaseFinalize; diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp new file mode 100644 index 000000000..09a11abe6 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitWebViewBaseAccessible.h" + +#include <gtk/gtk.h> + +struct _WebKitWebViewBaseAccessiblePrivate { + GtkWidget* widget; +}; + +G_DEFINE_TYPE(WebKitWebViewBaseAccessible, webkit_web_view_base_accessible, ATK_TYPE_SOCKET) + +static void webkitWebViewBaseAccessibleFinalize(GObject* gobject) +{ + WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(gobject); + accessible->priv->~WebKitWebViewBaseAccessiblePrivate(); + G_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->finalize(gobject); +} + +static void webkitWebViewBaseAccessibleWidgetDestroyed(GtkWidget* widget, WebKitWebViewBaseAccessible* accessible) +{ + accessible->priv->widget = 0; + atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_DEFUNCT, TRUE); +} + +static void webkitWebViewBaseAccessibleInitialize(AtkObject* atkObject, gpointer data) +{ + if (ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->initialize) + ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->initialize(atkObject, data); + + if (data && GTK_IS_WIDGET(data)) { + WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(atkObject); + accessible->priv->widget = GTK_WIDGET(data); + + g_signal_connect_after(accessible->priv->widget, "destroy", + G_CALLBACK(webkitWebViewBaseAccessibleWidgetDestroyed), atkObject); + } + + atk_object_set_role(atkObject, ATK_ROLE_FILLER); +} + +static AtkStateSet* webkitWebViewBaseAccessibleRefStateSet(AtkObject* atkObject) +{ + WebKitWebViewBaseAccessible* accessible = WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(atkObject); + + AtkStateSet* stateSet; + if (accessible->priv->widget) { + // Use the implementation of AtkSocket if the widget is still alive. + stateSet = ATK_OBJECT_CLASS(webkit_web_view_base_accessible_parent_class)->ref_state_set(atkObject); + } else { + // If the widget is no longer alive, save some remote calls + // (because of AtkSocket's implementation of ref_state_set()) + // and just return that this AtkObject is defunct. + stateSet = atk_state_set_new(); + atk_state_set_add_state(stateSet, ATK_STATE_DEFUNCT); + } + + return stateSet; +} + +static gint webkitWebViewBaseAccessibleGetIndexInParent(AtkObject* atkObject) +{ + AtkObject* atkParent = atk_object_get_parent(atkObject); + if (!atkParent) + return -1; + + guint count = atk_object_get_n_accessible_children(atkParent); + for (guint i = 0; i < count; ++i) { + AtkObject* child = atk_object_ref_accessible_child(atkParent, i); + bool childIsObject = child == atkObject; + g_object_unref(child); + if (childIsObject) + return i; + } + + return -1; +} + +static void webkit_web_view_base_accessible_init(WebKitWebViewBaseAccessible* accessible) +{ + WebKitWebViewBaseAccessiblePrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(accessible, WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessiblePrivate); + accessible->priv = priv; + new (priv) WebKitWebViewBaseAccessiblePrivate(); +} + +static void webkit_web_view_base_accessible_class_init(WebKitWebViewBaseAccessibleClass* klass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(klass); + gObjectClass->finalize = webkitWebViewBaseAccessibleFinalize; + + // No need to implement get_n_children() and ref_child() here + // since this is a subclass of AtkSocket and all the logic related + // to those functions will be implemented by the ATK bridge. + AtkObjectClass* atkObjectClass = ATK_OBJECT_CLASS(klass); + atkObjectClass->initialize = webkitWebViewBaseAccessibleInitialize; + atkObjectClass->ref_state_set = webkitWebViewBaseAccessibleRefStateSet; + atkObjectClass->get_index_in_parent = webkitWebViewBaseAccessibleGetIndexInParent; + + g_type_class_add_private(klass, sizeof(WebKitWebViewBaseAccessiblePrivate)); +} + +WebKitWebViewBaseAccessible* webkitWebViewBaseAccessibleNew(GtkWidget* widget) +{ + AtkObject* object = ATK_OBJECT(g_object_new(WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, NULL)); + atk_object_initialize(object, widget); + return WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(object); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.h new file mode 100644 index 000000000..3e932c3cd --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBaseAccessible.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitWebViewBaseAccessible_h +#define WebKitWebViewBaseAccessible_h + +#include <atk/atk.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE (webkit_web_view_base_accessible_get_type()) +#define WEBKIT_WEB_VIEW_BASE_ACCESSIBLE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessible)) +#define WEBKIT_WEB_VIEW_BASE_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessibleClass)) +#define WEBKIT_IS_WEB_VIEW_BASE_ACCESSIBLE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE)) +#define WEBKIT_IS_WEB_VIEW_BASE_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE)) +#define WEBKIT_WEB_VIEW_BASE_ACCESSIBLE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), WEBKIT_TYPE_WEB_VIEW_BASE_ACCESSIBLE, WebKitWebViewBaseAccessibleClass)) + +typedef struct _WebKitWebViewBaseAccessible WebKitWebViewBaseAccessible; +typedef struct _WebKitWebViewBaseAccessibleClass WebKitWebViewBaseAccessibleClass; +typedef struct _WebKitWebViewBaseAccessiblePrivate WebKitWebViewBaseAccessiblePrivate; + + +struct _WebKitWebViewBaseAccessible { + AtkSocket parent; + /*< private >*/ + WebKitWebViewBaseAccessiblePrivate* priv; +}; + +struct _WebKitWebViewBaseAccessibleClass { + AtkSocketClass parentClass; +}; + +GType webkit_web_view_base_accessible_get_type(); + +WebKitWebViewBaseAccessible* webkitWebViewBaseAccessibleNew(GtkWidget*); + +G_END_DECLS + +#endif // WebKitWebViewBaseAccessible_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h index 5c8161afd..66386d028 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h @@ -42,5 +42,6 @@ void webkitWebViewClosePage(WebKitWebView*); void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message); bool webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message); WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText); +void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); #endif // WebKitWebViewPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp index c99f6d6e8..b170c82c9 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWindowProperties.cpp @@ -24,10 +24,6 @@ #include "WebKitWindowPropertiesPrivate.h" #include "WebURLRequest.h" #include <WebCore/IntRect.h> -#include <WebKit2/WKDictionary.h> -#include <WebKit2/WKNumber.h> -#include <WebKit2/WKRetainPtr.h> -#include <WebKit2/WKString.h> #include <glib/gi18n-lib.h> /** diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index c513959c2..c6f943ab2 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -20,6 +20,9 @@ <xi:include href="xml/WebKitURIRequest.xml"/> <xi:include href="xml/WebKitURIResponse.xml"/> <xi:include href="xml/WebKitWindowProperties.xml"/> + <xi:include href="xml/WebKitDownload.xml"/> + <xi:include href="xml/WebKitPolicyDecision.xml"/> + <xi:include href="xml/WebKitNavigationPolicyDecision.xml"/> <xi:include href="xml/WebKitError.xml"/> </chapter> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index 84468945d..ef44b2bed 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -27,6 +27,7 @@ WebKitCacheModel webkit_web_context_get_default webkit_web_context_get_cache_model webkit_web_context_set_cache_model +webkit_web_context_download_uri <SUBSECTION Standard> WebKitWebContextClass @@ -47,6 +48,7 @@ webkit_web_context_get_type <TITLE>WebKitWebView</TITLE> WebKitWebView WebKitLoadEvent +WebKitPolicyDecisionType webkit_web_view_new webkit_web_view_new_with_context webkit_web_view_get_context @@ -202,6 +204,8 @@ webkit_settings_get_enable_caret_browsing webkit_settings_set_enable_caret_browsing webkit_settings_get_enable_fullscreen webkit_settings_set_enable_fullscreen +webkit_settings_get_print_backgrounds +webkit_settings_set_print_backgrounds <SUBSECTION Standard> WebKitSettingsClass @@ -285,15 +289,87 @@ webkit_window_properties_get_type </SECTION> <SECTION> +<FILE>WebKitDownload</FILE> +WebKitDownload +webkit_download_get_destination +webkit_download_set_destination +webkit_download_get_response +webkit_download_cancel +webkit_download_get_estimated_progress +webkit_download_get_elapsed_time + +<SUBSECTION Standard> +WebKitDownloadClass +WEBKIT_TYPE_DOWNLOAD +WEBKIT_DOWNLOAD +WEBKIT_IS_DOWNLOAD +WEBKIT_DOWNLOAD_CLASS +WEBKIT_IS_DOWNLOAD_CLASS +WEBKIT_DOWNLOAD_GET_CLASS + +<SUBSECTION Private> +WebKitDownloadPrivate +webkit_download_get_type +</SECTION> + +<SECTION> +<FILE>WebKitPolicyDecision</FILE> +WebKitPolicyDecision +webkit_policy_decision_download +webkit_policy_decision_ignore +webkit_policy_decision_use + +<SUBSECTION Standard> +WebKitPolicyDecisionClass +WEBKIT_TYPE_POLICY_DECISION +WEBKIT_POLICY_DECISION +WEBKIT_IS_POLICY_DECISION +WEBKIT_POLICY_DECISION_CLASS +WEBKIT_IS_POLICY_DECISION_CLASS +WEBKIT_POLICY_DECISION_GET_CLASS + +<SUBSECTION Private> +WebKitPolicyDecisionPrivate +webkit_policy_decision_get_type +</SECTION> + +<SECTION> +<FILE>WebKitNavigationPolicyDecision</FILE> +WebKitNavigationPolicyDecision +WebKitNavigationType +webkit_navigation_policy_decision_get_frame_name +webkit_navigation_policy_decision_get_modifiers +webkit_navigation_policy_decision_get_mouse_button +webkit_navigation_policy_decision_get_navigation_type +webkit_navigation_policy_decision_get_request + +<SUBSECTION Standard> +WebKitNavigationPolicyDecisionClass +WEBKIT_TYPE_NAVIGATION_POLICY_DECISION +WEBKIT_NAVIGATION_POLICY_DECISION +WEBKIT_IS_NAVIGATION_POLICY_DECISION +WEBKIT_NAVIGATION_POLICY_DECISION_CLASS +WEBKIT_IS_NAVIGATION_POLICY_DECISION_CLASS +WEBKIT_NAVIGATION_POLICY_DECISION_GET_CLASS + +<SUBSECTION Private> +WebKitNavigationPolicyDecisionPrivate +webkit_navigation_policy_decision_get_type +</SECTION> + +<SECTION> <FILE>WebKitError</FILE> WEBKIT_NETWORK_ERROR WEBKIT_PLUGIN_ERROR WEBKIT_POLICY_ERROR +WEBKIT_DOWNLOAD_ERROR WebKitNetworkError WebKitPluginError WebKitPolicyError +WebKitDownloadError webkit_network_error_quark webkit_plugin_error_quark webkit_policy_error_quark +webkit_download_error_quark </SECTION> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types index 40a841c89..cba2df42c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types @@ -8,3 +8,5 @@ webkit_settings_get_type webkit_uri_response_get_type webkit_uri_request_get_type webkit_window_properties_get_type +webkit_download_get_type + diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp new file mode 100644 index 000000000..a8bbbc3fa --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include <gtk/gtk.h> +#include <webkit2/webkit2.h> + +static void loadChangedCallback(WebKitWebView*, WebKitLoadEvent loadEvent, gpointer) +{ + // Send a message to the parent process when we're ready. + if (loadEvent == WEBKIT_LOAD_FINISHED) + g_print("OK"); +} + +int main(int argc, char** argv) +{ + // Make sure that both GAIL and the ATK bridge are loaded. + g_setenv("GTK_MODULES", "gail:atk-bridge", TRUE); + + gtk_init(&argc, &argv); + + WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new()); + webkit_web_view_load_html(webView, + "<html>" + " <body>" + " <h1>This is a test</h1>" + " <p>This is a paragraph with some plain text.</p>" + " <p>This paragraph contains <a href=\"http://www.webkitgtk.org\">a link</a> in the middle.</p>" + " </body>" + "</html>", + 0); + + GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(webView)); + gtk_widget_show_all(window); + + g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), 0); + g_signal_connect(webView, "load-changed", G_CALLBACK(loadChangedCallback), 0); + + gtk_main(); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index d912b657e..175a149e4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -1,13 +1,23 @@ TEST_PROGS += \ Programs/WebKit2APITests/TestWebKitWebContext \ Programs/WebKit2APITests/TestWebKitWebView \ - Programs/WebKit2APITests/TestWebKitWebLoaderClient \ + Programs/WebKit2APITests/TestLoaderClient \ Programs/WebKit2APITests/TestWebKitSettings \ - Programs/WebKit2APITests/TestBackForwardList + Programs/WebKit2APITests/TestBackForwardList \ + Programs/WebKit2APITests/TestDownloads \ + Programs/WebKit2APITests/TestWebKitPolicyClient noinst_PROGRAMS += $(TEST_PROGS) + +if HAVE_ATSPI2 +TEST_PROGS += Programs/WebKit2APITests/TestWebKitAccessibility + +noinst_PROGRAMS += Programs/WebKit2APITests/AccessibilityTestServer +endif + webkit2_tests_cppflags = \ -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs\" \ + -DWEBKIT_SRC_DIR=\"${shell pwd}/${srcdir}\" \ $(javascriptcore_cppflags) \ -I$(srcdir)/Source/JavaScriptCore \ -I$(srcdir)/Source \ @@ -58,11 +68,11 @@ Programs_WebKit2APITests_TestWebKitWebView_CPPFLAGS = $(webkit2_tests_cppflags) Programs_WebKit2APITests_TestWebKitWebView_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestWebKitWebView_LDFLAGS = $(webkit2_tests_ldflags) -Programs_WebKit2APITests_TestWebKitWebLoaderClient_SOURCES = \ - Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebLoaderClient.cpp -Programs_WebKit2APITests_TestWebKitWebLoaderClient_CPPFLAGS = $(webkit2_tests_cppflags) -Programs_WebKit2APITests_TestWebKitWebLoaderClient_LDADD = $(webkit2_tests_ldadd) -Programs_WebKit2APITests_TestWebKitWebLoaderClient_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestLoaderClient_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp +Programs_WebKit2APITests_TestLoaderClient_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestLoaderClient_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestLoaderClient_LDFLAGS = $(webkit2_tests_ldflags) Programs_WebKit2APITests_TestWebKitSettings_SOURCES = \ Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -76,3 +86,28 @@ Programs_WebKit2APITests_TestBackForwardList_CPPFLAGS = $(webkit2_tests_cppflags Programs_WebKit2APITests_TestBackForwardList_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestBackForwardList_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestWebKitPolicyClient_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp +Programs_WebKit2APITests_TestWebKitPolicyClient_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestWebKitPolicyClient_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestWebKitPolicyClient_LDFLAGS = $(webkit2_tests_ldflags) + +if HAVE_ATSPI2 +Programs_WebKit2APITests_AccessibilityTestServer_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/AccessibilityTestServer.cpp +Programs_WebKit2APITests_AccessibilityTestServer_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_AccessibilityTestServer_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_AccessibilityTestServer_LDFLAGS = $(webkit2_tests_ldflags) + +Programs_WebKit2APITests_TestWebKitAccessibility_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp +Programs_WebKit2APITests_TestWebKitAccessibility_CPPFLAGS = $(webkit2_tests_cppflags) $(ATSPI2_CFLAGS) +Programs_WebKit2APITests_TestWebKitAccessibility_LDADD = $(webkit2_tests_ldadd) $(ATSPI2_LIBS) +Programs_WebKit2APITests_TestWebKitAccessibility_LDFLAGS = $(webkit2_tests_ldflags) +endif + +Programs_WebKit2APITests_TestDownloads_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp +Programs_WebKit2APITests_TestDownloads_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestDownloads_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestDownloads_LDFLAGS = $(webkit2_tests_ldflags) diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp index 7581f2f6e..9eb08575d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp @@ -138,3 +138,37 @@ void LoadTrackingTest::estimatedProgressChanged() m_estimatedProgress = progress; } +void LoadTrackingTest::loadURI(const char* uri) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadURI(uri); +} + +void LoadTrackingTest::loadHtml(const char* html, const char* baseURI) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadHtml(html, baseURI); +} + +void LoadTrackingTest::loadPlainText(const char* plainText) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadPlainText(plainText); +} + +void LoadTrackingTest::loadRequest(WebKitURIRequest* request) +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + WebViewTest::loadRequest(request); +} + +void LoadTrackingTest::reload() +{ + m_loadEvents.clear(); + m_estimatedProgress = 0; + webkit_web_view_reload(m_webView); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h index 308aa9ce1..2d95c48f4 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h @@ -39,6 +39,12 @@ public: virtual void loadFailed(const char* failingURI, GError*); virtual void estimatedProgressChanged(); + void loadURI(const char* uri); + void loadHtml(const char* html, const char* baseURI); + void loadPlainText(const char* plainText); + void loadRequest(WebKitURIRequest*); + void reload(); + void setRedirectURI(const char* uri) { m_redirectURI = uri; } enum LoadEvents { diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp index ac2a57235..cc657cc64 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestBackForwardList.cpp @@ -27,7 +27,7 @@ #include <webkit2/webkit2.h> // Back forward list limit is 100 by default. -static const size_t kBackForwardListLimit = 100; +static const int kBackForwardListLimit = 100; static WebKitTestServer* kServer; @@ -240,7 +240,7 @@ static void testBackForwardListNavigation(BackForwardListTest* test, gconstpoint static void testBackForwardListLimitAndCache(BackForwardListTest* test, gconstpointer) { - for (size_t i = 0; i < kBackForwardListLimit; i++) { + for (int i = 0; i < kBackForwardListLimit; i++) { GOwnPtr<char> path(g_strdup_printf("/Page%d", i)); test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem; test->loadURI(kServer->getURIForPath(path.get()).data()); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp new file mode 100644 index 000000000..461cefa0e --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "TestMain.h" +#include "WebKitTestServer.h" +#include <glib/gstdio.h> +#include <gtk/gtk.h> +#include <libsoup/soup.h> +#include <string.h> +#include <webkit2/webkit2.h> +#include <wtf/Vector.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +static char* kTempDirectory; + +class DownloadTest: public Test { +public: + MAKE_GLIB_TEST_FIXTURE(DownloadTest); + + enum DownloadEvent { + Started, + ReceivedResponse, + CreatedDestination, + ReceivedData, + Failed, + Finished + }; + + static void receivedResponseCallback(WebKitDownload* download, GParamSpec*, DownloadTest* test) + { + g_assert(webkit_download_get_response(download)); + test->receivedResponse(download); + } + + static gboolean createdDestinationCallback(WebKitDownload* download, const gchar* destination, DownloadTest* test) + { + g_assert(webkit_download_get_destination(download)); + g_assert_cmpstr(webkit_download_get_destination(download), ==, destination); + test->createdDestination(download, destination); + return TRUE; + } + + static gboolean receivedDataCallback(WebKitDownload* download, guint64 dataLength, DownloadTest* test) + { + test->receivedData(download, dataLength); + return TRUE; + } + + static gboolean finishedCallback(WebKitDownload* download, DownloadTest* test) + { + test->finished(download); + return TRUE; + } + + static gboolean failedCallback(WebKitDownload* download, GError* error, DownloadTest* test) + { + g_assert(error); + test->failed(download, error); + return TRUE; + } + + static gboolean decideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, DownloadTest* test) + { + g_assert(suggestedFilename); + test->decideDestination(download, suggestedFilename); + return TRUE; + } + + static void downloadStartedCallback(WebKitWebContext* context, WebKitDownload* download, DownloadTest* test) + { + test->started(download); + g_signal_connect(download, "notify::response", G_CALLBACK(receivedResponseCallback), test); + g_signal_connect(download, "created-destination", G_CALLBACK(createdDestinationCallback), test); + g_signal_connect(download, "received-data", G_CALLBACK(receivedDataCallback), test); + g_signal_connect(download, "finished", G_CALLBACK(finishedCallback), test); + g_signal_connect(download, "failed", G_CALLBACK(failedCallback), test); + g_signal_connect(download, "decide-destination", G_CALLBACK(decideDestinationCallback), test); + } + + DownloadTest() + : m_webContext(webkit_web_context_get_default()) + , m_mainLoop(g_main_loop_new(0, TRUE)) + , m_downloadSize(0) + { + g_signal_connect(m_webContext, "download-started", G_CALLBACK(downloadStartedCallback), this); + } + + ~DownloadTest() + { + g_signal_handlers_disconnect_matched(m_webContext, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + g_main_loop_unref(m_mainLoop); + } + + virtual void started(WebKitDownload* download) + { + m_downloadEvents.append(Started); + } + + virtual void receivedResponse(WebKitDownload* download) + { + m_downloadEvents.append(ReceivedResponse); + } + + virtual void createdDestination(WebKitDownload* download, const char* destination) + { + m_downloadEvents.append(CreatedDestination); + } + + virtual void receivedData(WebKitDownload* download, guint64 dataLength) + { + m_downloadSize += dataLength; + if (!m_downloadEvents.contains(ReceivedData)) + m_downloadEvents.append(ReceivedData); + } + + virtual void finished(WebKitDownload* download) + { + m_downloadEvents.append(Finished); + g_main_loop_quit(m_mainLoop); + } + + virtual void failed(WebKitDownload* download, GError* error) + { + m_downloadEvents.append(Failed); + } + + virtual void decideDestination(WebKitDownload* download, const gchar* suggestedFilename) + { + GOwnPtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL)); + GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); + webkit_download_set_destination(download, destinationURI.get()); + } + + void waitUntilDownloadFinishes() + { + g_main_loop_run(m_mainLoop); + } + + void checkDestinationAndDeleteFile(WebKitDownload* download, const char* expectedName) + { + if (!webkit_download_get_destination(download)) + return; + GRefPtr<GFile> destFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(download))); + GOwnPtr<char> destBasename(g_file_get_basename(destFile.get())); + g_assert_cmpstr(destBasename.get(), ==, expectedName); + + g_file_delete(destFile.get(), 0, 0); + } + + WebKitWebContext* m_webContext; + GMainLoop* m_mainLoop; + Vector<DownloadEvent> m_downloadEvents; + guint64 m_downloadSize; +}; + +static CString getWebKit1TestResoucesDir() +{ + GOwnPtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Source", "WebKit", "gtk", "tests", "resources", NULL)); + return resourcesDir.get(); +} + +static void testDownloadLocalFile(DownloadTest* test, gconstpointer) +{ + GOwnPtr<char> sourcePath(g_build_filename(getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get())); + GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0)); + GOwnPtr<char> sourceURI(g_file_get_uri(source.get())); + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, sourceURI.get())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination); + g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData); + g_assert_cmpint(events[4], ==, DownloadTest::Finished); + + g_assert_cmpint(test->m_downloadSize, ==, g_file_info_get_size(sourceInfo.get())); + g_assert(webkit_download_get_destination(download.get())); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); + test->checkDestinationAndDeleteFile(download.get(), "test.pdf"); +} + +class DownloadErrorTest: public DownloadTest { +public: + MAKE_GLIB_TEST_FIXTURE(DownloadErrorTest); + + DownloadErrorTest() + : m_expectedError(WEBKIT_DOWNLOAD_ERROR_NETWORK) + { + } + + void receivedResponse(WebKitDownload* download) + { + DownloadTest::receivedResponse(download); + if (m_expectedError == WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER) + webkit_download_cancel(download); + } + + void createdDestination(WebKitDownload* download, const char* destination) + { + g_assert_not_reached(); + } + + void failed(WebKitDownload* download, GError* error) + { + g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, m_expectedError)); + DownloadTest::failed(download, error); + } + + void decideDestination(WebKitDownload* download, const gchar* suggestedFilename) + { + if (m_expectedError != WEBKIT_DOWNLOAD_ERROR_DESTINATION) { + DownloadTest::decideDestination(download, suggestedFilename); + return; + } + webkit_download_set_destination(download, "file:///foo/bar"); + } + + WebKitDownloadError m_expectedError; +}; + +static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) +{ + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK; + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, "file:///foo/bar")); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 3); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::Failed); + g_assert_cmpint(events[2], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; + GOwnPtr<char> path(g_build_filename(getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get())); + GOwnPtr<char> uri(g_file_get_uri(file.get())); + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), "bar"); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), "test.pdf"); +} + +static WebKitTestServer* kServer; +static const char* kServerSuggestedFilename = "webkit-downloaded-file"; + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + GOwnPtr<char> filePath(g_build_filename(getWebKit1TestResoucesDir().data(), path, NULL)); + char* contents; + gsize contentsLength; + if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) { + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); + soup_message_body_complete(message->response_body); + return; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + + GOwnPtr<char> contentDisposition(g_strdup_printf("filename=%s", kServerSuggestedFilename)); + soup_message_headers_append(message->response_headers, "Content-Disposition", contentDisposition.get()); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength); + + soup_message_body_complete(message->response_body); +} + +static void testDownloadRemoteFile(DownloadTest* test, gconstpointer) +{ + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination); + g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData); + g_assert_cmpint(events[4], ==, DownloadTest::Finished); + events.clear(); + + g_assert(webkit_download_get_destination(download.get())); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); + test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename); +} + +static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer) +{ + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK; + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, + kServer->getURIForPath("/foo").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + WebKitURIResponse* response = webkit_download_get_response(download.get()); + g_assert_cmpuint(webkit_uri_response_get_status_code(response), ==, 404); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), "bar"); + + test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; + download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); + test->waitUntilDownloadFinishes(); + + events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + events.clear(); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); + test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0); + g_assert(kTempDirectory); + + DownloadTest::add("Downloads", "local-file", testDownloadLocalFile); + DownloadErrorTest::add("Downloads", "local-file-error", testDownloadLocalFileError); + DownloadTest::add("Downloads", "remote-file", testDownloadRemoteFile); + DownloadErrorTest::add("Downloads", "remote-file-error", testDownloadRemoteFileError); +} + +void afterAll() +{ + delete kServer; + g_rmdir(kTempDirectory); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebLoaderClient.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp index aaa9ff873..3afa2b96f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp @@ -55,27 +55,26 @@ static void testLoadingError(LoadTrackingTest* test, gconstpointer) g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished); } -static void assertNormalLoadHappenedAndClearEvents(Vector<LoadTrackingTest::LoadEvents>& events) +static void assertNormalLoadHappened(Vector<LoadTrackingTest::LoadEvents>& events) { g_assert_cmpint(events.size(), ==, 3); g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted); g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished); - events.clear(); } static void testLoadHtml(LoadTrackingTest* test, gconstpointer) { test->loadHtml("<html><body>Hello WebKit-GTK+</body></html>", 0); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } static void testLoadPlainText(LoadTrackingTest* test, gconstpointer) { test->loadPlainText("Hello WebKit-GTK+"); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } static void testLoadRequest(LoadTrackingTest* test, gconstpointer) @@ -83,7 +82,7 @@ static void testLoadRequest(LoadTrackingTest* test, gconstpointer) GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal").data())); test->loadRequest(request.get()); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } class LoadStopTrackingTest : public LoadTrackingTest { @@ -126,16 +125,16 @@ static void testWebViewTitle(LoadTrackingTest* test, gconstpointer) static void testWebViewReload(LoadTrackingTest* test, gconstpointer) { // Check that nothing happens when there's nothing to reload. - webkit_web_view_reload(test->m_webView); + test->reload(); test->wait(0.25); // Wait for a quarter of a second. test->loadURI(kServer->getURIForPath("/normal").data()); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); - webkit_web_view_reload(test->m_webView); + test->reload(); test->waitUntilLoadFinished(); - assertNormalLoadHappenedAndClearEvents(test->m_loadEvents); + assertNormalLoadHappened(test->m_loadEvents); } static void testLoadProgress(LoadTrackingTest* test, gconstpointer) @@ -240,8 +239,8 @@ void beforeAll() kServer = new WebKitTestServer(); kServer->run(serverCallback); - LoadTrackingTest::add("WebKitWebLoaderClient", "loading-status", testLoadingStatus); - LoadTrackingTest::add("WebKitWebLoaderClient", "loading-error", testLoadingError); + LoadTrackingTest::add("WebKitWebView", "loading-status", testLoadingStatus); + LoadTrackingTest::add("WebKitWebView", "loading-error", testLoadingError); LoadTrackingTest::add("WebKitWebView", "load-html", testLoadHtml); LoadTrackingTest::add("WebKitWebView", "load-plain-text", testLoadPlainText); LoadTrackingTest::add("WebKitWebView", "load-request", testLoadRequest); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp new file mode 100644 index 000000000..3db9094a5 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitAccessibility.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "TestMain.h" +#include "WebViewTest.h" + +// The libatspi headers don't use G_BEGIN_DECLS +extern "C" { +#include <atspi/atspi.h> +} + +#include <errno.h> +#include <fcntl.h> +#include <glib.h> +#include <signal.h> +#include <unistd.h> +#include <wtf/PassRefPtr.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> + +// Name of the test server application creating the webView object. +static const char* kTestServerAppName = "AccessibilityTestServer"; + +// Max seconds to wait for the test server before inspecting it. +static const int kMaxWaitForChild = 5; + +// The PID for the test server running, so we can kill it if needed. +static GPid kChildProcessPid = 0; + +// Whether the child has replied and it's ready. +static bool kChildIsReady = false; + +static void stopTestServer() +{ + // Do nothing if there's no server running. + if (!kChildProcessPid) + return; + + g_spawn_close_pid(kChildProcessPid); + kill(kChildProcessPid, SIGTERM); + kChildProcessPid = 0; +} + +static void sigAbortHandler(int sigNum) +{ + // Just stop the test server if SIGABRT was received. + stopTestServer(); +} + +static gpointer testServerMonitorThreadFunc(gpointer) +{ + // Wait for the specified timeout to happen. + g_usleep(kMaxWaitForChild * G_USEC_PER_SEC); + + // Kill the child process if not ready yet. + if (!kChildIsReady) + stopTestServer(); + + g_thread_exit(0); + return 0; +} + +static void startTestServerMonitor() +{ + kChildIsReady = false; + +#if (!GLIB_CHECK_VERSION(2, 31, 0)) + g_thread_create(testServerMonitorThreadFunc, 0, FALSE, 0); +#else + g_thread_new("TestServerMonitor", testServerMonitorThreadFunc, 0); +#endif +} + +static void startTestServer() +{ + // Prepare argv[] for spawning the server process. + GOwnPtr<char> testServerPath(g_build_filename(WEBKIT_EXEC_PATH, "WebKit2APITests", kTestServerAppName, NULL)); + + char* testServerArgv[2]; + testServerArgv[0] = testServerPath.get(); + testServerArgv[1] = 0; + + // Spawn the server, getting its stdout file descriptor to set a + // communication channel, so we know when it's ready. + int childStdout = 0; + if (!g_spawn_async_with_pipes(0, testServerArgv, 0, static_cast<GSpawnFlags>(0), 0, 0, + &kChildProcessPid, 0, &childStdout, 0, 0)) { + close(childStdout); + return; + } + + // Start monitoring the test server (in a separate thread) to + // ensure we don't block on the child process more than a timeout. + startTestServerMonitor(); + + char msg[2]; + GIOChannel* ioChannel = g_io_channel_unix_new(childStdout); + if (g_io_channel_read_chars(ioChannel, msg, 2, 0, 0) == G_IO_STATUS_NORMAL) { + // Check whether the server sent a message saying it's ready + // and store the result globally, so the monitor can see it. + kChildIsReady = msg[0] == 'O' && msg[1] == 'K'; + } + g_io_channel_unref(ioChannel); + close(childStdout); + + // The timeout was reached and the server is not ready yet, so + // stop it inmediately, and let the unit tests fail. + if (!kChildIsReady) + stopTestServer(); +} + +static void checkAtspiAccessible(AtspiAccessible* accessible, const char* targetName, AtspiRole targetRole) +{ + g_assert(ATSPI_IS_ACCESSIBLE(accessible)); + + GOwnPtr<char> name(atspi_accessible_get_name(accessible, 0)); + g_assert_cmpstr(targetName, ==, name.get()); + g_assert_cmpint(targetRole, ==, atspi_accessible_get_role(accessible, 0)); +} + +static GRefPtr<AtspiAccessible> findTestServerApplication() +{ + // Only one desktop is supported by ATSPI at the moment. + GRefPtr<AtspiAccessible> desktop = adoptGRef(atspi_get_desktop(0)); + + // Look for the server application in the list of apps. + GRefPtr<AtspiAccessible> current; + int childCount = atspi_accessible_get_child_count(desktop.get(), 0); + for (int i = 0; i < childCount; i++) { + current = adoptGRef(atspi_accessible_get_child_at_index(desktop.get(), i, 0)); + if (!g_strcmp0(atspi_accessible_get_name(current.get(), 0), kTestServerAppName)) + return current; + } + + return 0; +} + +static void testAtspiBasicHierarchy(WebViewTest* test, gconstpointer) +{ + // The test server's accessibility object (UI Process). + GRefPtr<AtspiAccessible> testServerApp = findTestServerApplication(); + g_assert(ATSPI_IS_ACCESSIBLE(testServerApp.get())); + checkAtspiAccessible(testServerApp.get(), "AccessibilityTestServer", ATSPI_ROLE_APPLICATION); + + // The main window's accessibility object (UI Process). + GRefPtr<AtspiAccessible> currentParent = testServerApp; + GRefPtr<AtspiAccessible> currentChild = adoptGRef(atspi_accessible_get_child_at_index(currentParent.get(), 0, 0)); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_FRAME); + + // The WebView's accessibility object (UI Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_FILLER); + + // The WebPage's accessibility object (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_FILLER); + + // HTML root element's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + + // HTML body's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_DOCUMENT_FRAME); + + // HTML H1's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "This is a test", ATSPI_ROLE_HEADING); + + // HTML first paragraph's accessible element (Web Process). + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 1, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_PARAGRAPH); + + // HTML second paragraph's accessible element (Web Process). + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 2, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "", ATSPI_ROLE_PARAGRAPH); + + // HTML link's accessible element (Web Process). + currentParent = currentChild; + currentChild = atspi_accessible_get_child_at_index(currentParent.get(), 0, 0); + g_assert(ATSPI_IS_ACCESSIBLE(currentChild.get())); + checkAtspiAccessible(currentChild.get(), "a link", ATSPI_ROLE_LINK); +} + +void beforeAll() +{ + // We install a handler to ensure that we kill the child process + // if the parent dies because of whatever the reason is. + signal(SIGABRT, sigAbortHandler); + + // Start the accessibility test server and load the tests. + startTestServer(); + WebViewTest::add("WebKitAccessibility", "atspi-basic-hierarchy", testAtspiBasicHierarchy); +} + +void afterAll() +{ + // Ensure we stop the server. + stopTestServer(); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp new file mode 100644 index 000000000..7cbe4e7f9 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitPolicyClient.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "LoadTrackingTest.h" +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +class PolicyClientTest: public LoadTrackingTest { +public: + MAKE_GLIB_TEST_FIXTURE(PolicyClientTest); + + enum PolicyDecisionResponse { + Use, + Ignore, + Download, + None + }; + + PolicyClientTest() + : LoadTrackingTest() + , m_policyDecisionResponse(None) + , m_policyDecisionTypeFilter(0) + , m_respondToPolicyDecisionAsynchronously(false) + , m_haltMainLoopAfterMakingDecision(false) + { + g_signal_connect(m_webView, "decide-policy", G_CALLBACK(decidePolicyCallback), this); + } + + static gboolean quitMainLoopLater(GMainLoop* loop) + { + g_main_loop_quit(loop); + return FALSE; + } + + static void respondToPolicyDecision(PolicyClientTest* test, WebKitPolicyDecision* decision) + { + switch (test->m_policyDecisionResponse) { + case Use: + webkit_policy_decision_use(decision); + break; + case Ignore: + webkit_policy_decision_ignore(decision); + break; + case Download: + webkit_policy_decision_download(decision); + break; + case None: + break; + } + + if (test->m_haltMainLoopAfterMakingDecision) + g_idle_add(reinterpret_cast<GSourceFunc>(quitMainLoopLater), test->m_mainLoop); + } + + static gboolean respondToPolicyDecisionLater(PolicyClientTest* test) + { + respondToPolicyDecision(test, test->m_previousPolicyDecision.get()); + test->m_previousPolicyDecision = 0; + return FALSE; + } + + static gboolean decidePolicyCallback(WebKitWebView* webView, WebKitPolicyDecision* decision, WebKitPolicyDecisionType type, PolicyClientTest* test) + { + if (test->m_policyDecisionTypeFilter != type) + return FALSE; + + test->m_previousPolicyDecision = decision; + if (test->m_respondToPolicyDecisionAsynchronously) { + g_idle_add(reinterpret_cast<GSourceFunc>(respondToPolicyDecisionLater), test); + return TRUE; + } + + respondToPolicyDecision(test, decision); + + // We return FALSE here to ensure that the default policy decision + // handler doesn't override whatever we use here. + return FALSE; + } + + PolicyDecisionResponse m_policyDecisionResponse; + int m_policyDecisionTypeFilter; + bool m_respondToPolicyDecisionAsynchronously; + bool m_haltMainLoopAfterMakingDecision; + GRefPtr<WebKitPolicyDecision> m_previousPolicyDecision; +}; + +static void testNavigationPolicy(PolicyClientTest* test, gconstpointer) +{ + test->m_policyDecisionTypeFilter = WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION; + + test->m_policyDecisionResponse = PolicyClientTest::Use; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 3); + + // Ideally we'd like to have a more intensive test here, but it's still pretty tricky + // to trigger different types of navigations with the GTK+ WebKit2 API. + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(test->m_previousPolicyDecision.get()); + g_assert_cmpint(webkit_navigation_policy_decision_get_navigation_type(decision), ==, WEBKIT_NAVIGATION_TYPE_OTHER); + g_assert_cmpint(webkit_navigation_policy_decision_get_mouse_button(decision), ==, 0); + g_assert_cmpint(webkit_navigation_policy_decision_get_modifiers(decision), ==, 0); + g_assert_cmpstr(webkit_navigation_policy_decision_get_frame_name(decision), ==, 0); + WebKitURIRequest* request = webkit_navigation_policy_decision_get_request(decision); + g_assert_cmpstr(webkit_uri_request_get_uri(request), ==, "http://webkitgtk.org/"); + + test->m_policyDecisionResponse = PolicyClientTest::Use; + test->m_respondToPolicyDecisionAsynchronously = true; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 3); + + // If we are waiting until load completion, it will never complete if we ignore the + // navigation. So we tell the main loop to quit sometime later. + test->m_policyDecisionResponse = PolicyClientTest::Ignore; + test->m_respondToPolicyDecisionAsynchronously = false; + test->m_haltMainLoopAfterMakingDecision = true; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 0); + + test->m_policyDecisionResponse = PolicyClientTest::Ignore; + test->loadHtml("<html/>", "http://webkitgtk.org/"); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_loadEvents.size(), ==, 0); +} + +struct CreateCallbackData { + bool triedToOpenWindow; + GMainLoop* mainLoop; +}; + +static WebKitWebView* createCallback(WebKitWebView* webView, CreateCallbackData* data) +{ + data->triedToOpenWindow = true; + g_main_loop_quit(data->mainLoop); + return 0; +} + +static void testNewWindowPolicy(PolicyClientTest* test, gconstpointer) +{ + static const char* windowOpeningHTML = + "<html><body>" + " <a id=\"link\" href=\"http://www.google.com\" target=\"_blank\">Link</a>" + " <script>" + " var event = document.createEvent('MouseEvents');" + " event.initEvent('click', true, false);" + " document.getElementById('link').dispatchEvent(event);" + " </script>" + "</body></html>"; + test->m_policyDecisionTypeFilter = WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION; + webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(test->m_webView), TRUE); + + CreateCallbackData data; + data.triedToOpenWindow = false; + data.mainLoop = test->m_mainLoop; + + g_signal_connect(test->m_webView, "create", G_CALLBACK(createCallback), &data); + test->m_policyDecisionResponse = PolicyClientTest::Use; + test->loadHtml(windowOpeningHTML, "http://webkitgtk.org/"); + test->wait(1); + g_assert(data.triedToOpenWindow); + + WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(test->m_previousPolicyDecision.get()); + g_assert_cmpstr(webkit_navigation_policy_decision_get_frame_name(decision), ==, "_blank"); + + // Using a short timeout is a bit ugly here, but it's hard to get around because if we block + // the new window signal we cannot halt the main loop in the create callback. If we + // halt the main loop in the policy decision, the create callback never executes. + data.triedToOpenWindow = false; + test->m_policyDecisionResponse = PolicyClientTest::Ignore; + test->loadHtml(windowOpeningHTML, "http://webkitgtk.org/"); + test->wait(.2); + g_assert(!data.triedToOpenWindow); +} + +void beforeAll() +{ + PolicyClientTest::add("WebKitPolicyClient", "navigation-policy", testNavigationPolicy); + PolicyClientTest::add("WebKitPolicyClient", "new-window-policy", testNewWindowPolicy); +} + +void afterAll() +{ +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp index 93e9c9cd2..cce7e1fe7 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -184,6 +184,11 @@ static void testWebKitSettings(Test*, gconstpointer) webkit_settings_set_enable_fullscreen(settings, TRUE); g_assert(webkit_settings_get_enable_fullscreen(settings)); + // Print backgrounds is enabled by default + g_assert(webkit_settings_get_print_backgrounds(settings)); + webkit_settings_set_print_backgrounds(settings, FALSE); + g_assert(!webkit_settings_get_print_backgrounds(settings)); + g_object_unref(G_OBJECT(settings)); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp index dfd9da475..099eabda5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp @@ -48,7 +48,10 @@ void WebViewTest::loadURI(const char* uri) void WebViewTest::loadHtml(const char* html, const char* baseURI) { - m_activeURI = "about:blank"; + if (!baseURI) + m_activeURI = "about:blank"; + else + m_activeURI = baseURI; webkit_web_view_load_html(m_webView, html, baseURI); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h index 662354032..882e8b224 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h @@ -31,10 +31,10 @@ public: WebViewTest(); virtual ~WebViewTest(); - void loadURI(const char* uri); - void loadHtml(const char* html, const char* baseURI); - void loadPlainText(const char* plainText); - void loadRequest(WebKitURIRequest*); + virtual void loadURI(const char* uri); + virtual void loadHtml(const char* html, const char* baseURI); + virtual void loadPlainText(const char* plainText); + virtual void loadRequest(WebKitURIRequest*); void replaceContent(const char* html, const char* contentURI, const char* baseURI); void goBack(); void goForward(); diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index ab0e0a8f1..e9d892b54 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -26,6 +26,7 @@ #include <webkit2/WebKitBackForwardList.h> #include <webkit2/WebKitBackForwardListItem.h> #include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitDownload.h> #include <webkit2/WebKitEnumTypes.h> #include <webkit2/WebKitError.h> #include <webkit2/WebKitSettings.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list index 89c250e3e..5918d095a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list @@ -1,7 +1,13 @@ BOOLEAN:ENUM,STRING,POINTER +BOOLEAN:OBJECT +BOOLEAN:OBJECT,ENUM +BOOLEAN:OBJECT,STRING,POINTER +BOOLEAN:POINTER BOOLEAN:STRING BOOLEAN:STRING,POINTER BOOLEAN:STRING,STRING,POINTER +BOOLEAN:UINT64 +BOOLEAN:VOID OBJECT:VOID VOID:ENUM VOID:OBJECT,POINTER diff --git a/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.h b/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.h index 7836a546a..cbe34a1a9 100644 --- a/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.h +++ b/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.h @@ -26,12 +26,12 @@ #ifndef FindIndicatorWindow_h #define FindIndicatorWindow_h +#import "WebKitSystemInterface.h" +#import <WebCore/RunLoop.h> #import <wtf/Noncopyable.h> #import <wtf/PassOwnPtr.h> #import <wtf/RefPtr.h> #import <wtf/RetainPtr.h> -#import "RunLoop.h" -#import "WebKitSystemInterface.h" @class WKFindIndicatorWindowAnimation; @class WKView; @@ -68,7 +68,7 @@ private: WKWindowBounceAnimationContextRef m_bounceAnimationContext; RetainPtr<WKFindIndicatorWindowAnimation> m_bounceAnimation; - RunLoop::Timer<FindIndicatorWindow> m_startFadeOutTimer; + WebCore::RunLoop::Timer<FindIndicatorWindow> m_startFadeOutTimer; RetainPtr<WKFindIndicatorWindowAnimation> m_fadeOutAnimation; }; diff --git a/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextController.mm b/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextController.mm index 955b93045..2c4341b5d 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextController.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextController.mm @@ -243,6 +243,16 @@ static inline NSURL *autoreleased(WKURLRef url) return WKPaginationModeUnpaginated; } +- (void)setPaginationBehavesLikeColumns:(BOOL)behavesLikeColumns +{ + WKPageSetPaginationBehavesLikeColumns(self._pageRef, behavesLikeColumns); +} + +- (BOOL)paginationBehavesLikeColumns +{ + return WKPageGetPaginationBehavesLikeColumns(self._pageRef); +} + - (void)setPageLength:(CGFloat)pageLength { WKPageSetPageLength(self._pageRef, pageLength); diff --git a/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextControllerPrivate.h b/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextControllerPrivate.h index 3585642d3..c362c55c2 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextControllerPrivate.h +++ b/Source/WebKit2/UIProcess/API/mac/WKBrowsingContextControllerPrivate.h @@ -35,6 +35,9 @@ typedef NSUInteger WKBrowsingContextPaginationMode; @interface WKBrowsingContextController (Private) @property WKBrowsingContextPaginationMode paginationMode; +// Whether the column-break-{before,after} properties are respected instead of the +// page-break-{before,after} properties. +@property BOOL paginationBehavesLikeColumns; // Set to 0 to have the page length equal the view length. @property CGFloat pageLength; @property CGFloat gapBetweenPages; diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index 1e2509ba6..7d21e9b7f 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -40,7 +40,6 @@ #import "PDFViewController.h" #import "PageClientImpl.h" #import "PasteboardTypes.h" -#import "RunLoop.h" #import "TextChecker.h" #import "TextCheckerState.h" #import "TiledCoreAnimationDrawingAreaProxy.h" @@ -70,6 +69,7 @@ #import <WebCore/PlatformEventFactoryMac.h> #import <WebCore/PlatformScreen.h> #import <WebCore/Region.h> +#import <WebCore/RunLoop.h> #import <WebKitSystemInterface.h> #import <wtf/RefPtr.h> #import <wtf/RetainPtr.h> @@ -187,7 +187,14 @@ struct WKViewInterpretKeyEventsParameters { NSRect _windowBottomCornerIntersectionRect; unsigned _frameSizeUpdatesDisabledCount; + + // Whether the containing window of the WKView has a valid backing store. + // The window server invalidates the backing store whenever the window is resized or minimized. + // We use this flag to determine when we need to paint the background (white or clear) + // when the web process is unresponsive or takes too long to paint. + BOOL _windowHasValidBackingStore; } + @end @implementation WKViewData @@ -324,6 +331,9 @@ struct WKViewInterpretKeyEventsParameters { - (void)setFrameSize:(NSSize)size { + if (!NSEqualSizes(size, [self frame].size)) + _data->_windowHasValidBackingStore = NO; + [super setFrameSize:size]; if (![self frameSizeUpdatesDisabled]) @@ -1766,9 +1776,9 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl name:NSWindowDidMiniaturizeNotification object:window]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:window]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowFrameDidChange:) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidMove:) name:NSWindowDidMoveNotification object:window]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowFrameDidChange:) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidResize:) name:NSWindowDidResizeNotification object:window]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidOrderOffScreen:) name:@"NSWindowDidOrderOffScreenNotification" object:window]; @@ -1818,15 +1828,18 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl // update the active state first and then make it visible. If the view is about to be hidden, we hide it first and then // update the active state. if ([self window]) { + _data->_windowHasValidBackingStore = NO; _data->_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive); _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible | WebPageProxy::ViewIsInWindow); [self _updateWindowVisibility]; [self _updateWindowAndViewFrames]; - _data->_flagsChangedEventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSFlagsChangedMask handler:^(NSEvent *flagsChangedEvent) { - [self _postFakeMouseMovedEventForFlagsChangedEvent:flagsChangedEvent]; - return flagsChangedEvent; - }]; + if (!_data->_flagsChangedEventMonitor) { + _data->_flagsChangedEventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSFlagsChangedMask handler:^(NSEvent *flagsChangedEvent) { + [self _postFakeMouseMovedEventForFlagsChangedEvent:flagsChangedEvent]; + return flagsChangedEvent; + }]; + } [self _accessibilityRegisterUIProcessTokens]; } else { @@ -1883,6 +1896,8 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl - (void)_windowDidMiniaturize:(NSNotification *)notification { + _data->_windowHasValidBackingStore = NO; + [self _updateWindowVisibility]; } @@ -1891,8 +1906,15 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl [self _updateWindowVisibility]; } -- (void)_windowFrameDidChange:(NSNotification *)notification +- (void)_windowDidMove:(NSNotification *)notification { + [self _updateWindowAndViewFrames]; +} + +- (void)_windowDidResize:(NSNotification *)notification +{ + _data->_windowHasValidBackingStore = NO; + [self _updateWindowAndViewFrames]; } @@ -1919,6 +1941,7 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl if (oldBackingScaleFactor == newBackingScaleFactor) return; + _data->_windowHasValidBackingStore = NO; _data->_page->setIntrinsicDeviceScaleFactor(newBackingScaleFactor); } @@ -1963,9 +1986,15 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I IntRect rect = enclosingIntRect(rectsBeingDrawn[i]); drawingArea->paint(context, rect, unpaintedRegion); - Vector<IntRect> unpaintedRects = unpaintedRegion.rects(); - for (size_t i = 0; i < unpaintedRects.size(); ++i) - drawPageBackground(context, _data->_page.get(), unpaintedRects[i]); + // If the window doesn't have a valid backing store, we need to fill the parts of the page that we + // didn't paint with the background color (white or clear), to avoid garbage in those areas. + if (!_data->_windowHasValidBackingStore) { + Vector<IntRect> unpaintedRects = unpaintedRegion.rects(); + for (size_t i = 0; i < unpaintedRects.size(); ++i) + drawPageBackground(context, _data->_page.get(), unpaintedRects[i]); + + _data->_windowHasValidBackingStore = YES; + } } } else drawPageBackground(context, _data->_page.get(), enclosingIntRect(rect)); @@ -2119,9 +2148,9 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I } #if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) -- (void)quickLookPreviewItemsAtWindowLocation:(NSPoint)location +- (void)quickLookWithEvent:(NSEvent *)event { - NSPoint locationInViewCoordinates = [self convertPoint:location fromView:nil]; + NSPoint locationInViewCoordinates = [self convertPoint:[event locationInWindow] fromView:nil]; _data->_page->performDictionaryLookupAtLocation(FloatPoint(locationInViewCoordinates.x, locationInViewCoordinates.y)); } #endif @@ -2250,12 +2279,12 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (NSRect)_convertToDeviceSpace:(NSRect)rect { - return toDeviceSpace(rect, [self window]); + return toDeviceSpace(rect, [self window], _data->_page->deviceScaleFactor()); } - (NSRect)_convertToUserSpace:(NSRect)rect { - return toUserSpace(rect, [self window]); + return toUserSpace(rect, [self window], _data->_page->deviceScaleFactor()); } // Any non-zero value will do, but using something recognizable might help us debug some day. diff --git a/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply.cpp b/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply.cpp index 4e8810302..38ac7b909 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply.cpp @@ -30,151 +30,95 @@ using namespace WebKit; QQuickNetworkReply::QQuickNetworkReply(QObject* parent) : QObject(parent) - , m_networkReplyData(adoptRef(new WebKit::QtNetworkReplyData)) + , m_networkReplyData(adoptRef(new WebKit::QtRefCountedNetworkReplyData)) { Q_ASSERT(parent); } QString QQuickNetworkReply::contentType() const { - return m_networkReplyData->m_contentType; + return m_networkReplyData->data().m_contentType; } void QQuickNetworkReply::setContentType(const QString& contentType) { - m_networkReplyData->m_contentType = contentType; + m_networkReplyData->data().m_contentType = contentType; } -QNetworkAccessManager::Operation QQuickNetworkReply::operation() const +QVariant QQuickNetworkReply::data() const { - return m_networkReplyData->m_operation; + return m_data; } -void QQuickNetworkReply::setOperation(QNetworkAccessManager::Operation operation) +void QQuickNetworkReply::setData(const QVariant& data) { - m_networkReplyData->m_operation = operation; + m_data = data; } -QString QQuickNetworkReply::contentDisposition() const -{ - return m_networkReplyData->m_contentDisposition; -} - -void QQuickNetworkReply::setContentDisposition(const QString& disposition) -{ - m_networkReplyData->m_contentDisposition = disposition; -} - -QString QQuickNetworkReply::location() const -{ - return m_networkReplyData->m_location; -} - -void QQuickNetworkReply::setLocation(const QString& location) -{ - m_networkReplyData->m_location = location; -} - -QString QQuickNetworkReply::lastModified() const -{ - return QDateTime::fromMSecsSinceEpoch(m_networkReplyData->m_lastModified).toString(Qt::ISODate); -} - -void QQuickNetworkReply::setLastModified(const QString& lastModified) -{ - m_networkReplyData->m_lastModified = QDateTime::fromString(lastModified, Qt::ISODate).toMSecsSinceEpoch(); -} - -QString QQuickNetworkReply::cookie() const -{ - return m_networkReplyData->m_cookie; -} - -void QQuickNetworkReply::setCookie(const QString& cookie) -{ - m_networkReplyData->m_cookie = cookie; -} - -QString QQuickNetworkReply::userAgent() const -{ - return m_networkReplyData->m_userAgent; -} - -void QQuickNetworkReply::setUserAgent(const QString& userAgent) -{ - m_networkReplyData->m_userAgent = userAgent; -} - -QString QQuickNetworkReply::server() const -{ - return m_networkReplyData->m_server; -} - -void QQuickNetworkReply::setServer(const QString& server) -{ - m_networkReplyData->m_server = server; -} - -QString QQuickNetworkReply::data() const -{ - if (m_networkReplyData->m_dataHandle.isNull()) - return QString(); - RefPtr<SharedMemory> sm = SharedMemory::create(m_networkReplyData->m_dataHandle, SharedMemory::ReadOnly); - if (!sm) - return QString(); - - uint64_t stringLength = m_networkReplyData->m_contentLength / sizeof(UChar); - return QString(reinterpret_cast<const QChar*>(sm->data()), stringLength); -} - -void QQuickNetworkReply::setData(const QString& data) +void QQuickNetworkReply::send() { - // This function can be called several times. In this case the previous SharedMemory handles - // will be overwritten and the previously allocated SharedMemory will die with the last handle. - m_networkReplyData->m_contentLength = 0; + if (m_data.isNull()) + return; - if (data.isNull()) + uint64_t smLength = 0; + const void* ptrData = 0; + QString stringData; + QByteArray byteArrayData; + if (m_data.type() == QVariant::String) { + stringData = m_data.toString(); + ptrData = reinterpret_cast<const void*>(stringData.constData()); + smLength = sizeof(QChar) * stringData.length(); + setContentType(QLatin1String("text/html; charset=utf-16")); + } else { + if (!m_data.canConvert<QByteArray>()) + return; + byteArrayData = m_data.toByteArray(); + ptrData = byteArrayData.data(); + smLength = byteArrayData.size(); + } + + if (contentType().isEmpty()) { + qWarning("QQuickNetworkReply::send - Cannot send raw data without a content type being specified!"); return; - const UChar* ucharData = reinterpret_cast<const UChar*>(data.constData()); - uint64_t smLength = sizeof(UChar) * data.length(); + } - RefPtr<SharedMemory> sm = SharedMemory::create(smLength); - if (!sm) + WTF::RefPtr<WebKit::SharedMemory> sharedMemory = SharedMemory::create(smLength); + if (!sharedMemory) return; // The size of the allocated shared memory can be bigger than requested. // Usually the size will be rounded up to the next multiple of a page size. - memcpy(sm->data(), ucharData, smLength); + memcpy(sharedMemory->data(), ptrData, smLength); - if (!sm->createHandle(m_networkReplyData->m_dataHandle, SharedMemory::ReadOnly)) - return; - m_networkReplyData->m_contentLength = smLength; + if (sharedMemory->createHandle(m_networkReplyData->data().m_dataHandle, SharedMemory::ReadOnly)) { + m_networkReplyData->data().m_contentLength = smLength; + if (m_webViewExperimental) + m_webViewExperimental.data()->sendApplicationSchemeReply(this); + } + + // After sending the reply data, we have to reinitialize the m_networkReplyData, + // to make sure we have a fresh SharesMemory::Handle. + m_networkReplyData = adoptRef(new WebKit::QtRefCountedNetworkReplyData); } -void QQuickNetworkReply::send() +void QQuickNetworkReply::setWebViewExperimental(QQuickWebViewExperimental* webViewExperimental) { - QObject* schemeParent = parent()->parent(); - if (!schemeParent) - return; - QQuickWebViewExperimental* webViewExperimental = qobject_cast<QQuickWebViewExperimental*>(schemeParent->parent()); - if (!webViewExperimental) - return; - webViewExperimental->sendApplicationSchemeReply(this); + m_webViewExperimental = webViewExperimental; } -WTF::RefPtr<WebKit::QtNetworkRequestData> QQuickNetworkReply::networkRequestData() const +WebKit::QtRefCountedNetworkRequestData* QQuickNetworkReply::networkRequestData() const { - return m_networkRequestData; + return m_networkRequestData.get(); } -void QQuickNetworkReply::setNetworkRequestData(WTF::RefPtr<WebKit::QtNetworkRequestData> data) +void QQuickNetworkReply::setNetworkRequestData(WTF::PassRefPtr<WebKit::QtRefCountedNetworkRequestData> data) { m_networkRequestData = data; - m_networkReplyData->m_replyUuid = data->m_replyUuid; + m_networkReplyData->data().m_replyUuid = m_networkRequestData->data().m_replyUuid; } -WTF::RefPtr<WebKit::QtNetworkReplyData> QQuickNetworkReply::networkReplyData() const +WebKit::QtRefCountedNetworkReplyData* QQuickNetworkReply::networkReplyData() const { - return m_networkReplyData; + return m_networkReplyData.get(); } #include "moc_qquicknetworkreply_p.cpp" diff --git a/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h b/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h index ffe45f3c9..1007f3a78 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h @@ -23,50 +23,42 @@ #include "QtNetworkReplyData.h" #include "QtNetworkRequestData.h" +#include "qquickwebview_p.h" +#include "SharedMemory.h" #include "qwebkitglobal.h" #include <QNetworkAccessManager> #include <QObject> +#include <QWeakPointer> #include <QtDeclarative/qdeclarativelist.h> #include <QtQuick/qquickitem.h> class QWEBKIT_EXPORT QQuickNetworkReply : public QObject { Q_OBJECT Q_PROPERTY(QString contentType READ contentType WRITE setContentType) - Q_PROPERTY(QString data READ data WRITE setData) + Q_PROPERTY(QVariant data READ data WRITE setData) Q_ENUMS(QNetworkAccessManager::Operation) public: QQuickNetworkReply(QObject* parent); QString contentType() const; void setContentType(const QString&); - QNetworkAccessManager::Operation operation() const; - void setOperation(QNetworkAccessManager::Operation); - QString contentDisposition() const; - void setContentDisposition(const QString&); - QString location() const; - void setLocation(const QString&); - QString lastModified() const; - void setLastModified(const QString&); - QString cookie() const; - void setCookie(const QString&); - QString userAgent() const; - void setUserAgent(const QString&); - QString server() const; - void setServer(const QString&); - QString data() const; - void setData(const QString& data); + QVariant data() const; + void setData(const QVariant& data); - WTF::RefPtr<WebKit::QtNetworkRequestData> networkRequestData() const; - void setNetworkRequestData(WTF::RefPtr<WebKit::QtNetworkRequestData> data); - WTF::RefPtr<WebKit::QtNetworkReplyData> networkReplyData() const; + void setWebViewExperimental(QQuickWebViewExperimental*); + WebKit::QtRefCountedNetworkRequestData* networkRequestData() const; + void setNetworkRequestData(WTF::PassRefPtr<WebKit::QtRefCountedNetworkRequestData> data); + WebKit::QtRefCountedNetworkReplyData* networkReplyData() const; public Q_SLOTS: void send(); private: - WTF::RefPtr<WebKit::QtNetworkRequestData> m_networkRequestData; - WTF::RefPtr<WebKit::QtNetworkReplyData> m_networkReplyData; + WTF::RefPtr<WebKit::QtRefCountedNetworkRequestData> m_networkRequestData; + WTF::RefPtr<WebKit::QtRefCountedNetworkReplyData> m_networkReplyData; + QVariant m_data; + QWeakPointer<QQuickWebViewExperimental> m_webViewExperimental; }; QML_DECLARE_TYPE(QQuickNetworkReply) diff --git a/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest.cpp b/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest.cpp new file mode 100644 index 000000000..152ef4e5d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Zeno Albisser <zeno@webkit.org> + * + * 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 program 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 program; 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 "qquicknetworkrequest_p.h" + +#include "QtNetworkRequestData.h" +#include "qquickwebview_p.h" + +using namespace WebKit; + +QQuickNetworkRequest::QQuickNetworkRequest(QObject* parent) + : QObject(parent) +{ + Q_ASSERT(parent); +} + +void QQuickNetworkRequest::setNetworkRequestData(WTF::PassRefPtr<WebKit::QtRefCountedNetworkRequestData> data) +{ + m_networkRequestData = data; +} + +QUrl QQuickNetworkRequest::url() const +{ + if (m_networkRequestData) + return QUrl(m_networkRequestData->data().m_urlString); + return QUrl(); +} + +#include "moc_qquicknetworkrequest_p.cpp" + diff --git a/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h b/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h index 113114c87..7df66f569 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h @@ -21,6 +21,8 @@ #ifndef qquicknetworkrequest_p_h #define qquicknetworkrequest_p_h +#include "QtNetworkRequestData.h" +#include "RefPtr.h" #include "qwebkitglobal.h" #include <QObject> #include <QtDeclarative/qdeclarativelist.h> @@ -28,20 +30,17 @@ class QWEBKIT_EXPORT QQuickNetworkRequest : public QObject { Q_OBJECT - Q_PROPERTY(QString url READ url) + Q_PROPERTY(QUrl url READ url) public: - QQuickNetworkRequest(QObject* parent) - : QObject(parent) - { - Q_ASSERT(parent); - } + QQuickNetworkRequest(QObject* parent); - QString url() const { return m_url; } - void setUrl(const QString& url) { m_url = url; } + void setNetworkRequestData(WTF::PassRefPtr<WebKit::QtRefCountedNetworkRequestData> data); + + QUrl url() const; private: - QString m_url; + WTF::RefPtr<WebKit::QtRefCountedNetworkRequestData> m_networkRequestData; }; QML_DECLARE_TYPE(QQuickNetworkRequest) diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp index b5db3938f..206ba2522 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp @@ -30,9 +30,9 @@ #include <QtQuick/QSGGeometryNode> #include <QtQuick/QSGMaterial> -QQuickWebPage::QQuickWebPage(QQuickItem* parent) - : QQuickItem(parent) - , d(new QQuickWebPagePrivate(this)) +QQuickWebPage::QQuickWebPage(QQuickWebView* viewportItem) + : QQuickItem(viewportItem) + , d(new QQuickWebPagePrivate(this, viewportItem)) { setFlag(ItemHasContents); @@ -62,8 +62,9 @@ void QQuickWebPage::geometryChanged(const QRectF& newGeometry, const QRectF& old d->setDrawingAreaSize(newGeometry.size().toSize()); } -QQuickWebPagePrivate::QQuickWebPagePrivate(QQuickWebPage* q) +QQuickWebPagePrivate::QQuickWebPagePrivate(QQuickWebPage* q, QQuickWebView* viewportItem) : q(q) + , viewportItem(viewportItem) , webPageProxy(0) , sgUpdateQueue(q) , paintingIsInitialized(false) @@ -76,7 +77,7 @@ QQuickWebPagePrivate::QQuickWebPagePrivate(QQuickWebPage* q) void QQuickWebPagePrivate::initialize(WebKit::WebPageProxy* webPageProxy) { this->webPageProxy = webPageProxy; - eventHandler.reset(new QtWebPageEventHandler(toAPI(webPageProxy), q)); + eventHandler.reset(new QtWebPageEventHandler(toAPI(webPageProxy), q, viewportItem)); } static float computeEffectiveOpacity(const QQuickItem* item) @@ -99,6 +100,12 @@ void QQuickWebPagePrivate::setDrawingAreaSize(const QSize& size) drawingArea->setSize(WebCore::IntSize(size), WebCore::IntSize()); } +void QQuickWebPagePrivate::paint(QPainter* painter) +{ + if (webPageProxy->drawingArea()) + webPageProxy->drawingArea()->paintLayerTree(painter); +} + void QQuickWebPagePrivate::paintToCurrentGLContext() { if (!q->isVisible()) @@ -117,23 +124,7 @@ void QQuickWebPagePrivate::paintToCurrentGLContext() if (!drawingArea) return; - // Make sure that no GL error code stays from previous QT operations. - glGetError(); - - glEnable(GL_SCISSOR_TEST); - ASSERT(!glGetError()); - const int left = clipRect.left(); - const int width = clipRect.width(); - const int bottom = q->canvas()->height() - (clipRect.bottom() + 1); - const int height = clipRect.height(); - - glScissor(left, bottom, width, height); - ASSERT(!glGetError()); - - drawingArea->paintToCurrentGLContext(transform, opacity); - - glDisable(GL_SCISSOR_TEST); - ASSERT(!glGetError()); + drawingArea->paintToCurrentGLContext(transform, opacity, clipRect); } struct PageProxyMaterial; diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h index f797810f6..bf44b9dc7 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h @@ -27,6 +27,7 @@ #include <QtQuick/QQuickItem> class QQuickWebPagePrivate; +class QQuickWebView; class QtWebPageEventHandler; class QWebPreferences; @@ -37,7 +38,7 @@ class QtSGUpdateQueue; class QWEBKIT_EXPORT QQuickWebPage : public QQuickItem { Q_OBJECT public: - QQuickWebPage(QQuickItem* parent = 0); + QQuickWebPage(QQuickWebView* view = 0); virtual ~QQuickWebPage(); void setContentSize(const QSizeF& size); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h index 3b58eb510..0c17aa5b5 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h @@ -34,7 +34,7 @@ class QtWebPageEventHandler; class QQuickWebPagePrivate { public: - QQuickWebPagePrivate(QQuickWebPage* q); + QQuickWebPagePrivate(QQuickWebPage* q, QQuickWebView* viewportItem); ~QQuickWebPagePrivate(); void initialize(WebKit::WebPageProxy*); @@ -43,10 +43,12 @@ public: void updateSize(); void paintToCurrentGLContext(); + void paint(QPainter*); void resetPaintNode(); QScopedPointer<QtWebPageEventHandler> eventHandler; QQuickWebPage* const q; + QQuickWebView* const viewportItem; WebKit::WebPageProxy* webPageProxy; WebKit::QtSGUpdateQueue sgUpdateQueue; bool paintingIsInitialized; diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp index 187b9b4ca..5712ca593 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp @@ -34,6 +34,7 @@ #include "WebPreferences.h" #include "qquicknetworkreply_p.h" +#include "qquicknetworkrequest_p.h" #include "qquickwebpage_p_p.h" #include "qquickwebview_p_p.h" #include "qwebdownloaditem_p_p.h" @@ -47,19 +48,26 @@ #include <QDeclarativeEngine> #include <QFileDialog> #include <QtQuick/QQuickCanvas> +#include <WebCore/IntPoint.h> +#include <WebCore/IntRect.h> #include <WKOpenPanelResultListener.h> #include <wtf/text/WTFString.h> +using namespace WebCore; + QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport) : q_ptr(viewport) , alertDialog(0) , confirmDialog(0) , promptDialog(0) + , authenticationDialog(0) + , certificateVerificationDialog(0) , itemSelector(0) , postTransitionState(adoptPtr(new PostTransitionState(this))) , isTransitioningToNewPage(false) , pageIsSuspended(false) , m_navigatorQtObjectEnabled(false) + , m_renderToOffscreenBuffer(false) { viewport->setFlags(QQuickItem::ItemClipsChildrenToShape); QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged())); @@ -100,6 +108,7 @@ void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pa // Any page setting should preferrable be set before creating the page. setUseTraditionalDesktopBehaviour(false); webPageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true); + webPageProxy->pageGroup()->preferences()->setForceCompositingMode(true); pageClient.initialize(q_ptr, pageViewPrivate->eventHandler.data(), &undoController); webPageProxy->initializeWebPage(); @@ -128,10 +137,12 @@ void QQuickWebViewPrivate::initializeDesktop(QQuickWebView* viewport) QObject::disconnect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), viewport, SLOT(_q_suspend())); QObject::disconnect(interactionEngine.data(), SIGNAL(contentResumeRequested()), viewport, SLOT(_q_resume())); QObject::disconnect(interactionEngine.data(), SIGNAL(viewportTrajectoryVectorChanged(const QPointF&)), viewport, SLOT(_q_viewportTrajectoryVectorChanged(const QPointF&))); + QObject::disconnect(interactionEngine.data(), SIGNAL(visibleContentRectAndScaleChanged()), viewport, SLOT(_q_updateVisibleContentRectAndScale())); } interactionEngine.reset(0); pageView->d->eventHandler->setViewportInteractionEngine(0); enableMouseEvents(); + updateDesktopViewportSize(); } void QQuickWebViewPrivate::initializeTouch(QQuickWebView* viewport) @@ -142,7 +153,22 @@ void QQuickWebViewPrivate::initializeTouch(QQuickWebView* viewport) QObject::connect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), viewport, SLOT(_q_suspend())); QObject::connect(interactionEngine.data(), SIGNAL(contentResumeRequested()), viewport, SLOT(_q_resume())); QObject::connect(interactionEngine.data(), SIGNAL(viewportTrajectoryVectorChanged(const QPointF&)), viewport, SLOT(_q_viewportTrajectoryVectorChanged(const QPointF&))); - updateViewportSize(); + QObject::connect(interactionEngine.data(), SIGNAL(visibleContentRectAndScaleChanged()), viewport, SLOT(_q_updateVisibleContentRectAndScale())); + updateTouchViewportSize(); +} + +void QQuickWebViewPrivate::setNeedsDisplay() +{ + Q_Q(QQuickWebView); + if (renderToOffscreenBuffer()) { + // TODO: we can maintain a real image here and use it for pixel tests. Right now this is used only for running the rendering code-path while running tests. + QImage dummyImage(1, 1, QImage::Format_ARGB32); + QPainter painter(&dummyImage); + q->page()->d->paint(&painter); + return; + } + + q->page()->update(); } void QQuickWebViewPrivate::loadDidCommit() @@ -190,7 +216,7 @@ void QQuickWebViewPrivate::_q_resume() postTransitionState->apply(); } - updateVisibleContentRectAndScale(); + _q_updateVisibleContentRectAndScale(); } void QQuickWebViewPrivate::didChangeContentsSize(const QSize& newSize) @@ -274,7 +300,7 @@ void QQuickWebViewPrivate::handleDownloadRequest(DownloadProxy* download) context->downloadManager()->addDownload(download, downloadItem); } -void QQuickWebViewPrivate::updateVisibleContentRectAndScale() +void QQuickWebViewPrivate::_q_updateVisibleContentRectAndScale() { DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); if (!drawingArea) @@ -316,7 +342,19 @@ void QQuickWebViewPrivate::_q_onReceivedResponseFromDownload(QWebDownloadItem* d emit q->experimental()->downloadRequested(downloadItem); } -void QQuickWebViewPrivate::updateViewportSize() +void QQuickWebViewPrivate::updateDesktopViewportSize() +{ + Q_Q(QQuickWebView); + QSize viewportSize = q->boundingRect().size().toSize(); + pageView->setWidth(viewportSize.width()); + pageView->setHeight(viewportSize.height()); + // The fixed layout is handled by the FrameView and the drawing area doesn't behave differently + // wether its fixed or not. We still need to tell the drawing area which part of it + // has to be rendered on tiles, and in desktop mode it's all of it. + webPageProxy->drawingArea()->setVisibleContentsRectAndScale(IntRect(IntPoint(), viewportSize), 1); +} + +void QQuickWebViewPrivate::updateTouchViewportSize() { Q_Q(QQuickWebView); QSize viewportSize = q->boundingRect().size().toSize(); @@ -329,7 +367,7 @@ void QQuickWebViewPrivate::updateViewportSize() webPageProxy->setViewportSize(viewportSize); interactionEngine->applyConstraints(computeViewportConstraints()); - updateVisibleContentRectAndScale(); + _q_updateVisibleContentRectAndScale(); } void QQuickWebViewPrivate::PostTransitionState::apply() @@ -440,6 +478,45 @@ QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const return dialogRunner.result(); } +void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password) +{ + if (!authenticationDialog) + return; + + Q_Q(QQuickWebView); + QtDialogRunner dialogRunner; + if (!dialogRunner.initForAuthentication(authenticationDialog, q, hostname, realm, prefilledUsername)) + return; + + setViewInAttachedProperties(dialogRunner.dialog()); + + disableMouseEvents(); + dialogRunner.exec(); + enableMouseEvents(); + + username = dialogRunner.username(); + password = dialogRunner.password(); +} + +bool QQuickWebViewPrivate::handleCertificateVerificationRequest(const QString& hostname) +{ + if (!certificateVerificationDialog) + return false; + + Q_Q(QQuickWebView); + QtDialogRunner dialogRunner; + if (!dialogRunner.initForCertificateVerification(certificateVerificationDialog, q, hostname)) + return false; + + setViewInAttachedProperties(dialogRunner.dialog()); + + disableMouseEvents(); + dialogRunner.exec(); + enableMouseEvents(); + + return dialogRunner.wasAccepted(); +} + void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type) { #ifndef QT_NO_FILEDIALOG @@ -607,6 +684,18 @@ void QQuickWebViewExperimental::setUseTraditionalDesktopBehaviour(bool enable) d->setUseTraditionalDesktopBehaviour(enable); } +void QQuickWebViewExperimental::setRenderToOffscreenBuffer(bool enable) +{ + Q_D(QQuickWebView); + d->setRenderToOffscreenBuffer(enable); +} + +bool QQuickWebViewExperimental::renderToOffscreenBuffer() const +{ + Q_D(const QQuickWebView); + return d->renderToOffscreenBuffer(); +} + void QQuickWebViewExperimental::postMessage(const QString& message) { Q_D(QQuickWebView); @@ -671,6 +760,36 @@ void QQuickWebViewExperimental::setPromptDialog(QDeclarativeComponent* promptDia emit promptDialogChanged(); } +QDeclarativeComponent* QQuickWebViewExperimental::authenticationDialog() const +{ + Q_D(const QQuickWebView); + return d->authenticationDialog; +} + +void QQuickWebViewExperimental::setAuthenticationDialog(QDeclarativeComponent* authenticationDialog) +{ + Q_D(QQuickWebView); + if (d->authenticationDialog == authenticationDialog) + return; + d->authenticationDialog = authenticationDialog; + emit authenticationDialogChanged(); +} + +QDeclarativeComponent* QQuickWebViewExperimental::certificateVerificationDialog() const +{ + Q_D(const QQuickWebView); + return d->certificateVerificationDialog; +} + +void QQuickWebViewExperimental::setCertificateVerificationDialog(QDeclarativeComponent* certificateVerificationDialog) +{ + Q_D(QQuickWebView); + if (d->certificateVerificationDialog == certificateVerificationDialog) + return; + d->certificateVerificationDialog = certificateVerificationDialog; + emit certificateVerificationDialogChanged(); +} + QDeclarativeComponent* QQuickWebViewExperimental::itemSelector() const { Q_D(const QQuickWebView); @@ -707,6 +826,7 @@ void QQuickWebViewExperimental::schemeDelegates_Append(QDeclarativeListProperty< QQuickWebViewExperimental* webViewExperimental = qobject_cast<QQuickWebViewExperimental*>(property->object->parent()); if (!webViewExperimental) return; + scheme->reply()->setWebViewExperimental(webViewExperimental); QQuickWebViewPrivate* d = webViewExperimental->d_func(); d->webPageProxy->registerApplicationScheme(scheme->scheme()); } @@ -735,15 +855,17 @@ QDeclarativeListProperty<QQuickUrlSchemeDelegate> QQuickWebViewExperimental::sch QQuickWebViewExperimental::schemeDelegates_Clear); } -void QQuickWebViewExperimental::invokeApplicationSchemeHandler(PassRefPtr<QtNetworkRequestData> request) +void QQuickWebViewExperimental::invokeApplicationSchemeHandler(PassRefPtr<QtRefCountedNetworkRequestData> request) { + RefPtr<QtRefCountedNetworkRequestData> req = request; const QObjectList children = schemeParent->children(); for (int index = 0; index < children.count(); index++) { QQuickUrlSchemeDelegate* delegate = qobject_cast<QQuickUrlSchemeDelegate*>(children.at(index)); if (!delegate) continue; - if (!delegate->scheme().compare(QString(request->m_scheme), Qt::CaseInsensitive)) { - delegate->reply()->setNetworkRequestData(request); + if (!delegate->scheme().compare(QString(req->data().m_scheme), Qt::CaseInsensitive)) { + delegate->request()->setNetworkRequestData(req); + delegate->reply()->setNetworkRequestData(req); emit delegate->receivedRequest(); return; } @@ -782,7 +904,6 @@ QQuickWebView::QQuickWebView(QQuickItem* parent) { Q_D(QQuickWebView); d->initialize(); - d->initializeTouch(this); } QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent) @@ -924,7 +1045,7 @@ QVariant QQuickWebView::inputMethodQuery(Qt::InputMethodQuery property) const switch(property) { case Qt::ImCursorRectangle: - return QRectF(state.microFocus); + return QRectF(state.cursorRect); case Qt::ImFont: return QVariant(); case Qt::ImCursorPosition: @@ -964,11 +1085,10 @@ void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& old Q_D(QQuickWebView); QQuickItem::geometryChanged(newGeometry, oldGeometry); if (newGeometry.size() != oldGeometry.size()) { - if (d->pageView->usesTraditionalDesktopBehaviour()) { - d->pageView->setWidth(newGeometry.width()); - d->pageView->setHeight(newGeometry.height()); - } else - d->updateViewportSize(); + if (d->pageView->usesTraditionalDesktopBehaviour()) + d->updateDesktopViewportSize(); + else + d->updateTouchViewportSize(); } } diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h index 0fa0791cf..7a713d133 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h @@ -44,7 +44,7 @@ class PlatformWebView; } namespace WebKit { -class QtNetworkRequestData; +class QtRefCountedNetworkRequestData; } namespace WTF { @@ -165,6 +165,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_suspend()); Q_PRIVATE_SLOT(d_func(), void _q_resume()); Q_PRIVATE_SLOT(d_func(), void _q_viewportTrajectoryVectorChanged(const QPointF&)); + Q_PRIVATE_SLOT(d_func(), void _q_updateVisibleContentRectAndScale()); Q_PRIVATE_SLOT(d_func(), void _q_onOpenPanelFilesSelected()); Q_PRIVATE_SLOT(d_func(), void _q_onOpenPanelFinished(int result)); Q_PRIVATE_SLOT(d_func(), void _q_onVisibleChanged()); @@ -208,6 +209,8 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject { Q_PROPERTY(QDeclarativeComponent* alertDialog READ alertDialog WRITE setAlertDialog NOTIFY alertDialogChanged) Q_PROPERTY(QDeclarativeComponent* confirmDialog READ confirmDialog WRITE setConfirmDialog NOTIFY confirmDialogChanged) Q_PROPERTY(QDeclarativeComponent* promptDialog READ promptDialog WRITE setPromptDialog NOTIFY promptDialogChanged) + Q_PROPERTY(QDeclarativeComponent* authenticationDialog READ authenticationDialog WRITE setAuthenticationDialog NOTIFY authenticationDialogChanged) + Q_PROPERTY(QDeclarativeComponent* certificateVerificationDialog READ certificateVerificationDialog WRITE setCertificateVerificationDialog NOTIFY certificateVerificationDialogChanged) Q_PROPERTY(QDeclarativeComponent* itemSelector READ itemSelector WRITE setItemSelector NOTIFY itemSelectorChanged) Q_PROPERTY(QWebPreferences* preferences READ preferences CONSTANT FINAL) Q_PROPERTY(bool useTraditionalDesktopBehaviour READ useTraditionalDesktopBehaviour WRITE setUseTraditionalDesktopBehaviour) @@ -229,13 +232,18 @@ public: void setConfirmDialog(QDeclarativeComponent*); QDeclarativeComponent* promptDialog() const; void setPromptDialog(QDeclarativeComponent*); + QDeclarativeComponent* authenticationDialog() const; + void setAuthenticationDialog(QDeclarativeComponent*); + QDeclarativeComponent* certificateVerificationDialog() const; + void setCertificateVerificationDialog(QDeclarativeComponent*); QDeclarativeComponent* itemSelector() const; void setItemSelector(QDeclarativeComponent*); - + bool useTraditionalDesktopBehaviour() const; + void setUseTraditionalDesktopBehaviour(bool enable); + QWebViewportInfo* viewportInfo(); QWebPreferences* preferences() const; - bool useTraditionalDesktopBehaviour() const; QWebNavigationHistory* navigationHistory() const; QQuickWebPage* page(); @@ -244,11 +252,14 @@ public: static int schemeDelegates_Count(QDeclarativeListProperty<QQuickUrlSchemeDelegate>*); static void schemeDelegates_Clear(QDeclarativeListProperty<QQuickUrlSchemeDelegate>*); QDeclarativeListProperty<QQuickUrlSchemeDelegate> schemeDelegates(); - void invokeApplicationSchemeHandler(WTF::PassRefPtr<WebKit::QtNetworkRequestData>); + void invokeApplicationSchemeHandler(WTF::PassRefPtr<WebKit::QtRefCountedNetworkRequestData>); void sendApplicationSchemeReply(QQuickNetworkReply*); + // C++ only + bool renderToOffscreenBuffer() const; + void setRenderToOffscreenBuffer(bool enable); + public Q_SLOTS: - void setUseTraditionalDesktopBehaviour(bool enable); void goBackTo(int index); void goForwardTo(int index); void postMessage(const QString&); @@ -257,6 +268,8 @@ Q_SIGNALS: void alertDialogChanged(); void confirmDialogChanged(); void promptDialogChanged(); + void authenticationDialogChanged(); + void certificateVerificationDialogChanged(); void itemSelectorChanged(); void downloadRequested(QWebDownloadItem* downloadItem); void permissionRequested(QWebPermissionRequest* permission); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h index 4be71707c..17a5cf82a 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h @@ -77,10 +77,13 @@ public: void didChangeViewportProperties(const WebCore::ViewportArguments& args); void didChangeBackForwardList(); - void updateViewportSize(); + void setNeedsDisplay(); + + void updateDesktopViewportSize(); + void updateTouchViewportSize(); QtViewportInteractionEngine::Constraints computeViewportConstraints(); - void updateVisibleContentRectAndScale(); + void _q_updateVisibleContentRectAndScale(); void _q_suspend(); void _q_resume(); @@ -96,11 +99,16 @@ public: bool runJavaScriptConfirm(const QString&); QString runJavaScriptPrompt(const QString&, const QString& defaultValue, bool& ok); + void handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password); + bool handleCertificateVerificationRequest(const QString& hostname); + void setUseTraditionalDesktopBehaviour(bool enable); + void setRenderToOffscreenBuffer(bool enable) { m_renderToOffscreenBuffer = enable; } void setViewInAttachedProperties(QObject*); void setIcon(const QUrl&); bool navigatorQtObjectEnabled() const; + bool renderToOffscreenBuffer() const { return m_renderToOffscreenBuffer; } void setNavigatorQtObjectEnabled(bool); // PageClient. @@ -150,6 +158,8 @@ private: QDeclarativeComponent* alertDialog; QDeclarativeComponent* confirmDialog; QDeclarativeComponent* promptDialog; + QDeclarativeComponent* authenticationDialog; + QDeclarativeComponent* certificateVerificationDialog; QDeclarativeComponent* itemSelector; WebCore::ViewportArguments viewportArguments; @@ -160,6 +170,7 @@ private: bool isTransitioningToNewPage; bool pageIsSuspended; bool m_navigatorQtObjectEnabled; + bool m_renderToOffscreenBuffer; QUrl m_iconURL; }; diff --git a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp new file mode 100644 index 000000000..e0c2c256c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 program 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 program; 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 "bytearraytestdata.h" + +ByteArrayTestData::ByteArrayTestData(QObject* parent) + : QObject(parent) +{ + QString text = QStringLiteral("<html><head><title>title with copyright %1</title></head><body>content</body></html>"); + text = text.arg(QChar::fromLatin1(169)); + + m_latin1Data = text.toLatin1(); + m_utf8Data = text.toUtf8(); + + Q_ASSERT(m_latin1Data != m_utf8Data); +} + +QVariant ByteArrayTestData::latin1Data() const +{ + return QVariant(m_latin1Data); +} + +QVariant ByteArrayTestData::utf8Data() const +{ + return QVariant(m_utf8Data); +} + +#include "moc_bytearraytestdata.cpp" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h new file mode 100644 index 000000000..7170f6594 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 program 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 program; 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 bytearraytestdata_h +#define bytearraytestdata_h + +#include "qwebkitglobal.h" +#include <QByteArray> +#include <QObject> +#include <QtQuick/qquickitem.h> + +class QWEBKIT_EXPORT ByteArrayTestData : public QObject { + Q_OBJECT + Q_PROPERTY(QVariant latin1Data READ latin1Data) + Q_PROPERTY(QVariant utf8Data READ utf8Data) + +public: + ByteArrayTestData(QObject* parent = 0); + QVariant latin1Data() const; + QVariant utf8Data() const; + +private: + QByteArray m_latin1Data; + QByteArray m_utf8Data; +}; + +QML_DECLARE_TYPE(ByteArrayTestData) + +#endif // bytearraytestdata_h diff --git a/Source/WebKit2/UIProcess/API/qt/tests/publicapi/publicapi.pro b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/publicapi.pro new file mode 100644 index 000000000..728521f8a --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/publicapi.pro @@ -0,0 +1,2 @@ +include(../tests.pri) +CONFIG += qtwebkit-private diff --git a/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp new file mode 100644 index 000000000..f1a81bc18 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp @@ -0,0 +1,170 @@ +/* + Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + + 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 <QMetaEnum> +#include <QMetaMethod> +#include <QMetaObject> +#include <QMetaProperty> +#include <QMetaType> +#include <QtTest/QtTest> +#include <qquickwebview_p.h> +#include <qwebnavigationrequest_p.h> + +class tst_publicapi : public QObject { + Q_OBJECT +private slots: + void publicAPI(); +}; + +static QList<const QMetaObject*> typesToCheck = QList<const QMetaObject*>() + << &QQuickWebView::staticMetaObject + << &QWebNavigationRequest::staticMetaObject; + +static QStringList expectedAPI = QStringList() + << "QQuickWebView.AcceptRequest --> NavigationRequestAction" + << "QQuickWebView.IgnoreRequest --> NavigationRequestAction" + << "QQuickWebView.InternalErrorDomain --> ErrorDomain" + << "QQuickWebView.NetworkErrorDomain --> ErrorDomain" + << "QQuickWebView.HttpErrorDomain --> ErrorDomain" + << "QQuickWebView.DownloadErrorDomain --> ErrorDomain" + << "QQuickWebView.title --> QString" + << "QQuickWebView.url --> QUrl" + << "QQuickWebView.icon --> QUrl" + << "QQuickWebView.loadProgress --> int" + << "QQuickWebView.canGoBack --> bool" + << "QQuickWebView.canGoForward --> bool" + << "QQuickWebView.loading --> bool" + << "QQuickWebView.canReload --> bool" + << "QQuickWebView.titleChanged(QString) --> void" + << "QQuickWebView.loadStarted() --> void" + << "QQuickWebView.loadSucceeded() --> void" + << "QQuickWebView.loadFailed(QQuickWebView::ErrorDomain,int,QUrl,QString) --> void" + << "QQuickWebView.loadProgressChanged(int) --> void" + << "QQuickWebView.urlChanged(QUrl) --> void" + << "QQuickWebView.iconChanged(QUrl) --> void" + << "QQuickWebView.linkHovered(QUrl,QString) --> void" + << "QQuickWebView.navigationStateChanged() --> void" + << "QQuickWebView.navigationRequested(QWebNavigationRequest*) --> void" + << "QQuickWebView.load(QUrl) --> void" + << "QQuickWebView.loadHtml(QString,QUrl) --> void" + << "QQuickWebView.loadHtml(QString) --> void" + << "QQuickWebView.goBack() --> void" + << "QQuickWebView.goForward() --> void" + << "QQuickWebView.stop() --> void" + << "QQuickWebView.reload() --> void" + << "QWebNavigationRequest.url --> QUrl" + << "QWebNavigationRequest.originatingUrl --> QUrl" + << "QWebNavigationRequest.button --> int" + << "QWebNavigationRequest.modifiers --> int" + << "QWebNavigationRequest.action --> int" + << "QWebNavigationRequest.actionChanged() --> void" + ; + +static bool isCheckedEnum(const QByteArray& typeName) +{ + QList<QByteArray> tokens = typeName.split(':'); + if (tokens.size() == 3) { + QByteArray& enumClass = tokens[0]; + QByteArray& enumName = tokens[2]; + foreach (const QMetaObject* mo, typesToCheck) { + if (mo->className() != enumClass) + continue; + for (int i = mo->enumeratorOffset(); i < mo->enumeratorCount(); ++i) + if (mo->enumerator(i).name() == enumName) + return true; + } + } + return false; +} + +static bool isCheckedClass(const QByteArray& typeName) +{ + foreach (const QMetaObject* mo, typesToCheck) { + QByteArray moTypeName(mo->className()); + if (moTypeName == typeName || moTypeName + "*" == typeName) + return true; + } + return false; +} + +static void checkKnownType(const QByteArray& typeName) +{ + if ((typeName != "void" && !QMetaType::type(typeName)) || QMetaType::type(typeName) >= QMetaType::User) { + bool knownEnum = isCheckedEnum(typeName); + bool knownClass = isCheckedClass(typeName); + QVERIFY2(knownEnum || knownClass, qPrintable(QString("The API uses an unknown type [%1], you might have to add it to the typesToCheck list.").arg(typeName.constData()))); + } +} + +static void gatherAPI(const QString& prefix, const QMetaEnum& metaEnum, QStringList* output) +{ + for (int i = 0; i < metaEnum.keyCount(); ++i) + *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(metaEnum.key(i)).arg(metaEnum.name()); +} + +static void gatherAPI(const QString& prefix, const QMetaProperty& property, QStringList* output) +{ + *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(property.name()).arg(property.typeName()); + checkKnownType(property.typeName()); +} + +static void gatherAPI(const QString& prefix, const QMetaMethod& method, QStringList* output) +{ + if (method.access() != QMetaMethod::Private) { + const char* methodTypeName = !!strlen(method.typeName()) ? method.typeName() : "void"; + *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(method.signature()).arg(methodTypeName); + + checkKnownType(methodTypeName); + foreach (QByteArray paramType, method.parameterTypes()) + checkKnownType(paramType); + } +} + +static void gatherAPI(const QString& prefix, const QMetaObject* meta, QStringList* output) +{ + // *Offset points us only at the leaf class members, we don't have inheritance in our API yet anyway. + for (int i = meta->enumeratorOffset(); i < meta->enumeratorCount(); ++i) + gatherAPI(prefix, meta->enumerator(i), output); + for (int i = meta->propertyOffset(); i < meta->propertyCount(); ++i) + gatherAPI(prefix, meta->property(i), output); + for (int i = meta->methodOffset(); i < meta->methodCount(); ++i) + gatherAPI(prefix, meta->method(i), output); +} + +void tst_publicapi::publicAPI() +{ + QStringList actualAPI; + foreach (const QMetaObject* meta, typesToCheck) + gatherAPI(QString::fromLatin1(meta->className()) + ".", meta, &actualAPI); + + // Uncomment to print the actual API. + // foreach(QString actual, actualAPI) + // printf(" << \"%s\"\n", qPrintable(actual)); + + // Make sure that nothing slips in the public API unintentionally. + foreach (QString actual, actualAPI) + QVERIFY2(expectedAPI.contains(actual), qPrintable(actual)); + // Make sure that the expected list is up-to-date with intentionally added APIs. + foreach (QString expected, expectedAPI) + QVERIFY2(actualAPI.contains(expected), qPrintable(expected)); +} + +QTEST_MAIN(tst_publicapi) + +#include "tst_publicapi.moc" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_applicationScheme.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_applicationScheme.qml index 29774e117..239483c5b 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_applicationScheme.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_applicationScheme.qml @@ -2,6 +2,7 @@ import QtQuick 2.0 import QtTest 1.0 import QtWebKit 3.0 import QtWebKit.experimental 3.0 +import Test 1.0 WebView { id: webView @@ -16,7 +17,47 @@ WebView { reply.data = "<html><head><title>Test Application Scheme</title></head><body>A test page.</body></html>" reply.send() } + }, + UrlSchemeDelegate { + scheme: "scheme1" + onReceivedRequest: { + reply.data = "<html><head><title>Scheme1 Reply</title></head><body>A test page.</body></html>" + reply.send() + } + }, + UrlSchemeDelegate { + scheme: "scheme2" + onReceivedRequest: { + reply.data = "<html><head><title>Scheme2 Reply</title></head><body>A test page.</body></html>" + reply.send() + } + }, + UrlSchemeDelegate { + scheme: "scheme3" + onReceivedRequest: { + if (request.url == "scheme3://url1") + reply.data = "<html><head><title>Scheme3 Reply1</title></head><body>A test page.</body></html>" + else if (request.url == "scheme3://url2") + reply.data = "<html><head><title>Scheme3 Reply2</title></head><body>A test page.</body></html>" + else + reply.data = "<html><head><title>Should not happen</title></head><body>A test page.</body></html>" + reply.send() + } + }, + UrlSchemeDelegate { + scheme: "schemeCharset" + onReceivedRequest: { + if (request.url == "schemecharset://latin1") { + reply.data = byteArrayHelper.latin1Data + reply.contentType = "text/html; charset=iso-8859-1" + } else if (request.url == "schemecharset://utf-8") { + reply.data = byteArrayHelper.utf8Data + reply.contentType = "text/html; charset=utf-8" + } + reply.send() + } } + ] } @@ -26,16 +67,67 @@ WebView { signalName: "titleChanged" } + ByteArrayTestData { + id: byteArrayHelper + } + TestCase { name: "WebViewApplicationSchemes" function test_applicationScheme() { + spyTitle.clear() compare(spyTitle.count, 0) var testUrl = "applicationScheme://something" webView.load(testUrl) spyTitle.wait() compare(webView.title, "Test Application Scheme") } - } + function test_multipleSchemes() { + // Test if we receive the right reply when defining multiple schemes. + spyTitle.clear() + compare(spyTitle.count, 0) + var testUrl = "scheme2://some-url-string" + webView.load(testUrl) + spyTitle.wait() + compare(webView.title, "Scheme2 Reply") + + testUrl = "scheme1://some-url-string" + webView.load(testUrl) + spyTitle.wait() + compare(webView.title, "Scheme1 Reply") + + compare(spyTitle.count, 2) + } + + function test_multipleUrlsForScheme() { + spyTitle.clear() + compare(spyTitle.count, 0) + var testUrl = "scheme3://url1" + webView.load(testUrl) + spyTitle.wait() + compare(webView.title, "Scheme3 Reply1") + + testUrl = "scheme3://url2" + webView.load(testUrl) + spyTitle.wait() + compare(webView.title, "Scheme3 Reply2") + + compare(spyTitle.count, 2) + } + + function test_charsets() { + spyTitle.clear() + compare(spyTitle.count, 0) + var testUrl = "schemeCharset://latin1" + webView.load(testUrl) + spyTitle.wait() + compare(webView.title, "title with copyright ©") + + testUrl = "schemeCharset://utf-8" + webView.load(testUrl) + spyTitle.wait() + compare(webView.title, "title with copyright ©") + } + } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/tst_qmltests.cpp b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/tst_qmltests.cpp index e8d9aab0e..8c8c4b3e6 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/tst_qmltests.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/tst_qmltests.cpp @@ -17,6 +17,7 @@ Boston, MA 02110-1301, USA. */ +#include "../bytearraytestdata.h" #include "../util.h" #include <QVarLengthArray> @@ -41,5 +42,6 @@ int main(int argc, char** argv) // Instantiate QApplication to prevent quick_test_main to instantiate a QGuiApplication. // This can be removed as soon as we do not use QtWidgets any more. QApplication app(argc, argv); + qmlRegisterType<ByteArrayTestData>("Test", 1, 0, "ByteArrayTestData"); return quick_test_main(argc, argv, "qmltests", 0, QUICK_TEST_SOURCE_DIR); } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/tests.pri b/Source/WebKit2/UIProcess/API/qt/tests/tests.pri index 297bcec92..06ff1a0a3 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/tests.pri +++ b/Source/WebKit2/UIProcess/API/qt/tests/tests.pri @@ -3,11 +3,14 @@ TEMPLATE = app VPATH += $$_PRO_FILE_PWD_ TARGET = tst_$$TARGET +HEADERS += ../bytearraytestdata.h + SOURCES += $${TARGET}.cpp \ - ../util.cpp + ../util.cpp \ + ../bytearraytestdata.cpp INCLUDEPATH += $$PWD -QT += testlib declarative widgets +QT += testlib declarative widgets quick CONFIG += qtwebkit diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxy.h b/Source/WebKit2/UIProcess/DrawingAreaProxy.h index 2f5832287..617c17506 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxy.h +++ b/Source/WebKit2/UIProcess/DrawingAreaProxy.h @@ -27,6 +27,7 @@ #ifndef DrawingAreaProxy_h #define DrawingAreaProxy_h +#include "BackingStore.h" #include "DrawingAreaInfo.h" #include <WebCore/IntRect.h> #include <WebCore/IntSize.h> @@ -87,7 +88,8 @@ public: virtual WebCore::IntRect viewportVisibleRect() const { return contentsRect(); } virtual WebCore::IntRect contentsRect() const; virtual bool isBackingStoreReady() const { return true; } - virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity) { } + virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&) { } + virtual void paintLayerTree(BackingStore::PlatformGraphicsContext) { } LayerTreeHostProxy* layerTreeHostProxy() const { return m_layerTreeHostProxy.get(); } #if USE(TILED_BACKING_STORE) diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp index 7b153848d..24a5aed18 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp +++ b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp @@ -30,7 +30,9 @@ #include "DrawingAreaProxyMessages.h" #include "LayerTreeContext.h" #include "UpdateInfo.h" +#include "WebPageGroup.h" #include "WebPageProxy.h" +#include "WebPreferences.h" #include "WebProcessProxy.h" #include <WebCore/Region.h> @@ -56,6 +58,11 @@ DrawingAreaProxyImpl::DrawingAreaProxyImpl(WebPageProxy* webPageProxy) , m_isBackingStoreDiscardable(true) , m_discardBackingStoreTimer(RunLoop::current(), this, &DrawingAreaProxyImpl::discardBackingStore) { +#if USE(TEXTURE_MAPPER) + // Construct the proxy early to allow messages to be sent to the web process while AC is entered there. + if (webPageProxy->pageGroup()->preferences()->forceCompositingMode()) + m_layerTreeHostProxy = adoptPtr(new LayerTreeHostProxy(this)); +#endif } DrawingAreaProxyImpl::~DrawingAreaProxyImpl() @@ -353,10 +360,16 @@ void DrawingAreaProxyImpl::setVisibleContentRectTrajectoryVector(const WebCore:: m_layerTreeHostProxy->setVisibleContentRectTrajectoryVector(trajectoryVector); } -void DrawingAreaProxyImpl::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity) +void DrawingAreaProxyImpl::paintLayerTree(BackingStore::PlatformGraphicsContext context) +{ + if (m_layerTreeHostProxy) + m_layerTreeHostProxy->paintToGraphicsContext(context); +} + +void DrawingAreaProxyImpl::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect) { if (m_layerTreeHostProxy) - m_layerTreeHostProxy->paintToCurrentGLContext(matrix, opacity); + m_layerTreeHostProxy->paintToCurrentGLContext(matrix, opacity, clipRect); } #endif diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h index 05d735423..5fcf24c50 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h +++ b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h @@ -29,7 +29,7 @@ #include "BackingStore.h" #include "DrawingAreaProxy.h" #include "LayerTreeContext.h" -#include "RunLoop.h" +#include <WebCore/RunLoop.h> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> @@ -80,7 +80,8 @@ private: #if USE(TILED_BACKING_STORE) virtual void setVisibleContentsRectAndScale(const WebCore::IntRect& visibleContentsRect, float scale); virtual void setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint&); - virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity); + virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity, const WebCore::FloatRect&); + virtual void paintLayerTree(BackingStore::PlatformGraphicsContext); void didReceiveLayerTreeHostProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); #endif #else @@ -116,7 +117,7 @@ private: bool m_isBackingStoreDiscardable; OwnPtr<BackingStore> m_backingStore; - RunLoop::Timer<DrawingAreaProxyImpl> m_discardBackingStoreTimer; + WebCore::RunLoop::Timer<DrawingAreaProxyImpl> m_discardBackingStoreTimer; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp b/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp index 3c0fbf160..f37a5d3a2 100644 --- a/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp +++ b/Source/WebKit2/UIProcess/Launcher/ThreadLauncher.cpp @@ -26,7 +26,9 @@ #include "config.h" #include "ThreadLauncher.h" -#include "RunLoop.h" +#include <WebCore/RunLoop.h> + +using namespace WebCore; namespace WebKit { diff --git a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp index d7a50829d..94cad5fc4 100644 --- a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp +++ b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp @@ -28,18 +28,20 @@ #include "ProcessLauncher.h" #include "Connection.h" -#include "RunLoop.h" #include <WebCore/FileSystem.h> #include <WebCore/ResourceHandle.h> +#include <WebCore/RunLoop.h> #include <errno.h> -#if OS(LINUX) -#include <sys/prctl.h> -#endif +#include <locale.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GlibUtilities.h> +#if OS(LINUX) +#include <sys/prctl.h> +#endif + #ifdef SOCK_SEQPACKET #define SOCKET_TYPE SOCK_SEQPACKET #else @@ -58,6 +60,9 @@ static void childSetupFunction(gpointer userData) int socket = GPOINTER_TO_INT(userData); close(socket); + // Make child process inherit parent's locale. + g_setenv("LC_ALL", setlocale(LC_ALL, 0), TRUE); + #if OS(LINUX) // Kill child process when parent dies. prctl(PR_SET_PDEATHSIG, SIGKILL); diff --git a/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm b/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm index c70f62edf..dc839c84f 100644 --- a/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm +++ b/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm @@ -28,9 +28,9 @@ #import "DynamicLinkerEnvironmentExtractor.h" #import "EnvironmentVariables.h" -#import "RunLoop.h" #import "WebProcess.h" #import "WebKitSystemInterface.h" +#import <WebCore/RunLoop.h> #import <crt_externs.h> #import <mach-o/dyld.h> #import <mach/machine.h> diff --git a/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm b/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm index 1c74b7d28..dd53b3ef1 100644 --- a/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm +++ b/Source/WebKit2/UIProcess/Launcher/mac/ThreadLauncherMac.mm @@ -26,13 +26,15 @@ #import "config.h" #import "ThreadLauncher.h" -#import "RunLoop.h" #import "WebProcess.h" #import "WebSystemInterface.h" #import <runtime/InitializeThreading.h> +#import <WebCore/RunLoop.h> #import <wtf/MainThread.h> #import <wtf/Threading.h> +using namespace WebCore; + namespace WebKit { static void* webThreadBody(void* context) diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp index 837f59baf..8e8262063 100644 --- a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp +++ b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp @@ -28,7 +28,6 @@ #include "ProcessLauncher.h" #include "Connection.h" -#include "RunLoop.h" #include "WebProcess.h" #include <QCoreApplication> #include <QDebug> @@ -39,6 +38,7 @@ #include <QString> #include <QtCore/qglobal.h> #include <WebCore/NotImplemented.h> +#include <WebCore/RunLoop.h> #include <errno.h> #include <fcntl.h> #include <runtime/InitializeThreading.h> @@ -50,6 +50,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/Threading.h> #include <wtf/text/WTFString.h> + #if defined(Q_OS_LINUX) #include <sys/prctl.h> #include <signal.h> diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp index 7b95ca049..1d0caf3ae 100644 --- a/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp +++ b/Source/WebKit2/UIProcess/Launcher/qt/ThreadLauncherQt.cpp @@ -27,8 +27,8 @@ #include "config.h" #include "ThreadLauncher.h" -#include "RunLoop.h" #include "WebProcess.h" +#include <WebCore/RunLoop.h> #include <runtime/InitializeThreading.h> #include <wtf/MainThread.h> #include <wtf/Threading.h> diff --git a/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp index d526c0307..7de782f68 100644 --- a/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp +++ b/Source/WebKit2/UIProcess/Launcher/win/ProcessLauncherWin.cpp @@ -27,7 +27,7 @@ #include "ProcessLauncher.h" #include "Connection.h" -#include "RunLoop.h" +#include <WebCore/RunLoop.h> #include <shlwapi.h> #include <wtf/text/WTFString.h> @@ -43,6 +43,8 @@ const LPCWSTR webKitDLLName = L"WebKit_debug.dll"; const LPCWSTR webKitDLLName = L"WebKit.dll"; #endif +using namespace WebCore; + namespace WebKit { void ProcessLauncher::launchProcess() diff --git a/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp b/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp index 2596998ea..f9d1c0481 100644 --- a/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp +++ b/Source/WebKit2/UIProcess/Launcher/win/ThreadLauncherWin.cpp @@ -26,8 +26,8 @@ #include "config.h" #include "ThreadLauncher.h" -#include "RunLoop.h" #include "WebProcess.h" +#include <WebCore/RunLoop.h> #include <runtime/InitializeThreading.h> #include <wtf/MainThread.h> #include <wtf/Threading.h> diff --git a/Source/WebKit2/UIProcess/LayerTreeHostProxy.h b/Source/WebKit2/UIProcess/LayerTreeHostProxy.h index 871e3bf09..4c971875c 100644 --- a/Source/WebKit2/UIProcess/LayerTreeHostProxy.h +++ b/Source/WebKit2/UIProcess/LayerTreeHostProxy.h @@ -24,12 +24,12 @@ #include "DrawingAreaProxy.h" #include "MessageQueue.h" #include "Region.h" -#include "RunLoop.h" #include "WebLayerTreeInfo.h" #include <WebCore/GraphicsContext.h> #include <WebCore/GraphicsLayer.h> #include <WebCore/IntRect.h> #include <WebCore/IntSize.h> +#include <WebCore/RunLoop.h> #include <wtf/HashSet.h> #if USE(TEXTURE_MAPPER) @@ -42,11 +42,9 @@ namespace WebKit { class WebLayerInfo; class WebLayerUpdateInfo; -using namespace WebCore; - class LayerTreeMessageToRenderer; -class LayerTreeHostProxy : public GraphicsLayerClient { +class LayerTreeHostProxy : public WebCore::GraphicsLayerClient { public: LayerTreeHostProxy(DrawingAreaProxy*); virtual ~LayerTreeHostProxy(); @@ -54,10 +52,11 @@ public: void deleteCompositingLayer(WebLayerID); void setRootCompositingLayer(WebLayerID); void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); - void paintToCurrentGLContext(const TransformationMatrix&, float); + void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&); + void paintToGraphicsContext(BackingStore::PlatformGraphicsContext); void purgeGLResources(); - void setVisibleContentsRectAndScale(const IntRect&, float); - void setVisibleContentRectTrajectoryVector(const FloatPoint&); + void setVisibleContentsRectAndScale(const WebCore::IntRect&, float); + void setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint&); #if USE(TILED_BACKING_STORE) void syncRemoteContent(); void swapContentBuffers(); @@ -68,40 +67,39 @@ public: void createDirectlyCompositedImage(int64_t, const WebKit::ShareableBitmap::Handle&); void destroyDirectlyCompositedImage(int64_t); void didReceiveLayerTreeHostProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); - void setVisibleContentsRectForLayer(WebLayerID, const IntRect&); void updateViewport(); #endif protected: - PassOwnPtr<GraphicsLayer> createLayer(WebLayerID); + PassOwnPtr<WebCore::GraphicsLayer> createLayer(WebLayerID); - GraphicsLayer* layerByID(WebLayerID id) { return (id == InvalidWebLayerID) ? 0 : m_layers.get(id); } - GraphicsLayer* rootLayer() { return m_rootLayer.get(); } + WebCore::GraphicsLayer* layerByID(WebLayerID id) { return (id == InvalidWebLayerID) ? 0 : m_layers.get(id); } + WebCore::GraphicsLayer* rootLayer() { return m_rootLayer.get(); } // Reimplementations from WebCore::GraphicsLayerClient. - virtual void notifyAnimationStarted(const GraphicsLayer*, double) { } - virtual void notifySyncRequired(const GraphicsLayer*) { } - virtual bool showDebugBorders() const { return false; } - virtual bool showRepaintCounter() const { return false; } + virtual void notifyAnimationStarted(const WebCore::GraphicsLayer*, double) { } + virtual void notifySyncRequired(const WebCore::GraphicsLayer*) { } + virtual bool showDebugBorders(const WebCore::GraphicsLayer*) const { return false; } + virtual bool showRepaintCounter(const WebCore::GraphicsLayer*) const { return false; } void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect&) { } - RunLoop::Timer<LayerTreeHostProxy> m_animationTimer; + WebCore::RunLoop::Timer<LayerTreeHostProxy> m_animationTimer; DrawingAreaProxy* m_drawingAreaProxy; typedef HashMap<WebLayerID, WebCore::GraphicsLayer*> LayerMap; - IntRect m_visibleContentsRect; + WebCore::IntRect m_visibleContentsRect; float m_contentsScale; MessageQueue<LayerTreeMessageToRenderer> m_messagesToRenderer; void pushUpdateToQueue(PassOwnPtr<LayerTreeMessageToRenderer>); #if USE(TEXTURE_MAPPER) - OwnPtr<TextureMapper> m_textureMapper; + OwnPtr<WebCore::TextureMapper> m_textureMapper; #endif #if PLATFORM(QT) - typedef HashMap<IntPoint, RefPtr<BitmapTexture> > TiledImage; - TextureMapperNode::NodeRectMap m_nodeVisualContentsRectMap; + typedef HashMap<WebCore::IntPoint, RefPtr<WebCore::BitmapTexture> > TiledImage; + WebCore::TextureMapperNode::NodeRectMap m_nodeVisualContentsRectMap; HashMap<int, int> m_tileToNodeTile; int remoteTileIDToNodeTileID(int tileID) const; HashMap<int64_t, TiledImage> m_directlyCompositedImages; @@ -113,8 +111,8 @@ protected: void syncLayerParameters(const WebLayerInfo&); void createTile(WebLayerID, int, float scale); void removeTile(WebLayerID, int); - void updateTile(WebLayerID, int, const IntRect&, const IntRect&, const QImage&); - void createImage(int64_t, const QImage&); + void updateTile(WebLayerID, int, const WebCore::IntRect&, const WebCore::IntRect&, ShareableBitmap*); + void createImage(int64_t, ShareableBitmap*); void destroyImage(int64_t); void assignImageToLayer(WebCore::GraphicsLayer*, int64_t imageID); void flushLayerChanges(); @@ -123,12 +121,12 @@ protected: #endif - OwnPtr<GraphicsLayer> m_rootLayer; + OwnPtr<WebCore::GraphicsLayer> m_rootLayer; Vector<WebLayerID> m_layersToDelete; #if PLATFORM(QT) - void didFireViewportUpdateTimer(Timer<LayerTreeHostProxy>*); - Timer<LayerTreeHostProxy> m_viewportUpdateTimer; + void didFireViewportUpdateTimer(WebCore::Timer<LayerTreeHostProxy>*); + WebCore::Timer<LayerTreeHostProxy> m_viewportUpdateTimer; #endif LayerMap m_layers; diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp b/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp index 7bb74432c..065bbbf7f 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp +++ b/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp @@ -33,10 +33,10 @@ namespace WebKit { -WebNotification::WebNotification(const String& title, const String& body, const String& originIdentifier, uint64_t notificationID) +WebNotification::WebNotification(const String& title, const String& body, const String& originString, uint64_t notificationID) : m_title(title) , m_body(body) - , m_origin(WebSecurityOrigin::create(originIdentifier)) + , m_origin(WebSecurityOrigin::createFromString(originString)) , m_notificationID(notificationID) { } diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotification.h b/Source/WebKit2/UIProcess/Notifications/WebNotification.h index 0b89a0aab..9447da427 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotification.h +++ b/Source/WebKit2/UIProcess/Notifications/WebNotification.h @@ -45,9 +45,9 @@ class WebNotification : public APIObject { public: static const Type APIType = TypeNotification; - static PassRefPtr<WebNotification> create(const String& title, const String& body, const String& originIdentifier, uint64_t notificationID) + static PassRefPtr<WebNotification> create(const String& title, const String& body, const String& originString, uint64_t notificationID) { - return adoptRef(new WebNotification(title, body, originIdentifier, notificationID)); + return adoptRef(new WebNotification(title, body, originString, notificationID)); } const String& title() const { return m_title; } @@ -57,7 +57,7 @@ public: uint64_t notificationID() const { return m_notificationID; } private: - WebNotification(const String& title, const String& body, const String& originIdentifier, uint64_t notificationID); + WebNotification(const String& title, const String& body, const String& originString, uint64_t notificationID); virtual Type type() const { return APIType; } diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp index 7d7c045db..e74ad07b7 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp @@ -27,6 +27,7 @@ #include "WebNotificationManagerProxy.h" #include "ImmutableArray.h" +#include "ImmutableDictionary.h" #include "WebContext.h" #include "WebNotification.h" #include "WebNotificationManagerMessages.h" @@ -57,26 +58,31 @@ void WebNotificationManagerProxy::invalidate() void WebNotificationManagerProxy::initializeProvider(const WKNotificationProvider *provider) { m_provider.initialize(provider); + m_provider.addNotificationManager(this); } -void WebNotificationManagerProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) +void WebNotificationManagerProxy::populateCopyOfNotificationPermissions(HashMap<String, bool>& permissions) { - didReceiveWebNotificationManagerProxyMessage(connection, messageID, arguments); + RefPtr<ImmutableDictionary> knownPermissions = m_provider.notificationPermissions(); + permissions.clear(); + RefPtr<ImmutableArray> knownOrigins = knownPermissions->keys(); + for (size_t i = 0; i < knownOrigins->size(); ++i) { + WebString* origin = knownOrigins->at<WebString>(i); + permissions.set(origin->string(), knownPermissions->get<WebBoolean>(origin->string())->value()); + } } -void WebNotificationManagerProxy::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply) +void WebNotificationManagerProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) { - didReceiveSyncWebNotificationManagerProxyMessage(connection, messageID, arguments, reply); + didReceiveWebNotificationManagerProxyMessage(connection, messageID, arguments); } -void WebNotificationManagerProxy::show(WebPageProxy* page, const String& title, const String& body, const String& originIdentifier, uint64_t notificationID) +void WebNotificationManagerProxy::show(WebPageProxy* page, const String& title, const String& body, const String& originString, uint64_t notificationID) { if (!isNotificationIDValid(notificationID)) return; - m_provider.addNotificationManager(this); - - RefPtr<WebNotification> notification = WebNotification::create(title, body, originIdentifier, notificationID); + RefPtr<WebNotification> notification = WebNotification::create(title, body, originString, notificationID); m_notifications.set(notificationID, notification); m_provider.show(page, notification.get()); } @@ -90,7 +96,6 @@ void WebNotificationManagerProxy::cancel(uint64_t notificationID) if (!notification) return; - m_provider.addNotificationManager(this); m_provider.cancel(notification.get()); } @@ -106,12 +111,6 @@ void WebNotificationManagerProxy::didDestroyNotification(uint64_t notificationID m_provider.didDestroyNotification(notification.get()); } -void WebNotificationManagerProxy::notificationPermissionLevel(const String& originIdentifier, uint64_t& permissionLevel) -{ - RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier); - permissionLevel = m_provider.policyForNotificationPermissionAtOrigin(origin.get()); -} - void WebNotificationManagerProxy::providerDidShowNotification(uint64_t notificationID) { if (!m_context) @@ -148,4 +147,30 @@ void WebNotificationManagerProxy::providerDidCloseNotifications(ImmutableArray* m_context->sendToAllProcesses(Messages::WebNotificationManager::DidCloseNotifications(vectorNotificationIDs)); } +void WebNotificationManagerProxy::providerDidUpdateNotificationPolicy(const WebSecurityOrigin* origin, bool allowed) +{ + if (!m_context) + return; + + m_context->sendToAllProcesses(Messages::WebNotificationManager::DidUpdateNotificationDecision(origin->toString(), allowed)); +} + +void WebNotificationManagerProxy::providerDidRemoveNotificationPolicies(ImmutableArray* origins) +{ + if (!m_context) + return; + + size_t size = origins->size(); + if (!size) + return; + + Vector<String> originStrings; + originStrings.reserveInitialCapacity(size); + + for (size_t i = 0; i < size; ++i) + originStrings.append(origins->at<WebSecurityOrigin>(i)->toString()); + + m_context->sendToAllProcesses(Messages::WebNotificationManager::DidRemoveNotificationDecisions(originStrings)); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h index 1705abcf4..8f4b9e9de 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h @@ -29,9 +29,11 @@ #include "APIObject.h" #include "MessageID.h" #include "WebNotificationProvider.h" +#include <WebCore/NotificationPresenter.h> #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> +#include <wtf/text/StringHash.h> namespace CoreIPC { class ArgumentDecoder; @@ -44,6 +46,7 @@ namespace WebKit { class ImmutableArray; class WebContext; class WebPageProxy; +class WebSecurityOrigin; class WebNotificationManagerProxy : public APIObject { public: @@ -55,15 +58,17 @@ public: void clearContext() { m_context = 0; } void initializeProvider(const WKNotificationProvider*); + void populateCopyOfNotificationPermissions(HashMap<String, bool>&); - void show(WebPageProxy*, const WTF::String& title, const WTF::String& body, const WTF::String& originIdentifier, uint64_t notificationID); + void show(WebPageProxy*, const String& title, const String& body, const String& originString, uint64_t notificationID); void providerDidShowNotification(uint64_t notificationID); void providerDidClickNotification(uint64_t notificationID); void providerDidCloseNotifications(ImmutableArray* notificationIDs); + void providerDidUpdateNotificationPolicy(const WebSecurityOrigin*, bool allowed); + void providerDidRemoveNotificationPolicies(ImmutableArray* origins); void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); - void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&); private: explicit WebNotificationManagerProxy(WebContext*); @@ -71,12 +76,10 @@ private: virtual Type type() const { return APIType; } void didReceiveWebNotificationManagerProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); - void didReceiveSyncWebNotificationManagerProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&); // Message handlers void cancel(uint64_t notificationID); void didDestroyNotification(uint64_t notificationID); - void notificationPermissionLevel(const WTF::String& originIdentifier, uint64_t& permissionLevel); typedef HashMap<uint64_t, RefPtr<WebNotification> > WebNotificationMap; diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in index 04d1a01b1..a06fd0292 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.messages.in @@ -23,6 +23,4 @@ messages -> WebNotificationManagerProxy { Cancel(uint64_t notificationID); DidDestroyNotification(uint64_t notificationID); - - NotificationPermissionLevel(WTF::String originIdentifier) -> (uint64_t policy) } diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.cpp b/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.cpp index 080aea666..afd13bccd 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.cpp +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "WebNotificationProvider.h" +#include "ImmutableDictionary.h" #include "WKAPICast.h" #include "WebNotification.h" #include "WebNotificationManagerProxy.h" @@ -57,14 +58,6 @@ void WebNotificationProvider::didDestroyNotification(WebNotification* notificati m_client.didDestroyNotification(toAPI(notification), m_client.clientInfo); } -int WebNotificationProvider::policyForNotificationPermissionAtOrigin(WebSecurityOrigin* origin) -{ - if (!m_client.policyForNotificationPermissionAtOrigin) - return INT_MIN; - - return m_client.policyForNotificationPermissionAtOrigin(toAPI(origin), m_client.clientInfo); -} - void WebNotificationProvider::addNotificationManager(WebNotificationManagerProxy* manager) { if (!m_client.addNotificationManager) @@ -81,4 +74,12 @@ void WebNotificationProvider::removeNotificationManager(WebNotificationManagerPr m_client.removeNotificationManager(toAPI(manager), m_client.clientInfo); } +PassRefPtr<ImmutableDictionary> WebNotificationProvider::notificationPermissions() +{ + if (!m_client.notificationPermissions) + return ImmutableDictionary::create(); + + return adoptRef(toImpl(m_client.notificationPermissions(m_client.clientInfo))); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.h b/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.h index 43d963919..8503ee27c 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.h +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationProvider.h @@ -32,6 +32,7 @@ namespace WebKit { +class ImmutableDictionary; class WebNotification; class WebNotificationManagerProxy; class WebPageProxy; @@ -42,10 +43,11 @@ public: void show(WebPageProxy*, WebNotification*); void cancel(WebNotification*); void didDestroyNotification(WebNotification*); - int policyForNotificationPermissionAtOrigin(WebSecurityOrigin*); void addNotificationManager(WebNotificationManagerProxy*); void removeNotificationManager(WebNotificationManagerProxy*); + + PassRefPtr<ImmutableDictionary> notificationPermissions(); }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/PageClient.h b/Source/WebKit2/UIProcess/PageClient.h index c94ea1a13..bd6096c93 100644 --- a/Source/WebKit2/UIProcess/PageClient.h +++ b/Source/WebKit2/UIProcess/PageClient.h @@ -106,11 +106,12 @@ public: #if PLATFORM(QT) virtual void didChangeContentsSize(const WebCore::IntSize&) = 0; virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&) = 0; - virtual void focusEditableArea(const WebCore::IntRect&, const WebCore::IntRect&) = 0; virtual void didReceiveMessageFromNavigatorQtObject(const String&) = 0; virtual void handleDownloadRequest(DownloadProxy*) = 0; virtual void updateTextInputState() = 0; -#endif + virtual void handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password) = 0; + virtual void handleCertificateVerificationRequest(const String& hostname, bool& ignoreErrors) = 0; +#endif // PLATFORM(QT). #if PLATFORM(QT) || PLATFORM(GTK) virtual void startDrag(const WebCore::DragData&, PassRefPtr<ShareableBitmap> dragImage) = 0; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp index 41c7a47cb..893f84732 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -31,18 +31,20 @@ #include "PluginProcessCreationParameters.h" #include "PluginProcessManager.h" #include "PluginProcessMessages.h" -#include "RunLoop.h" #include "WebContext.h" #include "WebCoreArgumentCoders.h" #include "WebPluginSiteDataManager.h" #include "WebProcessMessages.h" #include "WebProcessProxy.h" #include <WebCore/NotImplemented.h> +#include <WebCore/RunLoop.h> #if PLATFORM(MAC) #include "MachPort.h" #endif +using namespace WebCore; + namespace WebKit { PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo) diff --git a/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp b/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp index 057cc7435..87838ca26 100644 --- a/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp +++ b/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "ResponsivenessTimer.h" +using namespace WebCore; + namespace WebKit { static const double kResponsivenessTimeout = 3; diff --git a/Source/WebKit2/UIProcess/ResponsivenessTimer.h b/Source/WebKit2/UIProcess/ResponsivenessTimer.h index 659191612..36733151f 100644 --- a/Source/WebKit2/UIProcess/ResponsivenessTimer.h +++ b/Source/WebKit2/UIProcess/ResponsivenessTimer.h @@ -26,7 +26,7 @@ #ifndef ResponsivenessTimer_h #define ResponsivenessTimer_h -#include "RunLoop.h" +#include <WebCore/RunLoop.h> namespace WebKit { @@ -55,7 +55,7 @@ private: ResponsivenessTimer::Client* m_client; bool m_isResponsive; - RunLoop::Timer<ResponsivenessTimer> m_timer; + WebCore::RunLoop::Timer<ResponsivenessTimer> m_timer; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/TiledDrawingAreaProxy.h b/Source/WebKit2/UIProcess/TiledDrawingAreaProxy.h index 855977de9..0fcccf4e1 100644 --- a/Source/WebKit2/UIProcess/TiledDrawingAreaProxy.h +++ b/Source/WebKit2/UIProcess/TiledDrawingAreaProxy.h @@ -31,10 +31,9 @@ #include "DrawingAreaProxy.h" #include <WebCore/GraphicsContext.h> #include <WebCore/IntRect.h> +#include <WebCore/RunLoop.h> #include <wtf/HashSet.h> -#include "RunLoop.h" - #if PLATFORM(MAC) #include <wtf/RetainPtr.h> #ifdef __OBJC__ diff --git a/Source/WebKit2/UIProcess/VisitedLinkProvider.h b/Source/WebKit2/UIProcess/VisitedLinkProvider.h index a428d5b83..461c5ac94 100644 --- a/Source/WebKit2/UIProcess/VisitedLinkProvider.h +++ b/Source/WebKit2/UIProcess/VisitedLinkProvider.h @@ -26,9 +26,9 @@ #ifndef VisitedLinkProvider_h #define VisitedLinkProvider_h -#include "RunLoop.h" #include "VisitedLinkTable.h" #include <WebCore/LinkHash.h> +#include <WebCore/RunLoop.h> #include <wtf/Forward.h> #include <wtf/HashSet.h> @@ -58,7 +58,7 @@ private: VisitedLinkTable m_table; HashSet<WebCore::LinkHash, WebCore::LinkHashHash> m_pendingVisitedLinks; - RunLoop::Timer<VisitedLinkProvider> m_pendingVisitedLinksTimer; + WebCore::RunLoop::Timer<VisitedLinkProvider> m_pendingVisitedLinksTimer; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebConnectionToWebProcess.cpp b/Source/WebKit2/UIProcess/WebConnectionToWebProcess.cpp index b1d103fbc..be814c0a9 100644 --- a/Source/WebKit2/UIProcess/WebConnectionToWebProcess.cpp +++ b/Source/WebKit2/UIProcess/WebConnectionToWebProcess.cpp @@ -30,6 +30,8 @@ #include "WebContextUserMessageCoders.h" #include "WebProcessProxy.h" +using namespace WebCore; + namespace WebKit { PassRefPtr<WebConnectionToWebProcess> WebConnectionToWebProcess::create(WebProcessProxy* process, CoreIPC::Connection::Identifier connectionIdentifier, RunLoop* runLoop) diff --git a/Source/WebKit2/UIProcess/WebConnectionToWebProcess.h b/Source/WebKit2/UIProcess/WebConnectionToWebProcess.h index b9d58f2c7..f4962e26c 100644 --- a/Source/WebKit2/UIProcess/WebConnectionToWebProcess.h +++ b/Source/WebKit2/UIProcess/WebConnectionToWebProcess.h @@ -35,14 +35,14 @@ class WebProcessProxy; class WebConnectionToWebProcess : public WebConnection, CoreIPC::Connection::Client { public: - static PassRefPtr<WebConnectionToWebProcess> create(WebProcessProxy*, CoreIPC::Connection::Identifier, RunLoop*); + static PassRefPtr<WebConnectionToWebProcess> create(WebProcessProxy*, CoreIPC::Connection::Identifier, WebCore::RunLoop*); CoreIPC::Connection* connection() { return m_connection.get(); } void invalidate(); private: - WebConnectionToWebProcess(WebProcessProxy*, CoreIPC::Connection::Identifier, RunLoop*); + WebConnectionToWebProcess(WebProcessProxy*, CoreIPC::Connection::Identifier, WebCore::RunLoop*); // WebConnection virtual void postMessage(const String&, APIObject*); diff --git a/Source/WebKit2/UIProcess/WebContext.cpp b/Source/WebKit2/UIProcess/WebContext.cpp index 18bca116a..23ca56be6 100644 --- a/Source/WebKit2/UIProcess/WebContext.cpp +++ b/Source/WebKit2/UIProcess/WebContext.cpp @@ -31,7 +31,6 @@ #include "InjectedBundleMessageKinds.h" #include "Logging.h" #include "MutableDictionary.h" -#include "RunLoop.h" #include "SandboxExtension.h" #include "StatisticsData.h" #include "TextChecker.h" @@ -58,6 +57,7 @@ #include <WebCore/LinkHash.h> #include <WebCore/Logging.h> #include <WebCore/ResourceRequest.h> +#include <WebCore/RunLoop.h> #include <runtime/InitializeThreading.h> #include <wtf/CurrentTime.h> #include <wtf/MainThread.h> @@ -231,7 +231,7 @@ void WebContext::languageChanged(void* context) void WebContext::languageChanged() { - sendToAllProcesses(Messages::WebProcess::LanguageChanged(defaultLanguage())); + sendToAllProcesses(Messages::WebProcess::UserPreferredLanguagesChanged(userPreferredLanguages())); } void WebContext::fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled) @@ -255,7 +255,7 @@ void WebContext::ensureWebProcess() parameters.shouldTrackVisitedLinks = m_historyClient.shouldTrackVisitedLinks(); parameters.cacheModel = m_cacheModel; - parameters.languageCode = defaultLanguage(); + parameters.languages = userPreferredLanguages(); parameters.applicationCacheDirectory = applicationCacheDirectory(); parameters.databaseDirectory = databaseDirectory(); parameters.localStorageDirectory = localStorageDirectory(); @@ -281,6 +281,10 @@ void WebContext::ensureWebProcess() parameters.defaultRequestTimeoutInterval = WebURLRequest::defaultTimeoutInterval(); +#if ENABLE(NOTIFICATIONS) + m_notificationManagerProxy->populateCopyOfNotificationPermissions(parameters.notificationPermissions); +#endif + // Add any platform specific parameters platformInitializeWebProcess(parameters); diff --git a/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp b/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp index 26c518fd8..e61faa162 100644 --- a/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebDatabaseManagerProxy.cpp @@ -137,7 +137,7 @@ void WebDatabaseManagerProxy::didGetDatabasesByOrigin(const Vector<OriginAndData for (size_t i = 0; i < originAndDatabasesCount; ++i) { const OriginAndDatabases& originAndDatabases = originAndDatabasesVector[i]; - RefPtr<APIObject> origin = WebSecurityOrigin::create(originAndDatabases.originIdentifier); + RefPtr<APIObject> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originAndDatabases.originIdentifier); size_t databasesCount = originAndDatabases.databases.size(); Vector<RefPtr<APIObject> > databases(databasesCount); @@ -188,7 +188,7 @@ void WebDatabaseManagerProxy::didGetDatabaseOrigins(const Vector<String>& origin Vector<RefPtr<APIObject> > securityOrigins(originIdentifiersCount); for (size_t i = 0; i < originIdentifiersCount; ++i) - securityOrigins[i] = WebSecurityOrigin::create(originIdentifiers[i]); + securityOrigins[i] = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifiers[i]); callback->performCallbackWithReturnValue(ImmutableArray::adopt(securityOrigins).get()); } @@ -219,13 +219,13 @@ void WebDatabaseManagerProxy::setQuotaForOrigin(WebSecurityOrigin* origin, uint6 void WebDatabaseManagerProxy::didModifyOrigin(const String& originIdentifier) { - RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier); + RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier); m_client.didModifyOrigin(this, origin.get()); } void WebDatabaseManagerProxy::didModifyDatabase(const String& originIdentifier, const String& databaseIdentifier) { - RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier); + RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier); m_client.didModifyDatabase(this, origin.get(), databaseIdentifier); } diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp index a7057e083..825420a4a 100644 --- a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp +++ b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp @@ -148,6 +148,7 @@ void WebInspectorProxy::detach() void WebInspectorProxy::setAttachedWindowHeight(unsigned height) { + inspectorPageGroup()->preferences()->setInspectorAttachedHeight(height); platformSetAttachedWindowHeight(height); } diff --git a/Source/WebKit2/UIProcess/WebLoaderClient.cpp b/Source/WebKit2/UIProcess/WebLoaderClient.cpp index 624169e4e..87feea062 100644 --- a/Source/WebKit2/UIProcess/WebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/WebLoaderClient.cpp @@ -123,6 +123,14 @@ void WebLoaderClient::didFirstVisuallyNonEmptyLayoutForFrame(WebPageProxy* page, m_client.didFirstVisuallyNonEmptyLayoutForFrame(toAPI(page), toAPI(frame), toAPI(userData), m_client.clientInfo); } +void WebLoaderClient::didNewFirstVisuallyNonEmptyLayout(WebPageProxy* page, APIObject* userData) +{ + if (!m_client.didNewFirstVisuallyNonEmptyLayout) + return; + + m_client.didNewFirstVisuallyNonEmptyLayout(toAPI(page), toAPI(userData), m_client.clientInfo); +} + void WebLoaderClient::didRemoveFrameFromHierarchy(WebPageProxy* page, WebFrameProxy* frame, APIObject* userData) { if (!m_client.didRemoveFrameFromHierarchy) diff --git a/Source/WebKit2/UIProcess/WebLoaderClient.h b/Source/WebKit2/UIProcess/WebLoaderClient.h index 9fe8fce2f..970591937 100644 --- a/Source/WebKit2/UIProcess/WebLoaderClient.h +++ b/Source/WebKit2/UIProcess/WebLoaderClient.h @@ -64,6 +64,10 @@ public: void didDisplayInsecureContentForFrame(WebPageProxy*, WebFrameProxy*, APIObject*); void didRunInsecureContentForFrame(WebPageProxy*, WebFrameProxy*, APIObject*); void didDetectXSSForFrame(WebPageProxy*, WebFrameProxy*, APIObject*); + + // FIXME: didFirstVisuallyNonEmptyLayoutForFrame and didNewFirstVisuallyNonEmptyLayout should be merged. + // The only reason for both to exist is to experiment with different heuristics for the time being. + void didNewFirstVisuallyNonEmptyLayout(WebPageProxy*, APIObject*); bool canAuthenticateAgainstProtectionSpaceInFrame(WebPageProxy*, WebFrameProxy*, WebProtectionSpace*); void didReceiveAuthenticationChallengeInFrame(WebPageProxy*, WebFrameProxy*, AuthenticationChallengeProxy*); diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index 7e08cecd8..b945ef0b5 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -166,6 +166,7 @@ WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> p , m_areMemoryCacheClientCallsEnabled(true) , m_useFixedLayout(false) , m_paginationMode(Page::Pagination::Unpaginated) + , m_paginationBehavesLikeColumns(false) , m_pageLength(0) , m_gapBetweenPages(0) , m_isValid(true) @@ -199,6 +200,7 @@ WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> p , m_pageCount(0) , m_renderTreeSize(0) , m_shouldSendEventsSynchronously(false) + , m_mediaVolume(1) { #ifndef NDEBUG webPageProxyCounter.increment(); @@ -976,6 +978,13 @@ void WebPageProxy::handleGestureEvent(const WebGestureEvent& event) #endif #if ENABLE(TOUCH_EVENTS) +#if PLATFORM(QT) +void WebPageProxy::handlePotentialActivation(const IntPoint& layoutPoint) +{ + process()->send(Messages::WebPage::HighlightPotentialActivation(layoutPoint), m_pageID); +} +#endif + void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event) { if (!isValid()) @@ -1305,6 +1314,18 @@ void WebPageProxy::setPaginationMode(WebCore::Page::Pagination::Mode mode) process()->send(Messages::WebPage::SetPaginationMode(mode), m_pageID); } +void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns) +{ + if (behavesLikeColumns == m_paginationBehavesLikeColumns) + return; + + m_paginationBehavesLikeColumns = behavesLikeColumns; + + if (!isValid()) + return; + process()->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID); +} + void WebPageProxy::setPageLength(double pageLength) { if (pageLength == m_pageLength) @@ -1858,6 +1879,16 @@ void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, Core m_loaderClient.didFirstVisuallyNonEmptyLayoutForFrame(this, frame, userData.get()); } +void WebPageProxy::didNewFirstVisuallyNonEmptyLayout(CoreIPC::ArgumentDecoder* arguments) +{ + RefPtr<APIObject> userData; + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); + if (!arguments->decode(messageDecoder)) + return; + + m_loaderClient.didNewFirstVisuallyNonEmptyLayout(this, userData.get()); +} + void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, CoreIPC::ArgumentDecoder* arguments) { RefPtr<APIObject> userData; @@ -2320,6 +2351,19 @@ void WebPageProxy::printMainFrame() printFrame(m_mainFrame->frameID()); } +void WebPageProxy::setMediaVolume(float volume) +{ + if (volume == m_mediaVolume) + return; + + m_mediaVolume = volume; + + if (!isValid()) + return; + + process()->send(Messages::WebPage::SetMediaVolume(volume), m_pageID); +} + #if PLATFORM(QT) void WebPageProxy::didChangeContentsSize(const IntSize& size) { @@ -2331,11 +2375,6 @@ void WebPageProxy::didFindZoomableArea(const IntPoint& target, const IntRect& ar m_pageClient->didFindZoomableArea(target, area); } -void WebPageProxy::focusEditableArea(const WebCore::IntRect& caret, const WebCore::IntRect& area) -{ - m_pageClient->focusEditableArea(caret, area); -} - void WebPageProxy::findZoomableAreaForPoint(const IntPoint& point) { if (!isValid()) @@ -2353,7 +2392,17 @@ void WebPageProxy::handleDownloadRequest(DownloadProxy* download) { m_pageClient->handleDownloadRequest(download); } -#endif + +void WebPageProxy::authenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password) +{ + m_pageClient->handleAuthenticationRequiredRequest(hostname, realm, prefilledUsername, username, password); +} + +void WebPageProxy::certificateVerificationRequest(const String& hostname, bool& ignoreErrors) +{ + m_pageClient->handleCertificateVerificationRequest(hostname, ignoreErrors); +} +#endif // PLATFORM(QT). #if ENABLE(TOUCH_EVENTS) void WebPageProxy::needTouchEvents(bool needTouchEvents) @@ -3234,6 +3283,7 @@ WebPageCreationParameters WebPageProxy::creationParameters() const parameters.useFixedLayout = m_useFixedLayout; parameters.fixedLayoutSize = m_fixedLayoutSize; parameters.paginationMode = m_paginationMode; + parameters.paginationBehavesLikeColumns = m_paginationBehavesLikeColumns; parameters.pageLength = m_pageLength; parameters.gapBetweenPages = m_gapBetweenPages; parameters.userAgent = userAgent(); @@ -3242,6 +3292,7 @@ WebPageCreationParameters WebPageProxy::creationParameters() const parameters.canRunBeforeUnloadConfirmPanel = m_uiClient.canRunBeforeUnloadConfirmPanel(); parameters.canRunModal = m_uiClient.canRunModal(); parameters.deviceScaleFactor = m_intrinsicDeviceScaleFactor; + parameters.mediaVolume = m_mediaVolume; #if PLATFORM(MAC) parameters.isSmartInsertDeleteEnabled = m_isSmartInsertDeleteEnabled; @@ -3296,7 +3347,7 @@ void WebPageProxy::exceededDatabaseQuota(uint64_t frameID, const String& originI WebFrameProxy* frame = process()->webFrame(frameID); MESSAGE_CHECK(frame); - RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier); + RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier); newQuota = m_uiClient.exceededDatabaseQuota(this, frame, origin.get(), databaseName, displayName, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); } @@ -3306,28 +3357,29 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID, WebFrameProxy* frame = process()->webFrame(frameID); MESSAGE_CHECK(frame); - RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier); + // FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier(). + RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originIdentifier); RefPtr<GeolocationPermissionRequestProxy> request = m_geolocationPermissionRequestManager.createRequest(geolocationID); if (!m_uiClient.decidePolicyForGeolocationPermissionRequest(this, frame, origin.get(), request.get())) request->deny(); } -void WebPageProxy::requestNotificationPermission(uint64_t requestID, const String& originIdentifier) +void WebPageProxy::requestNotificationPermission(uint64_t requestID, const String& originString) { if (!isRequestIDValid(requestID)) return; - RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::create(originIdentifier); + RefPtr<WebSecurityOrigin> origin = WebSecurityOrigin::createFromString(originString); RefPtr<NotificationPermissionRequest> request = m_notificationPermissionRequestManager.createRequest(requestID); if (!m_uiClient.decidePolicyForNotificationPermissionRequest(this, origin.get(), request.get())) request->deny(); } -void WebPageProxy::showNotification(const String& title, const String& body, const String& originIdentifier, uint64_t notificationID) +void WebPageProxy::showNotification(const String& title, const String& body, const String& originString, uint64_t notificationID) { - m_process->context()->notificationManagerProxy()->show(this, title, body, originIdentifier, notificationID); + m_process->context()->notificationManagerProxy()->show(this, title, body, originString, notificationID); } float WebPageProxy::headerHeight(WebFrameProxy* frame) @@ -3475,6 +3527,20 @@ void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, const PrintInfo& printIn m_dataCallbacks.set(callbackID, callback.get()); process()->send(Messages::WebPage::DrawPagesToPDF(frame->frameID(), printInfo, first, count, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0); } +#elif PLATFORM(GTK) +void WebPageProxy::drawPagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<VoidCallback> didPrintCallback) +{ + RefPtr<VoidCallback> callback = didPrintCallback; + if (!isValid()) { + callback->invalidate(); + return; + } + + uint64_t callbackID = callback->callbackID(); + m_voidCallbacks.set(callbackID, callback.get()); + m_isInPrintingMode = true; + process()->send(Messages::WebPage::DrawPagesForPrinting(frame->frameID(), printInfo, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0); +} #endif void WebPageProxy::flashBackingStoreUpdates(const Vector<IntRect>& updateRects) diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index cf5130419..caa5df4a2 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -107,6 +107,12 @@ class WKView; #endif #endif +#if PLATFORM(GTK) +typedef GtkWidget* PlatformWidget; +#elif PLATFORM(EFL) +typedef Evas_Object* PlatformWidget; +#endif + namespace WebKit { class NativeWebKeyboardEvent; @@ -314,7 +320,9 @@ public: void registerApplicationScheme(const String& scheme); void resolveApplicationSchemeRequest(QtNetworkRequestData); void sendApplicationSchemeReply(const QQuickNetworkReply*); -#endif + void authenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password); + void certificateVerificationRequest(const String& hostname, bool& ignoreErrors); +#endif // PLATFORM(QT). #if PLATFORM(QT) void setComposition(const String& text, Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd); @@ -358,11 +366,8 @@ public: HWND nativeWindow() const; #endif -#if PLATFORM(GTK) - GtkWidget* viewWidget(); -#endif -#if PLATFORM(EFL) - Evas_Object* viewObject(); +#if USE(CAIRO) && !PLATFORM(WIN_CAIRO) + PlatformWidget viewWidget(); #endif #if USE(TILED_BACKING_STORE) void setFixedVisibleContentRect(const WebCore::IntRect&); @@ -377,6 +382,9 @@ public: #endif #if ENABLE(TOUCH_EVENTS) void handleTouchEvent(const NativeWebTouchEvent&); +#if PLATFORM(QT) + void handlePotentialActivation(const WebCore::IntPoint&); +#endif #endif void scrollBy(WebCore::ScrollDirection, WebCore::ScrollGranularity); @@ -433,6 +441,8 @@ public: void setPaginationMode(WebCore::Page::Pagination::Mode); WebCore::Page::Pagination::Mode paginationMode() const { return m_paginationMode; } + void setPaginationBehavesLikeColumns(bool); + bool paginationBehavesLikeColumns() const { return m_paginationBehavesLikeColumns; } void setPageLength(double); double pageLength() const { return m_pageLength; } void setGapBetweenPages(double); @@ -567,12 +577,18 @@ public: void setSmartInsertDeleteEnabled(bool); #endif +#if PLATFORM(GTK) + String accessibilityPlugID() const { return m_accessibilityPlugID; } +#endif + void beginPrinting(WebFrameProxy*, const PrintInfo&); void endPrinting(); void computePagesForPrinting(WebFrameProxy*, const PrintInfo&, PassRefPtr<ComputedPagesCallback>); #if PLATFORM(MAC) || PLATFORM(WIN) void drawRectToPDF(WebFrameProxy*, const PrintInfo&, const WebCore::IntRect&, PassRefPtr<DataCallback>); void drawPagesToPDF(WebFrameProxy*, const PrintInfo&, uint32_t first, uint32_t count, PassRefPtr<DataCallback>); +#elif PLATFORM(GTK) + void drawPagesForPrinting(WebFrameProxy*, const PrintInfo&, PassRefPtr<VoidCallback>); #endif const String& pendingAPIRequestURL() const { return m_pendingAPIRequestURL; } @@ -603,6 +619,8 @@ public: void setShouldSendEventsSynchronously(bool sync) { m_shouldSendEventsSynchronously = sync; }; void printMainFrame(); + + void setMediaVolume(float); // WebPopupMenuProxy::Client virtual NativeWebMouseEvent* currentlyProcessedMouseDownEvent(); @@ -639,6 +657,7 @@ private: void didReceiveTitleForFrame(uint64_t frameID, const String&, CoreIPC::ArgumentDecoder*); void didFirstLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder*); void didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder*); + void didNewFirstVisuallyNonEmptyLayout(CoreIPC::ArgumentDecoder*); void didRemoveFrameFromHierarchy(uint64_t frameID, CoreIPC::ArgumentDecoder*); void didDisplayInsecureContentForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder*); void didRunInsecureContentForFrame(uint64_t frameID, CoreIPC::ArgumentDecoder*); @@ -705,8 +724,8 @@ private: void reattachToWebProcess(); void reattachToWebProcessWithItem(WebBackForwardListItem*); - void requestNotificationPermission(uint64_t notificationID, const String& originIdentifier); - void showNotification(const String& title, const String& body, const String& originIdentifier, uint64_t notificationID); + void requestNotificationPermission(uint64_t notificationID, const String& originString); + void showNotification(const String& title, const String& body, const String& originString, uint64_t notificationID); #if USE(TILED_BACKING_STORE) void pageDidRequestScroll(const WebCore::IntPoint&); @@ -715,7 +734,6 @@ private: #if PLATFORM(QT) void didChangeContentsSize(const WebCore::IntSize&); void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&); - void focusEditableArea(const WebCore::IntRect& caret, const WebCore::IntRect&); #endif #if ENABLE(TOUCH_EVENTS) void needTouchEvents(bool); @@ -745,6 +763,7 @@ private: #if PLATFORM(GTK) void getEditorCommandsForKeyEvent(const AtomicString&, Vector<String>&); + void bindAccessibilityTree(const String&); #endif #if PLATFORM(EFL) void getEditorCommandsForKeyEvent(Vector<String>&); @@ -930,6 +949,7 @@ private: WebCore::IntSize m_fixedLayoutSize; WebCore::Page::Pagination::Mode m_paginationMode; + bool m_paginationBehavesLikeColumns; double m_pageLength; double m_gapBetweenPages; @@ -974,6 +994,10 @@ private: bool m_isSmartInsertDeleteEnabled; #endif +#if PLATFORM(GTK) + String m_accessibilityPlugID; +#endif + int64_t m_spellDocumentTag; bool m_hasSpellDocumentTag; unsigned m_pendingLearnOrIgnoreWordMessageCount; @@ -999,9 +1023,11 @@ private: static WKPageDebugPaintFlags s_debugPaintFlags; bool m_shouldSendEventsSynchronously; + + float m_mediaVolume; #if PLATFORM(QT) - WTF::HashSet<RefPtr<QtNetworkRequestData> > m_applicationSchemeRequests; + WTF::HashSet<RefPtr<QtRefCountedNetworkRequestData> > m_applicationSchemeRequests; #endif }; diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in index 5c2133ab4..8c8ce4995 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in @@ -74,7 +74,8 @@ messages -> WebPageProxy { #if PLATFORM(QT) DidChangeContentsSize(WebCore::IntSize newSize) DidFindZoomableArea(WebCore::IntPoint target, WebCore::IntRect area) - FocusEditableArea(WebCore::IntRect caret, WebCore::IntRect area) + AuthenticationRequiredRequest(WTF::String hostname, WTF::String realm, WTF::String prefilledUsername) -> (WTF::String username, WTF::String password) + CertificateVerificationRequest(WTF::String hostname) -> (bool ignoreErrors) #endif #if ENABLE(TOUCH_EVENTS) NeedTouchEvents(bool needTouchEvents) @@ -105,6 +106,7 @@ messages -> WebPageProxy { DidFinishLoadForFrame(uint64_t frameID, WebKit::InjectedBundleUserMessageEncoder userData) DidFirstLayoutForFrame(uint64_t frameID, WebKit::InjectedBundleUserMessageEncoder userData) DidFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, WebKit::InjectedBundleUserMessageEncoder userData) + DidNewFirstVisuallyNonEmptyLayout(WebKit::InjectedBundleUserMessageEncoder userData) DidReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, WTF::String url, WebKit::InjectedBundleUserMessageEncoder userData) DidRemoveFrameFromHierarchy(uint64_t frameID, WebKit::InjectedBundleUserMessageEncoder userData) DidStartProvisionalLoadForFrame(uint64_t frameID, WTF::String url, WTF::String unreachableURL, WebKit::InjectedBundleUserMessageEncoder userData) @@ -147,6 +149,9 @@ messages -> WebPageProxy { #if PLATFORM(GTK) # Support for GTK+ platform keybindings GetEditorCommandsForKeyEvent(AtomicString eventType) -> (Vector<WTF::String> commandsList) + + # Support for connecting the Accessibility worlds of the UI and the Web processes + BindAccessibilityTree(WTF::String plugID) #endif # BackForward messages diff --git a/Source/WebKit2/UIProcess/WebPreferences.h b/Source/WebKit2/UIProcess/WebPreferences.h index 0f4943ab6..53b610200 100644 --- a/Source/WebKit2/UIProcess/WebPreferences.h +++ b/Source/WebKit2/UIProcess/WebPreferences.h @@ -69,6 +69,9 @@ public: #undef DECLARE_PREFERENCE_GETTER_AND_SETTERS + // Exposed for WebKitTestRunner use only. + void forceUpdate() { update(); } + private: WebPreferences(); WebPreferences(const String& identifier); diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.cpp b/Source/WebKit2/UIProcess/WebProcessProxy.cpp index 8c99b4efa..2109d9e7a 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/WebProcessProxy.cpp @@ -334,11 +334,6 @@ void WebProcessProxy::didReceiveSyncMessage(CoreIPC::Connection* connection, Cor return; } - if (messageID.is<CoreIPC::MessageClassWebNotificationManagerProxy>()) { - m_context->notificationManagerProxy()->didReceiveSyncMessage(connection, messageID, arguments, reply); - return; - } - uint64_t pageID = arguments->destinationID(); if (!pageID) return; diff --git a/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp b/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp index 51608a588..fec82b773 100644 --- a/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp +++ b/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp @@ -33,6 +33,10 @@ #include <WebCore/GraphicsContext.h> #include <cairo/cairo.h> +#if PLATFORM(EFL) +#include "ewk_private.h" +#endif + using namespace WebCore; namespace WebKit { @@ -64,6 +68,11 @@ void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& srcRect.move(-updateRectLocation.x(), -updateRectLocation.y()); bitmap->paint(graphicsContext, updateRect.location(), srcRect); } + +#if PLATFORM(EFL) + // Update ewk_view with new backingStore image. + ewk_view_image_data_set(m_webPageProxy->viewWidget(), cairo_image_surface_get_data(m_backingStore->cairoSurface()), m_size); +#endif } void BackingStore::scroll(const IntRect& scrollRect, const IntSize& scrollOffset) diff --git a/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp b/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp index 41fd01baa..0524bc517 100644 --- a/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp +++ b/Source/WebKit2/UIProcess/cf/WebPageProxyCF.cpp @@ -44,7 +44,7 @@ namespace WebKit { DEFINE_STATIC_GETTER(CFStringRef, SessionHistoryKey, (CFSTR("SessionHistory"))); DEFINE_STATIC_GETTER(CFStringRef, ProvisionalURLKey, (CFSTR("ProvisionalURL"))); -static const UInt32 CurrentSessionStateDataVersion = 3; +static const UInt32 CurrentSessionStateDataVersion = 2; PassRefPtr<WebData> WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback filter, void* context) const { diff --git a/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp index ae314b857..b076b4ef6 100644 --- a/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp +++ b/Source/WebKit2/UIProcess/efl/WebPageProxyEfl.cpp @@ -33,9 +33,9 @@ namespace WebKit { -Evas_Object* WebPageProxy::viewObject() +Evas_Object* WebPageProxy::viewWidget() { - return static_cast<PageClientImpl*>(m_pageClient)->viewObject(); + return static_cast<PageClientImpl*>(m_pageClient)->viewWidget(); } String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent) diff --git a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp index 1127dde84..f6b300eb7 100644 --- a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp @@ -49,6 +49,11 @@ void WebPageProxy::getEditorCommandsForKeyEvent(const AtomicString& eventType, V m_pageClient->getEditorCommandsForKeyEvent(m_keyEventQueue.first(), eventType, commandsList); } +void WebPageProxy::bindAccessibilityTree(const String& plugID) +{ + m_accessibilityPlugID = plugID; +} + void WebPageProxy::saveRecentSearches(const String&, const Vector<String>&) { notImplemented(); diff --git a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm index 26410bce0..d43a2ac04 100644 --- a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm @@ -32,7 +32,9 @@ #import "WebContext.h" #import "WKInspectorMac.h" #import "WKViewPrivate.h" +#import "WebPageGroup.h" #import "WebPageProxy.h" +#import "WebPreferences.h" #import "WebProcessProxy.h" #import <WebKitSystemInterface.h> #import <WebCore/InspectorFrontendClientLocal.h> @@ -207,6 +209,10 @@ void WebInspectorProxy::platformAttach() [m_inspectorView.get() removeFromSuperview]; + // The inspector view shares the width and the left starting point of the inspected view. + NSRect inspectedViewFrame = [inspectedView frame]; + [m_inspectorView.get() setFrame:NSMakeRect(NSMinX(inspectedViewFrame), 0, NSWidth(inspectedViewFrame), inspectorPageGroup()->preferences()->inspectorAttachedHeight())]; + [[inspectedView superview] addSubview:m_inspectorView.get() positioned:NSWindowBelow relativeTo:inspectedView]; [m_inspectorWindow.get() orderOut:nil]; @@ -249,9 +255,6 @@ void WebInspectorProxy::platformSetAttachedWindowHeight(unsigned height) [m_inspectorView.get() setFrame:NSMakeRect(NSMinX(inspectedViewFrame), 0.0, NSWidth(inspectedViewFrame), height)]; inspectedViewFrameDidChange(); - - [m_inspectorView.get() setNeedsDisplay:YES]; - [inspectedView setNeedsDisplay:YES]; } String WebInspectorProxy::inspectorPageURL() const diff --git a/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm index 37e8caae0..66422a147 100644 --- a/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebProcessProxyMac.mm @@ -74,12 +74,25 @@ static void handleSecItemRequest(CoreIPC::Connection* connection, uint64_t reque connection->send(Messages::WebProcess::SecItemResponse(requestID, response), 0); } +static void dispatchFunctionOnQueue(dispatch_queue_t queue, const Function<void ()>& function) +{ +#if COMPILER(CLANG) + dispatch_async(queue, function); +#else + Function<void ()>* functionPtr = new Function<void ()>(function); + dispatch_async(queue, ^{ + (*functionPtr)(); + delete functionPtr; + }); +#endif +} + void WebProcessProxy::secItemRequest(CoreIPC::Connection* connection, uint64_t requestID, const SecItemRequestData& request) { // Since we don't want the connection work queue to be held up, we do all // keychain interaction work on a global dispatch queue. dispatch_queue_t keychainWorkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_async(keychainWorkQueue, bind(handleSecItemRequest, RefPtr<CoreIPC::Connection>(connection), requestID, request)); + dispatchFunctionOnQueue(keychainWorkQueue, bind(handleSecItemRequest, RefPtr<CoreIPC::Connection>(connection), requestID, request)); } static void handleSecKeychainItemRequest(CoreIPC::Connection* connection, uint64_t requestID, const SecKeychainItemRequestData& request) @@ -128,7 +141,7 @@ void WebProcessProxy::secKeychainItemRequest(CoreIPC::Connection* connection, ui // Since we don't want the connection work queue to be held up, we do all // keychain interaction work on a global dispatch queue. dispatch_queue_t keychainWorkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_async(keychainWorkQueue, bind(handleSecKeychainItemRequest, RefPtr<CoreIPC::Connection>(connection), requestID, request)); + dispatchFunctionOnQueue(keychainWorkQueue, bind(handleSecKeychainItemRequest, RefPtr<CoreIPC::Connection>(connection), requestID, request)); } bool WebProcessProxy::fullKeyboardAccessEnabled() diff --git a/Source/WebKit2/UIProcess/qt/LayerTreeHostProxyQt.cpp b/Source/WebKit2/UIProcess/qt/LayerTreeHostProxyQt.cpp index 60736b1df..8969bbbe3 100644 --- a/Source/WebKit2/UIProcess/qt/LayerTreeHostProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/LayerTreeHostProxyQt.cpp @@ -27,6 +27,7 @@ #include "MessageID.h" #include "ShareableBitmap.h" #include "TextureMapperGL.h" +#include "TextureMapperQt.h" #include "UpdateInfo.h" #include "WebCoreArgumentCoders.h" #include "WebLayerTreeInfo.h" @@ -57,6 +58,8 @@ public: virtual Type type() const = 0; }; +using namespace WebCore; + template<class MessageData, LayerTreeMessageToRenderer::Type messageType> class LayerTreeMessageToRendererWithData : public LayerTreeMessageToRenderer { public: @@ -94,7 +97,7 @@ struct UpdateTileMessageData { int remoteTileID; IntRect sourceRect; IntRect targetRect; - QImage image; + RefPtr<ShareableBitmap> bitmap; }; struct RemoveTileMessageData { @@ -104,7 +107,7 @@ struct RemoveTileMessageData { struct CreateImageMessageData { int64_t imageID; - QImage image; + RefPtr<ShareableBitmap> bitmap; }; struct DestroyImageMessageData { @@ -165,10 +168,11 @@ LayerTreeHostProxy::~LayerTreeHostProxy() } // This function needs to be reentrant. -void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity) +void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect) { if (!m_textureMapper) m_textureMapper = TextureMapperGL::create(); + ASSERT(dynamic_cast<TextureMapperGL*>(m_textureMapper.get())); syncRemoteContent(); GraphicsLayer* currentRootLayer = rootLayer(); @@ -182,11 +186,11 @@ void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& mat GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); - IntRect viewportRect(viewport[0], viewport[1], viewport[2], viewport[3]); m_textureMapper->setViewportSize(IntSize(viewport[2], viewport[3])); node->setTextureMapper(m_textureMapper.get()); m_textureMapper->beginPainting(); m_textureMapper->bindSurface(0); + m_textureMapper->beginClip(TransformationMatrix(), clipRect); if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) { currentRootLayer->setOpacity(opacity); @@ -194,20 +198,8 @@ void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& mat currentRootLayer->syncCompositingStateForThisLayerOnly(); } - TextureMapperNode::NodeRectMap nodeVisualContentsRectMap; - if (node->collectVisibleContentsRects(nodeVisualContentsRectMap, viewportRect)) { - TextureMapperNode::NodeRectMap::iterator endIterator = nodeVisualContentsRectMap.end(); - for (TextureMapperNode::NodeRectMap::iterator it = nodeVisualContentsRectMap.begin(); it != endIterator; ++it) { - WebLayerID layerID = it->first->id(); - // avoid updating non-synced root layer - if (!layerID) - continue; - IntRect visibleRect = IntRect(it->second); - setVisibleContentsRectForLayer(layerID, visibleRect); - } - } node->paint(); - + m_textureMapper->endClip(); m_textureMapper->endPainting(); if (node->descendantsOrSelfHaveRunningAnimations()) { @@ -216,6 +208,28 @@ void LayerTreeHostProxy::paintToCurrentGLContext(const TransformationMatrix& mat } } +void LayerTreeHostProxy::paintToGraphicsContext(QPainter* painter) +{ + if (!m_textureMapper) + m_textureMapper = TextureMapperQt::create(); + ASSERT(dynamic_cast<TextureMapperQt*>(m_textureMapper.get())); + + syncRemoteContent(); + TextureMapperNode* node = toTextureMapperNode(rootLayer()); + + if (!node) + return; + + GraphicsContext graphicsContext(painter); + m_textureMapper->setGraphicsContext(&graphicsContext); + m_textureMapper->beginPainting(); + m_textureMapper->bindSurface(0); + node->paint(); + m_textureMapper->endPainting(); + m_textureMapper->setGraphicsContext(0); +} + + void LayerTreeHostProxy::didFireViewportUpdateTimer(Timer<LayerTreeHostProxy>*) { updateViewport(); @@ -226,11 +240,6 @@ void LayerTreeHostProxy::updateViewport() m_drawingAreaProxy->updateViewport(); } -void LayerTreeHostProxy::setVisibleContentsRectForLayer(WebLayerID layerID, const IntRect& rect) -{ - m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::SetVisibleContentRectForLayer(layerID, rect), m_drawingAreaProxy->page()->pageID()); -} - int LayerTreeHostProxy::remoteTileIDToNodeTileID(int tileID) const { HashMap<int, int>::const_iterator it = m_tileToNodeTile.find(tileID); @@ -245,6 +254,7 @@ void LayerTreeHostProxy::syncLayerParameters(const WebLayerInfo& layerInfo) ensureLayer(id); LayerMap::iterator it = m_layers.find(id); GraphicsLayer* layer = it->second; + bool needsToUpdateImageTiles = layerInfo.imageIsUpdated || layerInfo.contentsRect != layer->contentsRect(); layer->setName(layerInfo.name); @@ -261,7 +271,7 @@ void LayerTreeHostProxy::syncLayerParameters(const WebLayerInfo& layerInfo) layer->setContentsRect(layerInfo.contentsRect); layer->setDrawsContent(layerInfo.drawsContent); - if (layerInfo.imageIsUpdated) + if (needsToUpdateImageTiles) assignImageToLayer(layer, layerInfo.imageBackingStoreID); // Never make the root layer clip. @@ -366,7 +376,7 @@ void LayerTreeHostProxy::removeTile(WebLayerID layerID, int tileID) m_tileToNodeTile.remove(tileID); } -void LayerTreeHostProxy::updateTile(WebLayerID layerID, int tileID, const IntRect& sourceRect, const IntRect& targetRect, const QImage& image) +void LayerTreeHostProxy::updateTile(WebLayerID layerID, int tileID, const IntRect& sourceRect, const IntRect& targetRect, ShareableBitmap* bitmap) { ensureLayer(layerID); TextureMapperNode* node = toTextureMapperNode(layerByID(layerID)); @@ -377,15 +387,16 @@ void LayerTreeHostProxy::updateTile(WebLayerID layerID, int tileID, const IntRec if (!nodeTileID) return; - QImage imageRef(image); node->setTextureMapper(m_textureMapper.get()); - node->setContentsTileBackBuffer(nodeTileID, sourceRect, targetRect, imageRef.bits(), BitmapTexture::BGRAFormat); + QImage image = bitmap->createQImage(); + node->setContentsTileBackBuffer(nodeTileID, sourceRect, targetRect, image.constBits()); } -void LayerTreeHostProxy::createImage(int64_t imageID, const QImage& image) +void LayerTreeHostProxy::createImage(int64_t imageID, ShareableBitmap* bitmap) { TiledImage tiledImage; static const int TileDimension = 1024; + QImage image = bitmap->createQImage(); bool imageHasAlpha = image.hasAlphaChannel(); IntRect imageRect(0, 0, image.width(), image.height()); for (int y = 0; y < image.height(); y += TileDimension) { @@ -399,13 +410,12 @@ void LayerTreeHostProxy::createImage(int64_t imageID, const QImage& image) subImage = image.copy(rect); RefPtr<BitmapTexture> texture = m_textureMapper->createTexture(); texture->reset(rect.size(), !imageHasAlpha); - texture->updateContents(imageHasAlpha ? BitmapTexture::BGRAFormat : BitmapTexture::BGRFormat, IntRect(IntPoint::zero(), rect.size()), subImage.bits()); + texture->updateRawContents(IntRect(IntPoint::zero(), rect.size()), subImage.constBits()); tiledImage.add(rect.location(), texture); } } - m_directlyCompositedImages.remove(imageID); - m_directlyCompositedImages.add(imageID, tiledImage); + m_directlyCompositedImages.set(imageID, tiledImage); } void LayerTreeHostProxy::destroyImage(int64_t imageID) @@ -447,6 +457,8 @@ void LayerTreeHostProxy::assignImageToLayer(GraphicsLayer* layer, int64_t imageI void LayerTreeHostProxy::flushLayerChanges() { m_rootLayer->syncCompositingState(FloatRect()); + // The pending tiles state is on its way for the screen, tell the web process to render the next one. + m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::RenderNextFrame(), m_drawingAreaProxy->page()->pageID()); } void LayerTreeHostProxy::ensureRootLayer() @@ -504,18 +516,18 @@ void LayerTreeHostProxy::syncRemoteContent() case LayerTreeMessageToRenderer::UpdateTile: { const UpdateTileMessageData& data = static_cast<UpdateTileMessage*>(nextMessage.get())->data(); - updateTile(data.layerID, data.remoteTileID, data.sourceRect, data.targetRect, data.image); + updateTile(data.layerID, data.remoteTileID, data.sourceRect, data.targetRect, data.bitmap.get()); break; } case LayerTreeMessageToRenderer::CreateImage: { const CreateImageMessageData& data = static_cast<CreateImageMessage*>(nextMessage.get())->data(); - createImage(data.imageID, data.image); + createImage(data.imageID, data.bitmap.get()); break; } case LayerTreeMessageToRenderer::DestroyImage: { - const CreateImageMessageData& data = static_cast<CreateImageMessage*>(nextMessage.get())->data(); + const DestroyImageMessageData& data = static_cast<DestroyImageMessage*>(nextMessage.get())->data(); destroyImage(data.imageID); break; } @@ -548,8 +560,7 @@ void LayerTreeHostProxy::updateTileForLayer(int layerID, int tileID, const WebKi UpdateTileMessageData data; data.layerID = layerID; data.remoteTileID = tileID; - RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(updateInfo.bitmapHandle); - data.image = bitmap->createQImage().copy(); + data.bitmap = ShareableBitmap::create(updateInfo.bitmapHandle); data.sourceRect = IntRect(IntPoint::zero(), updateInfo.updateRectBounds.size()); data.targetRect = updateInfo.updateRectBounds; pushUpdateToQueue(UpdateTileMessage::create(data)); @@ -587,7 +598,6 @@ void LayerTreeHostProxy::syncCompositingLayerState(const WebLayerInfo& info) void LayerTreeHostProxy::didRenderFrame() { - m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::RenderNextFrame(), m_drawingAreaProxy->page()->pageID()); pushUpdateToQueue(FlushLayerChangesMessage::create()); updateViewport(); } @@ -595,9 +605,8 @@ void LayerTreeHostProxy::didRenderFrame() void LayerTreeHostProxy::createDirectlyCompositedImage(int64_t key, const WebKit::ShareableBitmap::Handle& handle) { CreateImageMessageData data; - RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(handle); data.imageID = key; - data.image = bitmap->createQImage().copy(); + data.bitmap = ShareableBitmap::create(handle); pushUpdateToQueue(CreateImageMessage::create(data)); } diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp index 32de21af7..f7e2b8514 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp @@ -69,6 +69,64 @@ private: QString m_defaultValue; }; +class AuthenticationDialogContextObject : public QObject { + Q_OBJECT + Q_PROPERTY(QString hostname READ hostname CONSTANT) + Q_PROPERTY(QString realm READ realm CONSTANT) + Q_PROPERTY(QString prefilledUsername READ prefilledUsername CONSTANT) + +public: + AuthenticationDialogContextObject(const QString& hostname, const QString& realm, const QString& prefilledUsername) + : QObject() + , m_hostname(hostname) + , m_realm(realm) + , m_prefilledUsername(prefilledUsername) + { + } + + QString hostname() const { return m_hostname; } + QString realm() const { return m_realm; } + QString prefilledUsername() const { return m_prefilledUsername; } + +public slots: + void accept(const QString& username, const QString& password) { emit accepted(username, password); } + void reject() { emit rejected(); } + +signals: + void accepted(const QString& username, const QString& password); + void rejected(); + +private: + QString m_hostname; + QString m_realm; + QString m_prefilledUsername; +}; + +class CertificateVerificationDialogContextObject : public QObject { + Q_OBJECT + Q_PROPERTY(QString hostname READ hostname CONSTANT) + +public: + CertificateVerificationDialogContextObject(const QString& hostname) + : QObject() + , m_hostname(hostname) + { + } + + QString hostname() const { return m_hostname; } + +public slots: + void accept() { emit accepted(); } + void reject() { emit rejected(); } + +signals: + void accepted(); + void rejected(); + +private: + QString m_hostname; +}; + bool QtDialogRunner::initForAlert(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& message) { DialogContextObject* contextObject = new DialogContextObject(message); @@ -103,6 +161,32 @@ bool QtDialogRunner::initForPrompt(QDeclarativeComponent* component, QQuickItem* return true; } +bool QtDialogRunner::initForAuthentication(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername) +{ + AuthenticationDialogContextObject* contextObject = new AuthenticationDialogContextObject(hostname, realm, prefilledUsername); + if (!createDialog(component, dialogParent, contextObject)) + return false; + + connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(onAuthenticationAccepted(QString, QString))); + connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(quit())); + connect(contextObject, SIGNAL(rejected()), SLOT(quit())); + + return true; +} + +bool QtDialogRunner::initForCertificateVerification(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& hostname) +{ + CertificateVerificationDialogContextObject* contextObject = new CertificateVerificationDialogContextObject(hostname); + if (!createDialog(component, dialogParent, contextObject)) + return false; + + connect(contextObject, SIGNAL(accepted()), SLOT(onAccepted())); + connect(contextObject, SIGNAL(accepted()), SLOT(quit())); + connect(contextObject, SIGNAL(rejected()), SLOT(quit())); + + return true; +} + bool QtDialogRunner::createDialog(QDeclarativeComponent* component, QQuickItem* dialogParent, QObject* contextObject) { QDeclarativeContext* baseContext = component->creationContext(); diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h index bfa530264..96dcea27f 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h @@ -38,12 +38,17 @@ public: bool initForAlert(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& message); bool initForConfirm(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& message); bool initForPrompt(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& message, const QString& defaultValue); + bool initForAuthentication(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername); + bool initForCertificateVerification(QDeclarativeComponent*, QQuickItem*, const QString& hostname); QQuickItem* dialog() const { return m_dialog.get(); } bool wasAccepted() const { return m_wasAccepted; } QString result() const { return m_result; } + QString username() const { return m_username; } + QString password() const { return m_password; } + public slots: void onAccepted(const QString& result = QString()) { @@ -51,6 +56,12 @@ public slots: m_result = result; } + void onAuthenticationAccepted(const QString& username, const QString& password) + { + m_username = username; + m_password = password; + } + private: bool createDialog(QDeclarativeComponent*, QQuickItem* dialogParent, QObject* contextObject); @@ -58,6 +69,9 @@ private: OwnPtr<QQuickItem> m_dialog; QString m_result; bool m_wasAccepted; + + QString m_username; + QString m_password; }; #endif // QtDialogRunner_h diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp index cc96876be..cdc863b61 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp @@ -62,7 +62,7 @@ PassOwnPtr<DrawingAreaProxy> QtPageClient::createDrawingAreaProxy() void QtPageClient::setViewNeedsDisplay(const WebCore::IntRect& rect) { - m_webView->page()->update(); + QQuickWebViewPrivate::get(m_webView)->setNeedsDisplay(); } void QtPageClient::pageDidRequestScroll(const IntPoint& pos) @@ -100,11 +100,27 @@ void QtPageClient::handleDownloadRequest(DownloadProxy* download) QQuickWebViewPrivate::get(m_webView)->handleDownloadRequest(download); } -void QtPageClient::handleApplicationSchemeRequest(PassRefPtr<QtNetworkRequestData> requestData) +void QtPageClient::handleApplicationSchemeRequest(PassRefPtr<QtRefCountedNetworkRequestData> requestData) { if (!m_webView || !m_webView->experimental()) return; - m_webView->experimental()->invokeApplicationSchemeHandler(requestData.get()); + m_webView->experimental()->invokeApplicationSchemeHandler(requestData); +} + +void QtPageClient::handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password) +{ + QString qUsername; + QString qPassword; + + QQuickWebViewPrivate::get(m_webView)->handleAuthenticationRequiredRequest(hostname, realm, prefilledUsername, qUsername, qPassword); + + username = qUsername; + password = qPassword; +} + +void QtPageClient::handleCertificateVerificationRequest(const String& hostname, bool& ignoreErrors) +{ + ignoreErrors = QQuickWebViewPrivate::get(m_webView)->handleCertificateVerificationRequest(hostname); } void QtPageClient::setCursor(const WebCore::Cursor& cursor) @@ -184,12 +200,6 @@ void QtPageClient::didFindZoomableArea(const IntPoint& target, const IntRect& ar m_eventHandler->didFindZoomableArea(target, area); } -void QtPageClient::focusEditableArea(const IntRect& caret, const IntRect& area) -{ - ASSERT(m_eventHandler); - m_eventHandler->focusEditableArea(caret, area); -} - void QtPageClient::didReceiveMessageFromNavigatorQtObject(const String& message) { QQuickWebViewPrivate::get(m_webView)->didReceiveMessageFromNavigatorQtObject(message); diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.h b/Source/WebKit2/UIProcess/qt/QtPageClient.h index 7715026f8..43050f502 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.h +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.h @@ -53,7 +53,9 @@ public: virtual void didRelaunchProcess(); virtual PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy(); virtual void handleDownloadRequest(DownloadProxy*); - virtual void handleApplicationSchemeRequest(PassRefPtr<QtNetworkRequestData>); + virtual void handleApplicationSchemeRequest(PassRefPtr<QtRefCountedNetworkRequestData>); + virtual void handleAuthenticationRequiredRequest(const String& hostname, const String& realm, const String& prefilledUsername, String& username, String& password); + virtual void handleCertificateVerificationRequest(const String& hostname, bool& ignoreErrors); virtual void displayView(); virtual void scrollView(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset); @@ -92,7 +94,6 @@ public: virtual void findStringInCustomRepresentation(const String&, WebKit::FindOptions, unsigned maxMatchCount) { } virtual void countStringMatchesInCustomRepresentation(const String&, WebKit::FindOptions, unsigned maxMatchCount) { } virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&); - virtual void focusEditableArea(const WebCore::IntRect&, const WebCore::IntRect&); virtual void updateTextInputState(); virtual void doneWithGestureEvent(const WebGestureEvent&, bool wasEventHandled); virtual void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled); diff --git a/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp index 2ed773c11..7032220d5 100644 --- a/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp @@ -35,7 +35,6 @@ QtTapGestureRecognizer::QtTapGestureRecognizer(QtWebPageEventHandler* eventHandl : QtGestureRecognizer(eventHandler) , m_tapState(NoTap) { - reset(); } bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTimestampMillis) @@ -68,6 +67,11 @@ bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTim } else m_tapState = SingleTapStarted; m_touchBeginEventForTap = adoptPtr(new QTouchEvent(*event)); + + if (m_tapState == SingleTapStarted) { + const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first(); + m_eventHandler->handlePotentialSingleTapEvent(touchPoint); + } break; case QEvent::TouchUpdate: // If the touch point moves further than the threshold, we cancel the tap gesture. @@ -82,6 +86,7 @@ bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTim break; case QEvent::TouchEnd: m_tapAndHoldTimer.stop(); + m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); switch (m_tapState) { case DoubleTapCandidate: @@ -111,6 +116,7 @@ bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTim default: break; } + return false; } @@ -140,6 +146,8 @@ void QtTapGestureRecognizer::tapAndHoldTimeout() void QtTapGestureRecognizer::reset() { + m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); + m_tapState = NoTap; m_touchBeginEventForTap.clear(); m_tapAndHoldTimer.stop(); diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp index d12eb0bbd..d2eb1566d 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp +++ b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp @@ -173,6 +173,9 @@ qreal QtViewportInteractionEngine::outerBoundedCSSScale(qreal cssScale) void QtViewportInteractionEngine::setItemRectVisible(const QRectF& itemRect) { + if (itemRect.isEmpty()) + return; + ViewportUpdateDeferrer guard(this); qreal itemScale = m_viewport->width() / itemRect.width(); @@ -302,6 +305,8 @@ void QtViewportInteractionEngine::wheelEvent(QWheelEvent* ev) QRectF endPosRange = computePosRangeForItemAtScale(m_content->contentScale()); m_content->setPos(-boundPosition(endPosRange.topLeft(), newPos, endPosRange.bottomRight())); + + emit visibleContentRectAndScaleChanged(); } void QtViewportInteractionEngine::pagePositionRequest(const QPoint& pagePosition) diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h index 1790c72ed..a4b699030 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h +++ b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h @@ -106,6 +106,7 @@ Q_SIGNALS: void contentResumeRequested(); void viewportTrajectoryVectorChanged(const QPointF&); + void visibleContentRectAndScaleChanged(); private Q_SLOTS: // Respond to changes of content that are not driven by us, like the page resizing itself. diff --git a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp index 29a547ba9..df27961b5 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp @@ -69,7 +69,7 @@ PassRefPtr<QtWebContext> QtWebContext::defaultContext() if (s_defaultContext) return PassRefPtr<QtWebContext>(s_defaultContext); - RefPtr<WebContext> context = WebContext::create(String()); + RefPtr<WebContext> context = WebContext::sharedProcessContext(); RefPtr<QtWebContext> defaultContext = QtWebContext::create(context.get()); s_defaultContext = defaultContext.get(); defaultContext->initialize(); diff --git a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp index 8b09b20f3..19ba336ae 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp @@ -53,11 +53,12 @@ QtWebIconDatabaseClient::QtWebIconDatabaseClient(QtWebContext *qtWebContext) iconDatabaseClient.version = kWKIconDatabaseClientCurrentVersion; iconDatabaseClient.clientInfo = this; iconDatabaseClient.didChangeIconForPageURL = didChangeIconForPageURL; - WKIconDatabaseSetIconDatabaseClient(toAPI(m_iconDatabase), &iconDatabaseClient); + WKIconDatabaseSetIconDatabaseClient(toAPI(m_iconDatabase.get()), &iconDatabaseClient); } QtWebIconDatabaseClient::~QtWebIconDatabaseClient() { + WKIconDatabaseSetIconDatabaseClient(toAPI(m_iconDatabase.get()), 0); } void QtWebIconDatabaseClient::didChangeIconForPageURL(WKIconDatabaseRef iconDatabase, WKURLRef pageURL, const void* clientInfo) diff --git a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h index e8d056248..b2c00a8ee 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h +++ b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h @@ -58,7 +58,7 @@ private: unsigned iconURLHashForPageURL(const String&); static void didChangeIconForPageURL(WKIconDatabaseRef, WKURLRef pageURL, const void* clientInfo); uint64_t m_contextId; - WebKit::WebIconDatabase* m_iconDatabase; + RefPtr<WebKit::WebIconDatabase> m_iconDatabase; Mutex m_imageLock; }; diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp index e5175201a..09f896021 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp @@ -26,6 +26,7 @@ #include "NativeWebWheelEvent.h" #include "QtViewportInteractionEngine.h" #include "qquickwebpage_p.h" +#include "qquickwebview_p.h" #include <QDrag> #include <QGraphicsSceneMouseEvent> #include <QGuiApplication> @@ -84,20 +85,23 @@ static inline WebCore::DragOperation dropActionToDragOperation(Qt::DropActions a return (DragOperation)result; } -QtWebPageEventHandler::QtWebPageEventHandler(WKPageRef pageRef, QQuickWebPage* qmlWebPage) +QtWebPageEventHandler::QtWebPageEventHandler(WKPageRef pageRef, QQuickWebPage* qmlWebPage, QQuickWebView* qmlWebView) : m_webPageProxy(toImpl(pageRef)) , m_panGestureRecognizer(this) , m_pinchGestureRecognizer(this) , m_tapGestureRecognizer(this) , m_webPage(qmlWebPage) + , m_webView(qmlWebView) , m_previousClickButton(Qt::NoButton) , m_clickCount(0) , m_postponeTextInputStateChanged(false) { + connect(qApp->inputPanel(), SIGNAL(visibleChanged()), this, SLOT(inputPanelVisibleChanged())); } QtWebPageEventHandler::~QtWebPageEventHandler() { + disconnect(qApp->inputPanel(), SIGNAL(visibleChanged()), this, SLOT(inputPanelVisibleChanged())); } bool QtWebPageEventHandler::handleEvent(QEvent* ev) @@ -282,6 +286,12 @@ bool QtWebPageEventHandler::handleDropEvent(QDropEvent* ev) return accepted; } +void QtWebPageEventHandler::handlePotentialSingleTapEvent(const QTouchEvent::TouchPoint& point) +{ + QTransform fromItemTransform = m_webPage->transformFromItem(); + m_webPageProxy->handlePotentialActivation(fromItemTransform.map(point.pos()).toPoint()); +} + void QtWebPageEventHandler::handleSingleTapEvent(const QTouchEvent::TouchPoint& point) { m_postponeTextInputStateChanged = true; @@ -429,6 +439,20 @@ static void setInputPanelVisible(bool visible) qApp->inputPanel()->setVisible(visible); } +void QtWebPageEventHandler::inputPanelVisibleChanged() +{ + if (!m_interactionEngine) + return; + + // We only respond to the input panel becoming visible. + if (!m_webView->hasFocus() || !qApp->inputPanel()->visible()) + return; + + const EditorState& editor = m_webPageProxy->editorState(); + if (editor.isContentEditable) + m_interactionEngine->focusEditableArea(QRectF(editor.cursorRect), QRectF(editor.editorRect)); +} + void QtWebPageEventHandler::updateTextInputState() { if (m_postponeTextInputStateChanged) @@ -436,6 +460,11 @@ void QtWebPageEventHandler::updateTextInputState() const EditorState& editor = m_webPageProxy->editorState(); + m_webView->setInputMethodHints(Qt::InputMethodHints(editor.inputMethodHints)); + + if (!m_webView->hasFocus()) + return; + // Ignore input method requests not due to a tap gesture. if (!editor.isContentEditable) setInputPanelVisible(false); @@ -448,7 +477,7 @@ void QtWebPageEventHandler::doneWithGestureEvent(const WebGestureEvent& event, b m_postponeTextInputStateChanged = false; - if (!wasEventHandled) + if (!wasEventHandled || !m_webView->hasFocus()) return; const EditorState& editor = m_webPageProxy->editorState(); @@ -517,14 +546,6 @@ void QtWebPageEventHandler::didFindZoomableArea(const IntPoint& target, const In m_interactionEngine->zoomToAreaGestureEnded(QPointF(target), QRectF(area)); } -void QtWebPageEventHandler::focusEditableArea(const IntRect& caret, const IntRect& area) -{ - if (!m_interactionEngine) - return; - - m_interactionEngine->focusEditableArea(QRectF(caret), QRectF(area)); -} - void QtWebPageEventHandler::startDrag(const WebCore::DragData& dragData, PassRefPtr<ShareableBitmap> dragImage) { QImage dragQImage; diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h index f5b7fb317..ebe95dd8d 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h @@ -40,18 +40,18 @@ class QtWebPageEventHandler : public QObject { Q_OBJECT public: - QtWebPageEventHandler(WKPageRef, QQuickWebPage*); + QtWebPageEventHandler(WKPageRef, QQuickWebPage*, QQuickWebView*); ~QtWebPageEventHandler(); bool handleEvent(QEvent*); void setViewportInteractionEngine(QtViewportInteractionEngine*); + void handlePotentialSingleTapEvent(const QTouchEvent::TouchPoint&); void handleSingleTapEvent(const QTouchEvent::TouchPoint&); void handleDoubleTapEvent(const QTouchEvent::TouchPoint&); void didFindZoomableArea(const WebCore::IntPoint& target, const WebCore::IntRect& area); - void focusEditableArea(const WebCore::IntRect& caret, const WebCore::IntRect& area); void updateTextInputState(); void doneWithGestureEvent(const WebGestureEvent& event, bool wasEventHandled); void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled); @@ -68,6 +68,10 @@ protected: QtPinchGestureRecognizer m_pinchGestureRecognizer; QtTapGestureRecognizer m_tapGestureRecognizer; QQuickWebPage* m_webPage; + QQuickWebView* m_webView; + +private slots: + void inputPanelVisibleChanged(); private: bool handleKeyPressEvent(QKeyEvent*); diff --git a/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp index ac9fde418..bf86edce6 100644 --- a/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp @@ -87,17 +87,17 @@ void WebPageProxy::registerApplicationScheme(const String& scheme) void WebPageProxy::resolveApplicationSchemeRequest(QtNetworkRequestData request) { - RefPtr<QtNetworkRequestData> requestData = adoptRef(new QtNetworkRequestData(request)); + RefPtr<QtRefCountedNetworkRequestData> requestData = adoptRef(new QtRefCountedNetworkRequestData(request)); m_applicationSchemeRequests.add(requestData); static_cast<QtPageClient*>(m_pageClient)->handleApplicationSchemeRequest(requestData); } void WebPageProxy::sendApplicationSchemeReply(const QQuickNetworkReply* reply) { - RefPtr<QtNetworkRequestData> requestData = reply->networkRequestData(); + RefPtr<QtRefCountedNetworkRequestData> requestData = reply->networkRequestData(); if (m_applicationSchemeRequests.contains(requestData)) { - RefPtr<QtNetworkReplyData> replyData = reply->networkReplyData(); - process()->send(Messages::WebPage::ApplicationSchemeReply(*replyData), pageID()); + RefPtr<QtRefCountedNetworkReplyData> replyData = reply->networkReplyData(); + process()->send(Messages::WebPage::ApplicationSchemeReply(replyData->data()), pageID()); m_applicationSchemeRequests.remove(requestData); } } diff --git a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp index d32e0f817..a040ad4aa 100644 --- a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp @@ -34,6 +34,7 @@ #include <WebCore/WebCoreInstanceHandle.h> #include <WebCore/ScrollbarTheme.h> #include <WebCore/BitmapInfo.h> +#include <WebCore/HWndDC.h> #include <WebCore/PlatformMouseEvent.h> #include <windowsx.h> @@ -808,7 +809,7 @@ void WebPopupMenuProxyWin::paint(const IntRect& damageRect, HDC hdc) return; if (!m_DC) { - m_DC = ::CreateCompatibleDC(::GetDC(m_popup)); + m_DC = ::CreateCompatibleDC(HWndDC(m_popup)); if (!m_DC) return; } @@ -848,12 +849,11 @@ void WebPopupMenuProxyWin::paint(const IntRect& damageRect, HDC hdc) if (m_scrollbar) m_scrollbar->paint(&context, damageRect); - HDC localDC = hdc ? hdc : ::GetDC(m_popup); - ::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY); + HWndDC hWndDC; + HDC localDC = hdc ? hdc : hWndDC.setHWnd(m_popup); - if (!hdc) - ::ReleaseDC(m_popup, localDC); + ::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY); } bool WebPopupMenuProxyWin::setFocusedIndex(int i, bool hotTracking) diff --git a/Source/WebKit2/UIProcess/win/WebView.cpp b/Source/WebKit2/UIProcess/win/WebView.cpp index d44e25560..c0e9f1729 100644 --- a/Source/WebKit2/UIProcess/win/WebView.cpp +++ b/Source/WebKit2/UIProcess/win/WebView.cpp @@ -32,11 +32,7 @@ #include "NativeWebKeyboardEvent.h" #include "NativeWebMouseEvent.h" #include "NativeWebWheelEvent.h" -#include "RunLoop.h" #include "WKAPICast.h" -#if USE(CG) -#include "WKCACFViewWindow.h" -#endif #include "WebContext.h" #include "WebContextMenuProxyWin.h" #include "WebEditCommandProxy.h" @@ -48,19 +44,24 @@ #include <WebCore/Cursor.h> #include <WebCore/DragSession.h> #include <WebCore/Editor.h> +#include <WebCore/FileSystem.h> #include <WebCore/FloatRect.h> -#if USE(CG) -#include <WebCore/GraphicsContextCG.h> -#endif +#include <WebCore/HWndDC.h> #include <WebCore/IntRect.h> #include <WebCore/NotImplemented.h> #include <WebCore/Region.h> +#include <WebCore/RunLoop.h> #include <WebCore/SoftLinking.h> #include <WebCore/WebCoreInstanceHandle.h> #include <WebCore/WindowMessageBroadcaster.h> #include <WebCore/WindowsTouch.h> #include <wtf/text/WTFString.h> +#if USE(CG) +#include "WKCACFViewWindow.h" +#include <WebCore/GraphicsContextCG.h> +#endif + #if ENABLE(FULLSCREEN_API) #include "WebFullScreenManagerProxy.h" #include <WebCore/FullScreenController.h> @@ -959,9 +960,8 @@ void WebView::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset) void WebView::flashBackingStoreUpdates(const Vector<IntRect>& updateRects) { static HBRUSH brush = createBrush(WebPageProxy::backingStoreUpdatesFlashColor().rgb()).leakPtr(); - HDC dc = ::GetDC(m_window); + HWndDC dc(m_window); flashRects(dc, updateRects.data(), updateRects.size(), brush); - ::ReleaseDC(m_window, dc); } WebCore::IntSize WebView::viewSize() @@ -1708,6 +1708,18 @@ HRESULT STDMETHODCALLTYPE WebView::DragLeave() return S_OK; } +static bool maybeCreateSandboxExtensionFromDragData(const DragData& dragData, SandboxExtension::Handle& sandboxExtensionHandle) +{ + if (!dragData.containsFiles()) + return false; + + // Unlike on Mac, we allow multiple files and directories, since on Windows + // we have actions for those (open the first file, open a Windows Explorer window). + + SandboxExtension::createHandle("\\", SandboxExtension::ReadOnly, sandboxExtensionHandle); + return true; +} + HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { if (m_dropTargetHelper) @@ -1720,6 +1732,9 @@ HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeySt DragData data(pDataObject, IntPoint(localpt.x, localpt.y), IntPoint(pt.x, pt.y), keyStateToDragOperation(grfKeyState)); SandboxExtension::Handle sandboxExtensionHandle; + bool createdExtension = maybeCreateSandboxExtensionFromDragData(data, sandboxExtensionHandle); + if (createdExtension) + m_page->process()->willAcquireUniversalFileReadSandboxExtension(); m_page->performDrag(&data, String(), sandboxExtensionHandle); return S_OK; } |