diff options
Diffstat (limited to 'Source/WebKit2/UIProcess')
241 files changed, 10075 insertions, 2199 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKAPICast.h b/Source/WebKit2/UIProcess/API/C/WKAPICast.h index bd3fa2d74..e47b05ff5 100644 --- a/Source/WebKit2/UIProcess/API/C/WKAPICast.h +++ b/Source/WebKit2/UIProcess/API/C/WKAPICast.h @@ -359,4 +359,9 @@ inline ProxyingRefPtr<WebGrammarDetail> toAPI(const WebCore::GrammarDetail& gram #if defined(BUILDING_GTK__) #include "WKAPICastGtk.h" #endif + +#if USE(SOUP) +#include "WKAPICastSoup.h" +#endif + #endif // WKAPICast_h diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.cpp b/Source/WebKit2/UIProcess/API/C/WKContext.cpp index cef897714..8890e801e 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKContext.cpp @@ -235,21 +235,6 @@ void WKContextSetLocalStorageDirectory(WKContextRef contextRef, WKStringRef loca toImpl(contextRef)->setLocalStorageDirectory(toImpl(localStorageDirectory)->string()); } -void WKContextSetOverrideWebInspectorBaseDirectory(WKContextRef contextRef, WKStringRef webInspectorBaseDirectory) -{ - toImpl(contextRef)->setOverrideWebInspectorBaseDirectory(toImpl(webInspectorBaseDirectory)->string()); -} - -void WKContextSetOverrideWebInspectorPagePath(WKContextRef contextRef, WKStringRef webInspectorPagePath) -{ - toImpl(contextRef)->setOverrideWebInspectorPagePath(toImpl(webInspectorPagePath)->string()); -} - -void WKContextSetOverrideWebInspectorLocalizedStringsPath(WKContextRef contextRef, WKStringRef webInspectorLocalizedStringsPath) -{ - toImpl(contextRef)->setOverrideWebInspectorLocalizedStringsPath(toImpl(webInspectorLocalizedStringsPath)->string()); -} - void WKContextDisableProcessTermination(WKContextRef contextRef) { toImpl(contextRef)->disableProcessTermination(); diff --git a/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h b/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h index ad69da1de..01dac4b01 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKContextPrivate.h @@ -62,9 +62,6 @@ WK_EXPORT void WKContextSetIconDatabasePath(WKContextRef context, WKStringRef ic // we should really change these settings to be on WebPreferences and changeable at runtime. WK_EXPORT void WKContextSetDatabaseDirectory(WKContextRef context, WKStringRef databaseDirectory); WK_EXPORT void WKContextSetLocalStorageDirectory(WKContextRef context, WKStringRef localStorageDirectory); -WK_EXPORT void WKContextSetOverrideWebInspectorBaseDirectory(WKContextRef context, WKStringRef webInspectorBaseDirectory); -WK_EXPORT void WKContextSetOverrideWebInspectorPagePath(WKContextRef context, WKStringRef webInspectorPagePath); -WK_EXPORT void WKContextSetOverrideWebInspectorLocalizedStringsPath(WKContextRef context, WKStringRef webInspectorLocalizedStringsPath); // FIXME: This is a workaround for testing purposes only and should be removed once a better // solution has been found for testing. diff --git a/Source/WebKit2/UIProcess/API/C/WKNativeEvent.h b/Source/WebKit2/UIProcess/API/C/WKNativeEvent.h index ee0bd1777..f0d39fb5a 100644 --- a/Source/WebKit2/UIProcess/API/C/WKNativeEvent.h +++ b/Source/WebKit2/UIProcess/API/C/WKNativeEvent.h @@ -41,6 +41,9 @@ struct NSEvent; typedef NSEvent *WKNativeEventPtr; #elif defined(WIN32) || defined(_WIN32) typedef const struct tagMSG* WKNativeEventPtr; +#elif defined(BUILDING_GTK__) +typedef union _GdkEvent GdkEvent; +typedef const GdkEvent* WKNativeEventPtr; #else typedef const void* WKNativeEventPtr; #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKNotification.cpp b/Source/WebKit2/UIProcess/API/C/WKNotification.cpp index 5dfcbba29..26700e1aa 100644 --- a/Source/WebKit2/UIProcess/API/C/WKNotification.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKNotification.cpp @@ -52,9 +52,9 @@ WKStringRef WKNotificationCopyIconURL(WKNotificationRef notification) return toCopiedAPI(toImpl(notification)->iconURL()); } -WKStringRef WKNotificationCopyReplaceID(WKNotificationRef notification) +WKStringRef WKNotificationCopyTag(WKNotificationRef notification) { - return toCopiedAPI(toImpl(notification)->replaceID()); + return toCopiedAPI(toImpl(notification)->tag()); } WKSecurityOriginRef WKNotificationGetSecurityOrigin(WKNotificationRef notification) diff --git a/Source/WebKit2/UIProcess/API/C/WKNotification.h b/Source/WebKit2/UIProcess/API/C/WKNotification.h index 11ea97275..3f4b1a900 100644 --- a/Source/WebKit2/UIProcess/API/C/WKNotification.h +++ b/Source/WebKit2/UIProcess/API/C/WKNotification.h @@ -37,7 +37,7 @@ WK_EXPORT WKTypeID WKNotificationGetTypeID(); WK_EXPORT WKStringRef WKNotificationCopyTitle(WKNotificationRef notification); WK_EXPORT WKStringRef WKNotificationCopyBody(WKNotificationRef notification); WK_EXPORT WKStringRef WKNotificationCopyIconURL(WKNotificationRef notification); -WK_EXPORT WKStringRef WKNotificationCopyReplaceID(WKNotificationRef notification); +WK_EXPORT WKStringRef WKNotificationCopyTag(WKNotificationRef notification); WK_EXPORT WKSecurityOriginRef WKNotificationGetSecurityOrigin(WKNotificationRef notification); WK_EXPORT uint64_t WKNotificationGetID(WKNotificationRef notification); diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.cpp b/Source/WebKit2/UIProcess/API/C/WKPage.cpp index 130dd0e45..e5682ca4c 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPage.cpp @@ -82,6 +82,11 @@ void WKPageLoadPlainTextString(WKPageRef pageRef, WKStringRef plainTextStringRef toImpl(pageRef)->loadPlainTextString(toWTFString(plainTextStringRef)); } +void WKPageLoadWebArchiveData(WKPageRef pageRef, WKDataRef webArchiveDataRef) +{ + toImpl(pageRef)->loadWebArchiveData(toImpl(webArchiveDataRef)); +} + void WKPageStopLoading(WKPageRef pageRef) { toImpl(pageRef)->stopLoading(); @@ -456,7 +461,9 @@ void WKPageCountStringMatches(WKPageRef pageRef, WKStringRef string, WKFindOptio void WKPageSetPageContextMenuClient(WKPageRef pageRef, const WKPageContextMenuClient* wkClient) { +#if ENABLE(CONTEXT_MENUS) toImpl(pageRef)->initializeContextMenuClient(wkClient); +#endif } void WKPageSetPageFindClient(WKPageRef pageRef, const WKPageFindClient* wkClient) diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.h b/Source/WebKit2/UIProcess/API/C/WKPage.h index 05b7aff0c..a6d8a661a 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.h +++ b/Source/WebKit2/UIProcess/API/C/WKPage.h @@ -71,7 +71,7 @@ typedef void (*WKPageDidChangeBackForwardListCallback)(WKPageRef page, WKBackFor 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); -typedef void (*WKPageWillGoToBackForwardListItemCallback)(WKPageRef page, WKBackForwardListItemRef item, const void *clientInfo); +typedef void (*WKPageWillGoToBackForwardListItemCallback)(WKPageRef page, WKBackForwardListItemRef item, WKTypeRef userData, const void *clientInfo); struct WKPageLoaderClient { int version; @@ -113,6 +113,8 @@ struct WKPageLoaderClient { WKPageDidNewFirstVisuallyNonEmptyLayoutCallback didNewFirstVisuallyNonEmptyLayout; WKPageWillGoToBackForwardListItemCallback willGoToBackForwardListItem; + + WKPageCallback interactionOccurredWhileProcessUnresponsive; }; typedef struct WKPageLoaderClient WKPageLoaderClient; @@ -319,6 +321,7 @@ WK_EXPORT void WKPageLoadURLRequest(WKPageRef page, WKURLRequestRef urlRequest); WK_EXPORT void WKPageLoadHTMLString(WKPageRef page, WKStringRef htmlString, WKURLRef baseURL); WK_EXPORT void WKPageLoadAlternateHTMLString(WKPageRef page, WKStringRef htmlString, WKURLRef baseURL, WKURLRef unreachableURL); WK_EXPORT void WKPageLoadPlainTextString(WKPageRef page, WKStringRef plainTextString); +WK_EXPORT void WKPageLoadWebArchiveData(WKPageRef page, WKDataRef webArchiveData); WK_EXPORT void WKPageStopLoading(WKPageRef page); WK_EXPORT void WKPageReload(WKPageRef page); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp index 39903bcb5..a92104dac 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp @@ -158,6 +158,16 @@ bool WKPreferencesGetJavaEnabled(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->javaEnabled(); } +void WKPreferencesSetJavaEnabledForLocalFiles(WKPreferencesRef preferencesRef, bool javaEnabledForLocalFiles) +{ + toImpl(preferencesRef)->setJavaEnabledForLocalFiles(javaEnabledForLocalFiles); +} + +bool WKPreferencesGetJavaEnabledForLocalFiles(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->javaEnabledForLocalFiles(); +} + void WKPreferencesSetJavaScriptCanOpenWindowsAutomatically(WKPreferencesRef preferencesRef, bool javaScriptCanOpenWindowsAutomatically) { toImpl(preferencesRef)->setJavaScriptCanOpenWindowsAutomatically(javaScriptCanOpenWindowsAutomatically); @@ -418,6 +428,16 @@ bool WKPreferencesGetCSSRegionsEnabled(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->cssRegionsEnabled(); } +void WKPreferencesSetRegionBasedColumnsEnabled(WKPreferencesRef preferencesRef, bool flag) +{ + toImpl(preferencesRef)->setRegionBasedColumnsEnabled(flag); +} + +bool WKPreferencesGetRegionBasedColumnsEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->regionBasedColumnsEnabled(); +} + void WKPreferencesSetNeedsSiteSpecificQuirks(WKPreferencesRef preferencesRef, bool flag) { toImpl(preferencesRef)->setNeedsSiteSpecificQuirks(flag); @@ -678,24 +698,24 @@ bool WKPreferencesGetApplicationChromeModeEnabled(WKPreferencesRef preferencesRe return toImpl(preferencesRef)->applicationChromeMode(); } -void WKPreferencesSetSuppressesIncrementalRendering(WKPreferencesRef preferencesRef, bool enabled) +void WKPreferencesSetInspectorUsesWebKitUserInterface(WKPreferencesRef preferencesRef, bool enabled) { - toImpl(preferencesRef)->setSuppressesIncrementalRendering(enabled); + toImpl(preferencesRef)->setInspectorUsesWebKitUserInterface(enabled); } -bool WKPreferencesGetSuppressesIncrementalRendering(WKPreferencesRef preferencesRef) +bool WKPreferencesGetInspectorUsesWebKitUserInterface(WKPreferencesRef preferencesRef) { - return toImpl(preferencesRef)->suppressesIncrementalRendering(); + return toImpl(preferencesRef)->inspectorUsesWebKitUserInterface(); } -void WKPreferencesSetSuppressIncrementalRendering(WKPreferencesRef preferencesRef, bool enabled) +void WKPreferencesSetSuppressesIncrementalRendering(WKPreferencesRef preferencesRef, bool enabled) { - WKPreferencesSetSuppressesIncrementalRendering(preferencesRef, enabled); + toImpl(preferencesRef)->setSuppressesIncrementalRendering(enabled); } -bool WKPreferencesGetSuppressIncrementalRendering(WKPreferencesRef preferencesRef) +bool WKPreferencesGetSuppressesIncrementalRendering(WKPreferencesRef preferencesRef) { - return WKPreferencesGetSuppressesIncrementalRendering(preferencesRef); + return toImpl(preferencesRef)->suppressesIncrementalRendering(); } void WKPreferencesSetBackspaceKeyNavigationEnabled(WKPreferencesRef preferencesRef, bool enabled) @@ -758,6 +778,26 @@ bool WKPreferencesGetNotificationsEnabled(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->notificationsEnabled(); } +void WKPreferencesSetShouldRespectImageOrientation(WKPreferencesRef preferencesRef, bool enabled) +{ + toImpl(preferencesRef)->setShouldRespectImageOrientation(enabled); +} + +bool WKPreferencesGetShouldRespectImageOrientation(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->shouldRespectImageOrientation(); +} + +void WKPreferencesSetRequestAnimationFrameEnabled(WKPreferencesRef preferencesRef, bool flag) +{ + toImpl(preferencesRef)->setRequestAnimationFrameEnabled(flag); +} + +bool WKPreferencesGetRequestAnimationFrameEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->requestAnimationFrameEnabled(); +} + void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef) { // Currently we reset the overrides on the web process when preferencesDidChange() is called. Since WTR preferences diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.h b/Source/WebKit2/UIProcess/API/C/WKPreferences.h index 501c5a5d6..5e885738e 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.h @@ -172,11 +172,6 @@ WK_EXPORT bool WKPreferencesGetWebAudioEnabled(WKPreferencesRef preferencesRef); // Defaults to false WK_EXPORT void WKPreferencesSetSuppressesIncrementalRendering(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetSuppressesIncrementalRendering(WKPreferencesRef preferencesRef); - -// Defaults to false -// These functions are deprecated. See <rdar://problem/10929617> Remove WKPreferences[Get|Set]SuppressIncrementalRendering from WKPreferences.h. -WK_EXPORT void WKPreferencesSetSuppressIncrementalRendering(WKPreferencesRef preferencesRef, bool enabled); -WK_EXPORT bool WKPreferencesGetSuppressIncrementalRendering(WKPreferencesRef preferencesRef); // Defaults to true WK_EXPORT void WKPreferencesSetBackspaceKeyNavigationEnabled(WKPreferencesRef preferencesRef, bool enabled); @@ -202,6 +197,10 @@ WK_EXPORT bool WKPreferencesGetShouldDisplayTextDescriptions(WKPreferencesRef pr WK_EXPORT void WKPreferencesSetNotificationsEnabled(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetNotificationsEnabled(WKPreferencesRef preferencesRef); +// Defaults to false +WK_EXPORT void WKPreferencesSetShouldRespectImageOrientation(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetShouldRespectImageOrientation(WKPreferencesRef preferencesRef); + #ifdef __cplusplus } #endif diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h index 36950e891..cbe6b4fd6 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h @@ -95,6 +95,10 @@ WK_EXPORT bool WKPreferencesGetWebGLEnabled(WKPreferencesRef); WK_EXPORT void WKPreferencesSetCSSRegionsEnabled(WKPreferencesRef, bool flag); WK_EXPORT bool WKPreferencesGetCSSRegionsEnabled(WKPreferencesRef); +// Defaults to false +WK_EXPORT void WKPreferencesSetRegionBasedColumnsEnabled(WKPreferencesRef, bool flag); +WK_EXPORT bool WKPreferencesGetRegionBasedColumnsEnabled(WKPreferencesRef); + // Defaults to false. WK_EXPORT void WKPreferencesSetNeedsSiteSpecificQuirks(WKPreferencesRef, bool); WK_EXPORT bool WKPreferencesGetNeedsSiteSpecificQuirks(WKPreferencesRef); @@ -167,6 +171,18 @@ WK_EXPORT bool WKPreferencesGetMockScrollbarsEnabled(WKPreferencesRef preference WK_EXPORT void WKPreferencesSetApplicationChromeModeEnabled(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetApplicationChromeModeEnabled(WKPreferencesRef preferencesRef); +// Defaults to false. +WK_EXPORT void WKPreferencesSetInspectorUsesWebKitUserInterface(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetInspectorUsesWebKitUserInterface(WKPreferencesRef preferencesRef); + +// Defaults to true. +WK_EXPORT void WKPreferencesSetJavaEnabledForLocalFiles(WKPreferencesRef preferences, bool javaEnabled); +WK_EXPORT bool WKPreferencesGetJavaEnabledForLocalFiles(WKPreferencesRef preferences); + +// Defaults to true. +WK_EXPORT void WKPreferencesSetRequestAnimationFrameEnabled(WKPreferencesRef, bool); +WK_EXPORT bool WKPreferencesGetRequestAnimationFrameEnabled(WKPreferencesRef); + WK_EXPORT void WKPreferencesResetTestRunnerOverrides(WKPreferencesRef preferencesRef); #ifdef __cplusplus diff --git a/Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.cpp b/Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.cpp new file mode 100644 index 000000000..2b29a2b76 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 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. + */ + +#include "config.h" +#include "WKFullScreenClientGtk.h" + +#include "WKAPICast.h" +#include "WebKitWebViewBasePrivate.h" + +using namespace WebKit; + +void WKViewSetFullScreenClientGtk(WKViewRef viewRef, const WKFullScreenClientGtk* wkClient) +{ + webkitWebViewBaseInitializeFullScreenClient(toImpl(viewRef), wkClient); +} diff --git a/Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.h b/Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.h new file mode 100644 index 000000000..a8c92166b --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 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 WKFullScreenClientGtk_h +#define WKFullScreenClientGtk_h + +#include <WebKit2/WKBase.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef bool (*WKFullScreenClientGtkWillEnterFullScreenCallback)(const void* clientInfo); +typedef bool (*WKFullScreenClientGtkWillExitFullScreenCallback)(const void* clientInfo); + +struct WKFullScreenClientGtk { + int version; + const void* clientInfo; + WKFullScreenClientGtkWillEnterFullScreenCallback willEnterFullScreen; + WKFullScreenClientGtkWillExitFullScreenCallback willExitFullScreen; +}; +typedef struct WKFullScreenClientGtk WKFullScreenClientGtk; + +enum { kWKFullScreenClientGtkCurrentVersion = 0 }; + +WK_EXPORT void WKViewSetFullScreenClientGtk(WKViewRef viewRef, const WKFullScreenClientGtk* client); + +#ifdef __cplusplus +} +#endif + +#endif /* WKFullScreenClientGtk_h */ diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKAPICastSoup.h b/Source/WebKit2/UIProcess/API/C/soup/WKAPICastSoup.h new file mode 100644 index 000000000..c8a954460 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/soup/WKAPICastSoup.h @@ -0,0 +1,41 @@ +/* + * Portions Copyright (c) 2012 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 WKAPICastSoup_h +#define WKAPICastSoup_h + +#ifndef WKAPICast_h +#error "Please #include \"WKAPICast.h\" instead of this file directly." +#endif + +namespace WebKit { + +class WebSoupRequestManagerProxy; + +WK_ADD_API_MAPPING(WKSoupRequestManagerRef, WebSoupRequestManagerProxy) + +} + +#endif // WKAPICastSoup_h diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKContextSoup.cpp b/Source/WebKit2/UIProcess/API/C/soup/WKContextSoup.cpp new file mode 100644 index 000000000..e4e88d384 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/soup/WKContextSoup.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012 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 MERCHANTAwBILITY 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. + */ + +#include "config.h" +#include "WKContextSoup.h" + +#include "WKAPICast.h" +#include "WebContext.h" + +using namespace WebKit; + +WKSoupRequestManagerRef WKContextGetSoupRequestManager(WKContextRef contextRef) +{ + return toAPI(toImpl(contextRef)->soupRequestManagerProxy()); +} + diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKContextSoup.h b/Source/WebKit2/UIProcess/API/C/soup/WKContextSoup.h new file mode 100644 index 000000000..36954ffe3 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/soup/WKContextSoup.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 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 WKContextSoup_h +#define WKContextSoup_h + +#include <WebKit2/WKBase.h> +#include <WebKit2/WKSoupRequestManager.h> + +#ifdef __cplusplus +extern "C" { +#endif + +WK_EXPORT WKSoupRequestManagerRef WKContextGetSoupRequestManager(WKContextRef context); + +#ifdef __cplusplus +} +#endif + +#endif /* WKContextSoup_h */ diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp new file mode 100644 index 000000000..187d7fd9c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 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. + */ + +#include "config.h" +#include "WKSoupRequestManager.h" + +#include "WKAPICast.h" +#include "WebSoupRequestManagerProxy.h" + +using namespace WebKit; + +WKTypeID WKSoupRequestManagerGetTypeID() +{ + return toAPI(WebSoupRequestManagerProxy::APIType); +} + +void WKSoupRequestManagerSetClient(WKSoupRequestManagerRef soupRequestManagerRef, const WKSoupRequestManagerClient* wkClient) +{ + toImpl(soupRequestManagerRef)->initializeClient(wkClient); +} + +void WKSoupRequestManagerRegisterURIScheme(WKSoupRequestManagerRef soupRequestManagerRef, WKStringRef schemeRef) +{ + toImpl(soupRequestManagerRef)->registerURIScheme(toImpl(schemeRef)->string()); +} + +void WKSoupRequestManagerHandleURIRequest(WKSoupRequestManagerRef soupRequestManagerRef, WKDataRef data, WKStringRef mimeTypeRef, uint64_t requestID) +{ + toImpl(soupRequestManagerRef)->handleURIRequest(toImpl(data), toImpl(mimeTypeRef)->string(), requestID); +} diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h new file mode 100644 index 000000000..74b4fa005 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 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 WKSoupRequestManager_h +#define WKSoupRequestManager_h + +#include "WKAPICast.h" +#include <WebKit2/WKBase.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*WKSoupRequestManagerDidReceiveURIRequestCallback)(WKSoupRequestManagerRef soupRequestManagerRef, WKURLRef urlRef, uint64_t requestID, const void* clientInfo); + +struct WKSoupRequestManagerClient { + int version; + const void* clientInfo; + WKSoupRequestManagerDidReceiveURIRequestCallback didReceiveURIRequest; +}; +typedef struct WKSoupRequestManagerClient WKSoupRequestManagerClient; + +enum { kWKSoupRequestManagerClientCurrentVersion = 0 }; + +WK_EXPORT WKTypeID WKSoupRequestManagerGetTypeID(); + +WK_EXPORT void WKSoupRequestManagerSetClient(WKSoupRequestManagerRef, const WKSoupRequestManagerClient* client); +WK_EXPORT void WKSoupRequestManagerRegisterURIScheme(WKSoupRequestManagerRef, WKStringRef schemeRef); +WK_EXPORT void WKSoupRequestManagerHandleURIRequest(WKSoupRequestManagerRef, WKDataRef, WKStringRef mimeTypeRef, uint64_t requestID); + +#ifdef __cplusplus +} +#endif + +#endif /* WKSoupRequestManager_h */ diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp index c21162903..c7e5f029c 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp @@ -131,7 +131,7 @@ void PageClientImpl::setCursorHiddenUntilMouseMoves(bool) notImplemented(); } -void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportArguments&) +void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&) { notImplemented(); } diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h index 40af3b23f..0858fc33d 100644 --- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h @@ -65,7 +65,7 @@ private: virtual void setCursor(const WebCore::Cursor&); virtual void setCursorHiddenUntilMouseMoves(bool); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp index 9fadbeab5..8fbfe73f6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp @@ -39,7 +39,9 @@ #include "WebPageProxy.h" #include "WebPopupMenuProxyGtk.h" #include <WebCore/Cursor.h> +#include <WebCore/EventNames.h> #include <WebCore/GtkUtilities.h> +#include <wtf/text/CString.h> #include <wtf/text/WTFString.h> using namespace WebCore; @@ -156,7 +158,7 @@ void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves) notImplemented(); } -void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportArguments&) +void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&) { notImplemented(); } diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h index 6a1cb2459..54ad99f8f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h @@ -69,7 +69,7 @@ private: virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void setCursor(const WebCore::Cursor&); virtual void setCursorHiddenUntilMouseMoves(bool); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp new file mode 100644 index 000000000..b993d2e83 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitCookieManager.h" + +#include "WebKitCookieManagerPrivate.h" +#include "WebKitEnumTypes.h" +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + CHANGED, + + LAST_SIGNAL +}; + +struct _WebKitCookieManagerPrivate { + WKRetainPtr<WKCookieManagerRef> wkCookieManager; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitCookieManager, webkit_cookie_manager, G_TYPE_OBJECT) + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS, kWKHTTPCookieAcceptPolicyAlways); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_COOKIE_POLICY_ACCEPT_NEVER, kWKHTTPCookieAcceptPolicyNever); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY, kWKHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain); + +static void webkit_cookie_manager_init(WebKitCookieManager* manager) +{ + WebKitCookieManagerPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(manager, WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManagerPrivate); + manager->priv = priv; + new (priv) WebKitCookieManagerPrivate(); +} + +static void webkitCookieManagerFinalize(GObject* object) +{ + WebKitCookieManagerPrivate* priv = WEBKIT_COOKIE_MANAGER(object)->priv; + WKCookieManagerStopObservingCookieChanges(priv->wkCookieManager.get()); + priv->~WebKitCookieManagerPrivate(); + G_OBJECT_CLASS(webkit_cookie_manager_parent_class)->finalize(object); +} + +static void webkit_cookie_manager_class_init(WebKitCookieManagerClass* findClass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass); + gObjectClass->finalize = webkitCookieManagerFinalize; + + g_type_class_add_private(findClass, sizeof(WebKitCookieManagerPrivate)); + + /** + * WebKitCookieManager::changed: + * @cookie_manager: the #WebKitCookieManager + * + * This signal is emitted when cookies are added, removed or modified. + */ + signals[CHANGED] = + g_signal_new("changed", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void cookiesDidChange(WKCookieManagerRef, const void* clientInfo) +{ + g_signal_emit(WEBKIT_COOKIE_MANAGER(clientInfo), signals[CHANGED], 0); +} + +WebKitCookieManager* webkitCookieManagerCreate(WKCookieManagerRef wkCookieManager) +{ + WebKitCookieManager* manager = WEBKIT_COOKIE_MANAGER(g_object_new(WEBKIT_TYPE_COOKIE_MANAGER, NULL)); + manager->priv->wkCookieManager = wkCookieManager; + + WKCookieManagerClient wkCookieManagerClient = { + kWKCookieManagerClientCurrentVersion, + manager, // clientInfo + cookiesDidChange + }; + WKCookieManagerSetClient(wkCookieManager, &wkCookieManagerClient); + WKCookieManagerStartObservingCookieChanges(wkCookieManager); + + return manager; +} + +/** + * webkit_cookie_manager_set_accept_policy: + * @cookie_manager: a #WebKitCookieManager + * @policy: a #WebKitCookieAcceptPolicy + * + * Set the cookie acceptance policy of @cookie_manager as @policy. + */ +void webkit_cookie_manager_set_accept_policy(WebKitCookieManager* manager, WebKitCookieAcceptPolicy policy) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + WKCookieManagerSetHTTPCookieAcceptPolicy(manager->priv->wkCookieManager.get(), policy); +} + +static void webkitCookieManagerGetAcceptPolicyCallback(WKHTTPCookieAcceptPolicy policy, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + g_simple_async_result_set_op_res_gpointer(result.get(), GUINT_TO_POINTER(policy), 0); + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_cookie_manager_get_accept_policy: + * @cookie_manager: a #WebKitCookieManager + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously get the cookie acceptance policy of @cookie_manager. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_cookie_manager_get_accept_policy_finish() to get the result of the operation. + */ +void webkit_cookie_manager_get_accept_policy(WebKitCookieManager* manager, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(manager), callback, userData, + reinterpret_cast<gpointer>(webkit_cookie_manager_get_accept_policy)); + WKCookieManagerGetHTTPCookieAcceptPolicy(manager->priv->wkCookieManager.get(), result, webkitCookieManagerGetAcceptPolicyCallback); +} + +/** + * webkit_cookie_manager_get_accept_policy_finish: + * @cookie_manager: a #WebKitCookieManager + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_cookie_manager_get_accept_policy(). + * + * Returns: the cookie acceptance policy of @cookie_manager as a #WebKitCookieAcceptPolicy. + */ +WebKitCookieAcceptPolicy webkit_cookie_manager_get_accept_policy_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_cookie_manager_get_accept_policy); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY; + + return static_cast<WebKitCookieAcceptPolicy>(GPOINTER_TO_UINT(g_simple_async_result_get_op_res_gpointer(simpleResult))); +} + +static void webkitCookieManagerGetDomainsWithCookiesCallback(WKArrayRef wkDomains, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + GPtrArray* domains = g_ptr_array_new_with_free_func(g_free); + for (size_t i = 0; i < WKArrayGetSize(wkDomains); ++i) { + WKStringRef wkDomain = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkDomains, i)); + String domain = toImpl(wkDomain)->string(); + if (domain.isEmpty()) + continue; + g_ptr_array_add(domains, g_strdup(domain.utf8().data())); + } + g_ptr_array_add(domains, 0); + g_simple_async_result_set_op_res_gpointer(result.get(), domains, reinterpret_cast<GDestroyNotify>(g_ptr_array_unref)); + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_cookie_manager_get_domains_with_cookies: + * @cookie_manager: a #WebKitCookieManager + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously get the list of domains for which @cookie_manager contains cookies. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_cookie_manager_get_domains_with_cookies_finish() to get the result of the operation. + */ +void webkit_cookie_manager_get_domains_with_cookies(WebKitCookieManager* manager, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(manager), callback, userData, + reinterpret_cast<gpointer>(webkit_cookie_manager_get_domains_with_cookies)); + WKCookieManagerGetHostnamesWithCookies(manager->priv->wkCookieManager.get(), result, webkitCookieManagerGetDomainsWithCookiesCallback); +} + +/** + * webkit_cookie_manager_get_domains_with_cookies_finish: + * @cookie_manager: a #WebKitCookieManager + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_cookie_manager_get_domains_with_cookies(). + * The return value is a %NULL terminated list of strings which should + * be released with g_strfreev(). + * + * Returns: (transfer full) (array zero-terminated=1): A %NULL terminated array of domain names + * or %NULL in case of error. + */ +gchar** webkit_cookie_manager_get_domains_with_cookies_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_cookie_manager_get_domains_with_cookies); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + GPtrArray* domains = static_cast<GPtrArray*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return reinterpret_cast<char**>(g_ptr_array_free(domains, FALSE)); +} + +/** + * webkit_cookie_manager_delete_cookies_for_domain: + * @cookie_manager: a #WebKitCookieManager + * @domain: a domain name + * + * Remove all cookies of @cookie_manager for the given @domain. + */ +void webkit_cookie_manager_delete_cookies_for_domain(WebKitCookieManager* manager, const gchar* domain) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + g_return_if_fail(domain); + + WKRetainPtr<WKStringRef> wkDomain(AdoptWK, WKStringCreateWithUTF8CString(domain)); + WKCookieManagerDeleteCookiesForHostname(manager->priv->wkCookieManager.get(), wkDomain.get()); +} + +/** + * webkit_cookie_manager_delete_all_cookies: + * @cookie_manager: a #WebKitCookieManager + * + * Delete all cookies of @cookie_manager + */ +void webkit_cookie_manager_delete_all_cookies(WebKitCookieManager* manager) +{ + g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager)); + + WKCookieManagerDeleteAllCookies(manager->priv->wkCookieManager.get()); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h new file mode 100644 index 000000000..791a61d82 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitCookieManager_h +#define WebKitCookieManager_h + +#include <gio/gio.h> +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_COOKIE_MANAGER (webkit_cookie_manager_get_type()) +#define WEBKIT_COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManager)) +#define WEBKIT_IS_COOKIE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_COOKIE_MANAGER)) +#define WEBKIT_COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManagerClass)) +#define WEBKIT_IS_COOKIE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_COOKIE_MANAGER)) +#define WEBKIT_COOKIE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_COOKIE_MANAGER, WebKitCookieManagerClass)) + +typedef struct _WebKitCookieManager WebKitCookieManager; +typedef struct _WebKitCookieManagerClass WebKitCookieManagerClass; +typedef struct _WebKitCookieManagerPrivate WebKitCookieManagerPrivate; + +/** + * WebKitCookieAcceptPolicy: + * @WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS: Accept all cookies unconditionally. + * @WEBKIT_COOKIE_POLICY_ACCEPT_NEVER: Reject all cookies unconditionally. + * @WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY: Accept only cookies set by the main document loaded. + * + * Enum values used to denote the cookie acceptance policies. + */ +typedef enum { + WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS, + WEBKIT_COOKIE_POLICY_ACCEPT_NEVER, + WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY +} WebKitCookieAcceptPolicy; + +struct _WebKitCookieManager { + GObject parent; + + WebKitCookieManagerPrivate *priv; +}; + +struct _WebKitCookieManagerClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_cookie_manager_get_type (void); + +WEBKIT_API void +webkit_cookie_manager_set_accept_policy (WebKitCookieManager *cookie_manager, + WebKitCookieAcceptPolicy policy); + +WEBKIT_API void +webkit_cookie_manager_get_accept_policy (WebKitCookieManager *cookie_manager, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API WebKitCookieAcceptPolicy +webkit_cookie_manager_get_accept_policy_finish (WebKitCookieManager *cookie_manager, + GAsyncResult *result, + GError **error); + +WEBKIT_API void +webkit_cookie_manager_get_domains_with_cookies (WebKitCookieManager *cookie_manager, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API gchar ** +webkit_cookie_manager_get_domains_with_cookies_finish (WebKitCookieManager *cookie_manager, + GAsyncResult *result, + GError **error); + +WEBKIT_API void +webkit_cookie_manager_delete_cookies_for_domain (WebKitCookieManager *cookie_manager, + const gchar *domain); + +WEBKIT_API void +webkit_cookie_manager_delete_all_cookies (WebKitCookieManager *cookie_manager); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManagerPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManagerPrivate.h new file mode 100644 index 000000000..a387af907 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManagerPrivate.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitCookieManagerPrivate_h +#define WebKitCookieManagerPrivate_h + +#include "WebKitCookieManager.h" +#include "WebKitPrivate.h" + +WebKitCookieManager* webkitCookieManagerCreate(WKCookieManagerRef); + +#endif // WebKitCookieManagerPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp index 42cf0ab35..daf09ecc2 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp @@ -68,3 +68,17 @@ GQuark webkit_download_error_quark() COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_NETWORK, DownloadErrorNetwork); COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER, DownloadErrorCancelledByUser); COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_DOWNLOAD_ERROR_DESTINATION, DownloadErrorDestination); + +GQuark webkit_print_error_quark() +{ + return g_quark_from_static_string(WebCore::errorDomainPrint); +} + +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_GENERAL, PrintErrorGeneral); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND, PrintErrorPrinterNotFound); +COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE, PrintErrorInvalidPageRange); + +GQuark webkit_javascript_error_quark() +{ + return g_quark_from_static_string("WebKitJavascriptError"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h index 9b0e630c8..c20581683 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitError.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitError.h @@ -29,10 +29,12 @@ G_BEGIN_DECLS -#define WEBKIT_NETWORK_ERROR webkit_network_error_quark () -#define WEBKIT_POLICY_ERROR webkit_policy_error_quark () -#define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () -#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () +#define WEBKIT_NETWORK_ERROR webkit_network_error_quark () +#define WEBKIT_POLICY_ERROR webkit_policy_error_quark () +#define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () +#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () +#define WEBKIT_PRINT_ERROR webkit_print_error_quark () +#define WEBKIT_JAVASCRIPT_ERROR webkit_print_error_quark () /** * WebKitNetworkError: @@ -104,17 +106,47 @@ typedef enum { WEBKIT_DOWNLOAD_ERROR_DESTINATION = 401 } WebKitDownloadError; +/** + * WebKitPrintError: + * @WEBKIT_PRINT_ERROR_GENERAL: Unspecified error during a print operation + * @WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND: Selected printer cannot be found + * @WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE: Invalid page range + * + * Enum values used to denote the various print errors. + */ +typedef enum { + WEBKIT_PRINT_ERROR_GENERAL = 599, + WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND = 500, + WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE = 501 +} WebKitPrintError; + +/** + * WebKitJavascriptError: + * @WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED: An exception was raised in Javascript execution + * + * Enum values used to denote errors happending when executing Javascript + */ +typedef enum { + WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED = 699 +} WebKitJavascriptError; + +WEBKIT_API GQuark +webkit_network_error_quark (void); + +WEBKIT_API GQuark +webkit_policy_error_quark (void); + WEBKIT_API GQuark -webkit_network_error_quark (void); +webkit_plugin_error_quark (void); WEBKIT_API GQuark -webkit_policy_error_quark (void); +webkit_download_error_quark (void); WEBKIT_API GQuark -webkit_plugin_error_quark (void); +webkit_print_error_quark (void); WEBKIT_API GQuark -webkit_download_error_quark (void); +webkit_javascript_error_quark (void); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.cpp new file mode 100644 index 000000000..96b87a3ba --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.cpp @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitFileChooserRequest.h" + +#include "WebKitFileChooserRequestPrivate.h" +#include "WebOpenPanelParameters.h" +#include <WebCore/FileSystem.h> +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebCore; +using namespace WebKit; + +/** + * SECTION: WebKitFileChooserRequest + * @Short_description: A request to open a file chooser + * @Title: WebKitFileChooserRequest + * @See_also: #WebKitWebView + * + * Whenever the user interacts with an <input type='file' /> + * HTML element, WebKit will need to show a dialog to choose one or + * more files to be uploaded to the server along with the rest of the + * form data. For that to happen in a general way, instead of just + * opening a #GtkFileChooserDialog (which might be not desirable in + * some cases, which could prefer to use their own file chooser + * dialog), WebKit will fire the #WebKitWebView::run-file-chooser + * signal with a #WebKitFileChooserRequest object, which will allow + * the client application to specify the files to be selected, to + * inspect the details of the request (e.g. if multiple selection + * should be allowed) and to cancel the request, in case nothing was + * selected. + * + * In case the client application does not wish to handle this signal, + * WebKit will provide a default handler which will asynchronously run + * a regular #GtkFileChooserDialog for the user to interact with. + */ +G_DEFINE_TYPE(WebKitFileChooserRequest, webkit_file_chooser_request, G_TYPE_OBJECT) + +struct _WebKitFileChooserRequestPrivate { + WKRetainPtr<WKOpenPanelParametersRef> wkParameters; + WKRetainPtr<WKOpenPanelResultListenerRef> wkListener; + GRefPtr<GtkFileFilter> filter; + GRefPtr<GPtrArray> mimeTypes; + GRefPtr<GPtrArray> selectedFiles; + bool handledRequest; +}; + +enum { + PROP_0, + PROP_FILTER, + PROP_MIME_TYPES, + PROP_SELECT_MULTIPLE, + PROP_SELECTED_FILES, +}; + +static void webkit_file_chooser_request_init(WebKitFileChooserRequest* request) +{ + request->priv = G_TYPE_INSTANCE_GET_PRIVATE(request, WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestPrivate); + new (request->priv) WebKitFileChooserRequestPrivate(); +} + +static void webkitFileChooserRequestFinalize(GObject* object) +{ + WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(object); + + // Make sure the request is always handled before finalizing. + if (!request->priv->handledRequest) + webkit_file_chooser_request_cancel(request); + + request->priv->~WebKitFileChooserRequestPrivate(); + G_OBJECT_CLASS(webkit_file_chooser_request_parent_class)->finalize(object); +} + +static void webkitFileChooserRequestGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(object); + switch (propId) { + case PROP_FILTER: + g_value_set_object(value, webkit_file_chooser_request_get_mime_types_filter(request)); + break; + case PROP_MIME_TYPES: + g_value_set_boxed(value, webkit_file_chooser_request_get_mime_types(request)); + break; + case PROP_SELECT_MULTIPLE: + g_value_set_boolean(value, webkit_file_chooser_request_get_select_multiple(request)); + break; + case PROP_SELECTED_FILES: + g_value_set_boxed(value, webkit_file_chooser_request_get_selected_files(request)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + break; + } +} + +static void webkit_file_chooser_request_class_init(WebKitFileChooserRequestClass* requestClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(requestClass); + objectClass->finalize = webkitFileChooserRequestFinalize; + objectClass->get_property = webkitFileChooserRequestGetProperty; + g_type_class_add_private(requestClass, sizeof(WebKitFileChooserRequestPrivate)); + + /** + * WebKitFileChooserRequest:filter: + * + * The filter currently associated with the request. See + * webkit_file_chooser_request_get_mime_types_filter() for more + * details. + */ + g_object_class_install_property(objectClass, + PROP_FILTER, + g_param_spec_object("filter", + _("MIME types filter"), + _("The filter currently associated with the request"), + GTK_TYPE_FILE_FILTER, + WEBKIT_PARAM_READABLE)); + /** + * WebKitFileChooserRequest:mime-types: + * + * A %NULL-terminated array of strings containing the list of MIME + * types the file chooser dialog should handle. See + * webkit_file_chooser_request_get_mime_types() for more details. + */ + g_object_class_install_property(objectClass, + PROP_MIME_TYPES, + g_param_spec_boxed("mime-types", + _("MIME types"), + _("The list of MIME types associated with the request"), + G_TYPE_STRV, + WEBKIT_PARAM_READABLE)); + /** + * WebKitFileChooserRequest:select-multiple: + * + * Whether the file chooser should allow selecting multiple + * files. See + * webkit_file_chooser_request_get_select_multiple() for + * more details. + */ + g_object_class_install_property(objectClass, + PROP_SELECT_MULTIPLE, + g_param_spec_boolean("select-multiple", + _("Select multiple files"), + _("Whether the file chooser should allow selecting multiple files"), + FALSE, + WEBKIT_PARAM_READABLE)); + /** + * WebKitFileChooserRequest:selected-files: + * + * A %NULL-terminated array of strings containing the list of + * selected files associated to the current request. See + * webkit_file_chooser_request_get_selected_files() for more details. + */ + g_object_class_install_property(objectClass, + PROP_SELECTED_FILES, + g_param_spec_boxed("selected-files", + _("Selected files"), + _("The list of selected files associated with the request"), + G_TYPE_STRV, + WEBKIT_PARAM_READABLE)); +} + +WebKitFileChooserRequest* webkitFileChooserRequestCreate(WKOpenPanelParametersRef wkParameters, WKOpenPanelResultListenerRef wkListener) +{ + WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(g_object_new(WEBKIT_TYPE_FILE_CHOOSER_REQUEST, NULL)); + request->priv->wkParameters = wkParameters; + request->priv->wkListener = wkListener; + return request; +} + +/** + * webkit_file_chooser_request_get_mime_types: + * @request: a #WebKitFileChooserRequest + * + * Get the list of MIME types the file chooser dialog should handle, + * in the format specified in RFC 2046 for "media types". Its contents + * depend on the value of the 'accept' attribute for HTML input + * elements. This function should normally be called before presenting + * the file chooser dialog to the user, to decide whether to allow the + * user to select multiple files at once or only one. + * + * Returns: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings if a list of accepted MIME types + * is defined or %NULL otherwise, meaning that any MIME type should be + * accepted. This array and its contents are owned by WebKitGTK+ and + * should not be modified or freed. + */ +const gchar* const* webkit_file_chooser_request_get_mime_types(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), 0); + if (request->priv->mimeTypes) + return reinterpret_cast<gchar**>(request->priv->mimeTypes->pdata); + + WKRetainPtr<WKArrayRef> wkMimeTypes(AdoptWK, WKOpenPanelParametersCopyAcceptedMIMETypes(request->priv->wkParameters.get())); + size_t numOfMimeTypes = WKArrayGetSize(wkMimeTypes.get()); + if (!numOfMimeTypes) + return 0; + + request->priv->mimeTypes = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + for (size_t i = 0; i < numOfMimeTypes; ++i) { + WKStringRef wkMimeType = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkMimeTypes.get(), i)); + String mimeTypeString = toImpl(wkMimeType)->string(); + if (mimeTypeString.isEmpty()) + continue; + g_ptr_array_add(request->priv->mimeTypes.get(), g_strdup(mimeTypeString.utf8().data())); + } + g_ptr_array_add(request->priv->mimeTypes.get(), 0); + + return reinterpret_cast<gchar**>(request->priv->mimeTypes->pdata); +} + +/** + * webkit_file_chooser_request_get_mime_types_filter: + * @request: a #WebKitFileChooserRequest + * + * Get the filter currently associated with the request, ready to be + * used by #GtkFileChooser. This function should normally be called + * before presenting the file chooser dialog to the user, to decide + * whether to apply a filter so the user would not be allowed to + * select files with other MIME types. + * + * See webkit_file_chooser_request_get_mime_types() if you are + * interested in getting the list of accepted MIME types. + * + * Returns: (transfer none): a #GtkFileFilter if a list of accepted + * MIME types is defined or %NULL otherwise. The returned object is + * owned by WebKitGTK+ should not be modified or freed. + */ +GtkFileFilter* webkit_file_chooser_request_get_mime_types_filter(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), 0); + if (request->priv->filter) + return request->priv->filter.get(); + + WKRetainPtr<WKArrayRef> wkMimeTypes(AdoptWK, WKOpenPanelParametersCopyAcceptedMIMETypes(request->priv->wkParameters.get())); + size_t numOfMimeTypes = WKArrayGetSize(wkMimeTypes.get()); + if (!numOfMimeTypes) + return 0; + + // Do not use adoptGRef here, since we want to sink the floating + // reference for the new instance of GtkFileFilter, so we make + // sure we keep the ownership during the lifetime of the request. + request->priv->filter = gtk_file_filter_new(); + for (size_t i = 0; i < numOfMimeTypes; ++i) { + WKStringRef wkMimeType = static_cast<WKStringRef>(WKArrayGetItemAtIndex(wkMimeTypes.get(), i)); + String mimeTypeString = toImpl(wkMimeType)->string(); + if (mimeTypeString.isEmpty()) + continue; + gtk_file_filter_add_mime_type(request->priv->filter.get(), mimeTypeString.utf8().data()); + } + + return request->priv->filter.get(); +} + +/** + * webkit_file_chooser_request_get_select_multiple: + * @request: a #WebKitFileChooserRequest + * + * Determine whether the file chooser associated to this + * #WebKitFileChooserRequest should allow selecting multiple files, + * which depends on the HTML input element having a 'multiple' + * attribute defined. + * + * Returns: %TRUE if the file chooser should allow selecting multiple files or %FALSE otherwise. + */ +gboolean webkit_file_chooser_request_get_select_multiple(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), FALSE); + return WKOpenPanelParametersGetAllowsMultipleFiles(request->priv->wkParameters.get()); +} + +/** + * webkit_file_chooser_request_select_files: + * @request: a #WebKitFileChooserRequest + * @files: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings, containing paths to local files. + * + * Ask WebKit to select local files for upload and complete the + * request. + */ +void webkit_file_chooser_request_select_files(WebKitFileChooserRequest* request, const gchar* const* files) +{ + g_return_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request)); + g_return_if_fail(files); + + GRefPtr<GPtrArray> selectedFiles = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + WKRetainPtr<WKMutableArrayRef> wkChosenFiles(AdoptWK, WKMutableArrayCreate()); + for (int i = 0; files[i]; i++) { + GRefPtr<GFile> filename = adoptGRef(g_file_new_for_path(files[i])); + + // Make sure the file path is presented as an URI (escaped + // string, with the 'file://' prefix) to WebCore otherwise the + // FileChooser won't actually choose it. + GOwnPtr<char> uri(g_file_get_uri(filename.get())); + WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(uri.get())); + WKArrayAppendItem(wkChosenFiles.get(), wkURL.get()); + + // Do not use the URI here because this won't reach WebCore. + g_ptr_array_add(selectedFiles.get(), g_strdup(files[i])); + } + g_ptr_array_add(selectedFiles.get(), 0); + + // Select the files in WebCore and update local private attributes. + WKOpenPanelResultListenerChooseFiles(request->priv->wkListener.get(), wkChosenFiles.get()); + request->priv->selectedFiles = selectedFiles; + request->priv->handledRequest = true; +} + +/** + * webkit_file_chooser_request_get_selected_files: + * @request: a #WebKitFileChooserRequest + * + * Get the list of selected files currently associated to the + * request. Initially, the return value of this method contains any + * files selected in previous file chooser requests for this HTML + * input element. Once webkit_file_chooser_request_select_files, the + * value will reflect whatever files are given. + * + * This function should normally be called only before presenting the + * file chooser dialog to the user, to decide whether to perform some + * extra action, like pre-selecting the files from a previous request. + * + * Returns: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings if there are selected files + * associated with the request or %NULL otherwise. This array and its + * contents are owned by WebKitGTK+ and should not be modified or + * freed. + */ +const gchar* const* webkit_file_chooser_request_get_selected_files(WebKitFileChooserRequest* request) +{ + g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), 0); + if (request->priv->selectedFiles) + return reinterpret_cast<gchar**>(request->priv->selectedFiles->pdata); + + const Vector<String> selectedFileNames = toImpl(request->priv->wkParameters.get())->selectedFileNames(); + size_t numOfFiles = selectedFileNames.size(); + if (!numOfFiles) + return 0; + + request->priv->selectedFiles = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + for (size_t i = 0; i < numOfFiles; ++i) { + if (selectedFileNames[i].isEmpty()) + continue; + CString filename = fileSystemRepresentation(selectedFileNames[i]); + g_ptr_array_add(request->priv->selectedFiles.get(), g_strdup(filename.data())); + } + g_ptr_array_add(request->priv->selectedFiles.get(), 0); + + return reinterpret_cast<gchar**>(request->priv->selectedFiles->pdata); +} + +/** + * webkit_file_chooser_request_cancel: + * @request: a #WebKitFileChooserRequest + * + * Ask WebKit to cancel the request. It's important to do this in case + * no selection has been made in the client, otherwise the request + * won't be properly completed and the browser will keep the request + * pending forever, which might cause the browser to hang. + */ +void webkit_file_chooser_request_cancel(WebKitFileChooserRequest* request) +{ + g_return_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request)); + WKOpenPanelResultListenerCancel(request->priv->wkListener.get()); + request->priv->handledRequest = true; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.h new file mode 100644 index 000000000..88eec9966 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequest.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitFileChooserRequest_h +#define WebKitFileChooserRequest_h + +#include <gtk/gtk.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_FILE_CHOOSER_REQUEST (webkit_file_chooser_request_get_type()) +#define WEBKIT_FILE_CHOOSER_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequest)) +#define WEBKIT_FILE_CHOOSER_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestClass)) +#define WEBKIT_IS_FILE_CHOOSER_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST)) +#define WEBKIT_IS_FILE_CHOOSER_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_FILE_CHOOSER_REQUEST)) +#define WEBKIT_FILE_CHOOSER_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestClass)) + +typedef struct _WebKitFileChooserRequest WebKitFileChooserRequest; +typedef struct _WebKitFileChooserRequestClass WebKitFileChooserRequestClass; +typedef struct _WebKitFileChooserRequestPrivate WebKitFileChooserRequestPrivate; + +struct _WebKitFileChooserRequest { + GObject parent; + + /*< private >*/ + WebKitFileChooserRequestPrivate *priv; +}; + +struct _WebKitFileChooserRequestClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_file_chooser_request_get_type (void); + +WEBKIT_API const gchar * const * +webkit_file_chooser_request_get_mime_types (WebKitFileChooserRequest *request); + +WEBKIT_API GtkFileFilter * +webkit_file_chooser_request_get_mime_types_filter (WebKitFileChooserRequest *request); + +WEBKIT_API gboolean +webkit_file_chooser_request_get_select_multiple (WebKitFileChooserRequest *request); + +WEBKIT_API void +webkit_file_chooser_request_select_files (WebKitFileChooserRequest *request, + const gchar * const *files); + +WEBKIT_API const gchar * const * +webkit_file_chooser_request_get_selected_files (WebKitFileChooserRequest *request); + +WEBKIT_API void +webkit_file_chooser_request_cancel (WebKitFileChooserRequest *request); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequestPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequestPrivate.h new file mode 100644 index 000000000..af7224a96 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFileChooserRequestPrivate.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitFileChooserRequestPrivate_h +#define WebKitFileChooserRequestPrivate_h + +#include "WebKitFileChooserRequest.h" +#include "WebKitPrivate.h" + +WebKitFileChooserRequest* webkitFileChooserRequestCreate(WKOpenPanelParametersRef, WKOpenPanelResultListenerRef); + +#endif // WebKitFileChooserRequestPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.cpp new file mode 100644 index 000000000..75b51e25d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitFullscreenClient.h" + +#include "WebKitPrivate.h" +#include "WebKitWebViewPrivate.h" + +using namespace WebKit; + +static bool willEnterFullScreen(const void* clientInfo) +{ + return webkitWebViewEnterFullScreen(WEBKIT_WEB_VIEW(clientInfo)); +} + +static bool willExitFullScreen(const void* clientInfo) +{ + return webkitWebViewLeaveFullScreen(WEBKIT_WEB_VIEW(clientInfo)); +} + +void attachFullScreenClientToView(WebKitWebView* webView) +{ + WKFullScreenClientGtk wkFullScreenClient = { + kWKFullScreenClientGtkCurrentVersion, + webView, // clientInfo + willEnterFullScreen, + willExitFullScreen + }; + WKViewSetFullScreenClientGtk(toAPI(WEBKIT_WEB_VIEW_BASE(webView)), &wkFullScreenClient); +} + diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.h new file mode 100644 index 000000000..187c067af --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitFullscreenClient.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitFullscreenClient_h +#define WebKitFullscreenClient_h + +#include "WebKitWebView.h" + +void attachFullScreenClientToView(WebKitWebView*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp new file mode 100644 index 000000000..84ad04d03 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitJavascriptResult.h" + +#include "WebKitJavascriptResultPrivate.h" +#include <wtf/gobject/GRefPtr.h> + +struct _WebKitJavascriptResult { + _WebKitJavascriptResult(WebKitWebView* view, WKSerializedScriptValueRef wkSerializedScriptValue) + : webView(view) + , referenceCount(1) + { + value = WKSerializedScriptValueDeserialize(wkSerializedScriptValue, webkit_web_view_get_javascript_global_context(view), 0); + } + + GRefPtr<WebKitWebView> webView; + JSValueRef value; + + int referenceCount; +}; + +G_DEFINE_BOXED_TYPE(WebKitJavascriptResult, webkit_javascript_result, webkit_javascript_result_ref, webkit_javascript_result_unref) + +WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView* webView, WKSerializedScriptValueRef wkSerializedScriptValue) +{ + WebKitJavascriptResult* result = g_slice_new(WebKitJavascriptResult); + new (result) WebKitJavascriptResult(webView, wkSerializedScriptValue); + return result; +} + +/** + * webkit_javascript_result_ref: + * @js_result: a #WebKitJavascriptResult + * + * Atomically increments the reference count of @js_result by one. This + * function is MT-safe and may be called from any thread. + * + * Returns: The passed in #WebKitJavascriptResult + */ +WebKitJavascriptResult* webkit_javascript_result_ref(WebKitJavascriptResult* javascriptResult) +{ + g_atomic_int_inc(&javascriptResult->referenceCount); + return javascriptResult; +} + +/** + * webkit_javascript_result_unref: + * @js_result: a #WebKitJavascriptResult + * + * Atomically decrements the reference count of @js_result by one. If the + * reference count drops to 0, all memory allocated by the #WebKitJavascriptResult is + * released. This function is MT-safe and may be called from any + * thread. + */ +void webkit_javascript_result_unref(WebKitJavascriptResult* javascriptResult) +{ + if (g_atomic_int_dec_and_test(&javascriptResult->referenceCount)) { + javascriptResult->~WebKitJavascriptResult(); + g_slice_free(WebKitJavascriptResult, javascriptResult); + } +} + +/** + * webkit_javascript_result_get_global_context: + * @js_result: a #WebKitJavascriptResult + * + * Get the global Javascript context that should be used with the + * <function>JSValueRef</function> returned by webkit_javascript_result_get_value(). + * + * Returns: the <function>JSGlobalContextRef</function> for the #WebKitJavascriptResult + */ +JSGlobalContextRef webkit_javascript_result_get_global_context(WebKitJavascriptResult* javascriptResult) +{ + return webkit_web_view_get_javascript_global_context(javascriptResult->webView.get()); +} + +/** + * webkit_javascript_result_get_value: + * @js_result: a #WebKitJavascriptResult + * + * Get the value of @js_result. You should use the <function>JSGlobalContextRef</function> + * returned by webkit_javascript_result_get_global_context() to use the <function>JSValueRef</function>. + * + * Returns: the <function>JSValueRef</function> of the #WebKitJavascriptResult + */ +JSValueRef webkit_javascript_result_get_value(WebKitJavascriptResult* javascriptResult) +{ + return javascriptResult->value; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h new file mode 100644 index 000000000..5a9f7389f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitJavascriptResult_h +#define WebKitJavascriptResult_h + +#include <JavaScriptCore/JSBase.h> +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_JAVASCRIPT_RESULT (webkit_javascript_result_get_type()) + +typedef struct _WebKitJavascriptResult WebKitJavascriptResult; + + +WEBKIT_API GType +webkit_javascript_result_get_type (void); + +WEBKIT_API WebKitJavascriptResult * +webkit_javascript_result_ref (WebKitJavascriptResult *js_result); + +WEBKIT_API void +webkit_javascript_result_unref (WebKitJavascriptResult *js_result); + +WEBKIT_API JSGlobalContextRef +webkit_javascript_result_get_global_context (WebKitJavascriptResult *js_result); + +WEBKIT_API JSValueRef +webkit_javascript_result_get_value (WebKitJavascriptResult *js_result); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h new file mode 100644 index 000000000..840ead058 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitJavascriptResultPrivate_h +#define WebKitJavascriptResultPrivate_h + +#include "WebKitJavascriptResult.h" +#include "WebKitPrivate.h" +#include "WebKitWebView.h" + +WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView*, WKSerializedScriptValueRef); + +#endif // WebKitJavascriptResultPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp index d79d40149..7da0b197a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp @@ -28,7 +28,9 @@ #include <WebCore/GtkUtilities.h> #include <WebCore/NotImplemented.h> #include <glib/gi18n-lib.h> +#include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> #ifdef HAVE_GTK_UNIX_PRINTING #include <gtk/gtkunixprint.h> @@ -46,6 +48,7 @@ enum { enum { FINISHED, + FAILED, LAST_SIGNAL }; @@ -193,6 +196,24 @@ static void webkit_print_operation_class_init(WebKitPrintOperationClass* printOp g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * WebKitPrintOperation::failed: + * @print_operation: the #WebKitPrintOperation on which the signal was emitted + * @error: the #GError that was triggered + * + * Emitted when an error occurs while printing. The given @error, of the domain + * %WEBKIT_PRINT_ERROR, contains further details of the failure. + * The #WebKitPrintOperation::finished signal is emitted after this one. + */ + signals[FAILED] = + g_signal_new("failed", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + g_type_class_add_private(printOperationClass, sizeof(WebKitPrintOperationPrivate)); } @@ -237,11 +258,19 @@ static WebKitPrintOperationResponse webkitPrintOperationRunDialog(WebKitPrintOpe } #endif -static void drawPagesForPrintingCompleted(WKErrorRef, void* context) +static void drawPagesForPrintingCompleted(WKErrorRef wkPrintError, WKErrorRef, void* context) { GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(WEBKIT_PRINT_OPERATION(context)); WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(printOperation->priv->webView)); page->endPrinting(); + + const WebCore::ResourceError& resourceError = toImpl(wkPrintError)->platformError(); + if (!resourceError.isNull()) { + GOwnPtr<GError> printError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), + resourceError.errorCode(), + resourceError.localizedDescription().utf8().data())); + g_signal_emit(printOperation.get(), signals[FAILED], 0, printError.get()); + } g_signal_emit(printOperation.get(), signals[FINISHED], 0, NULL); } @@ -249,7 +278,7 @@ static void webkitPrintOperationPrintPagesForFrame(WebKitPrintOperation* printOp { PrintInfo printInfo(printSettings, pageSetup); WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(printOperation->priv->webView)); - page->drawPagesForPrinting(webFrame, printInfo, VoidCallback::create(g_object_ref(printOperation), &drawPagesForPrintingCompleted)); + page->drawPagesForPrinting(webFrame, printInfo, PrintFinishedCallback::create(g_object_ref(printOperation), &drawPagesForPrintingCompleted)); } WebKitPrintOperationResponse webkitPrintOperationRunDialogForFrame(WebKitPrintOperation* printOperation, GtkWindow* parent, WebFrameProxy* webFrame) @@ -368,7 +397,8 @@ void webkit_print_operation_set_page_setup(WebKitPrintOperation* printOperation, * If the print dialog is cancelled %WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL * is returned. If the user clicks on the print button, %WEBKIT_PRINT_OPERATION_RESPONSE_PRINT * is returned and the print operation starts. In this case, the #WebKitPrintOperation::finished - * signal is emitted when the operation finishes. + * signal is emitted when the operation finishes. If an error occurs while printing, the signal + * #WebKitPrintOperation::failed is emitted before #WebKitPrintOperation::finished. * If the print dialog is not cancelled current print settings and page setup of @print_operation * are updated with options selected by the user when Print button is pressed in print dialog. * You can get the updated print settings and page setup by calling @@ -395,7 +425,8 @@ WebKitPrintOperationResponse webkit_print_operation_run_dialog(WebKitPrintOperat * webkit_print_operation_set_page_setup(), the default options will be used * and the print job will be sent to the default printer. * The #WebKitPrintOperation::finished signal is emitted when the printing - * operation finishes. + * operation finishes. If an error occurs while printing the signal + * #WebKitPrintOperation::failed is emitted before #WebKitPrintOperation::finished. */ void webkit_print_operation_print(WebKitPrintOperation* printOperation) { diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index e785c3638..4b7e9ad49 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -29,7 +29,9 @@ #include <WebKit2/WKAPICast.h> #include <WebKit2/WKDownload.h> #include <WebKit2/WKFindOptions.h> +#include <WebKit2/WKFullScreenClientGtk.h> #include <WebKit2/WKRetainPtr.h> +#include <WebKit2/WKSerializedScriptValue.h> #include <WebKit2/WKString.h> #include <WebKit2/WebKit2.h> #include <glib.h> diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp new file mode 100644 index 000000000..1cd8aaf7f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitResourceLoadClient.h" + +#include "WebContext.h" +#include "WebKitURIRequestPrivate.h" +#include "WebKitURIResponsePrivate.h" +#include "WebKitWebResourcePrivate.h" +#include "WebKitWebViewBasePrivate.h" +#include "WebKitWebViewPrivate.h" +#include "WebURLResponse.h" +#include <WebKit2/WKString.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebCore; +using namespace WebKit; + +static void didInitiateLoadForResource(WKPageRef, WKFrameRef wkFrame, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, bool pageIsProvisionallyLoading, const void* clientInfo) +{ + GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); + webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), wkFrame, resourceIdentifier, request.get(), pageIsProvisionallyLoading); +} + +static void didSendRequestForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, WKURLResponseRef wkRedirectResponse, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); + GRefPtr<WebKitURIResponse> redirectResponse = wkRedirectResponse ? adoptGRef(webkitURIResponseCreateForResourceResponse(toImpl(wkRedirectResponse)->resourceResponse())) : 0; + webkitWebResourceSentRequest(resource.get(), request.get(), redirectResponse.get()); +} + +static void didReceiveResponseForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKURLResponseRef wkResponse, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + GRefPtr<WebKitURIResponse> response = adoptGRef(webkitURIResponseCreateForResourceResponse(toImpl(wkResponse)->resourceResponse())); + webkitWebResourceSetResponse(resource.get(), response.get()); +} + +static void didReceiveContentLengthForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, uint64_t contentLength, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + webkitWebResourceNotifyProgress(resource.get(), contentLength); +} + +static void didFinishLoadForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, const void* clientInfo) +{ + GRefPtr<WebKitWebResource> resource = webkitWebViewResourceLoadFinished(WEBKIT_WEB_VIEW(clientInfo), resourceIdentifier); + if (!resource) + return; + + webkitWebResourceFinished(resource.get()); +} + +static void didFailLoadForResource(WKPageRef, WKFrameRef, uint64_t resourceIdentifier, WKErrorRef wkError, const void* clientInfo) +{ + WebKitWebView* webView = WEBKIT_WEB_VIEW(clientInfo); + GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier); + if (!resource) + return; + + const ResourceError& resourceError = toImpl(wkError)->platformError(); + GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()), + resourceError.errorCode(), + resourceError.localizedDescription().utf8().data())); + webkitWebResourceFailed(resource.get(), webError.get()); + webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier); +} + +void attachResourceLoadClientToView(WebKitWebView* webView) +{ + WKPageResourceLoadClient wkResourceLoadClient = { + kWKPageResourceLoadClientCurrentVersion, + webView, // ClientInfo + didInitiateLoadForResource, + didSendRequestForResource, + didReceiveResponseForResource, + didReceiveContentLengthForResource, + didFinishLoadForResource, + didFailLoadForResource, + }; + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WKPageSetPageResourceLoadClient(wkPage, &wkResourceLoadClient); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.h b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.h new file mode 100644 index 000000000..0e6a3613c --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitResourceLoadClient.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitResourceLoadClient_h +#define WebKitResourceLoadClient_h + +#include "WebKitWebView.h" + +void attachResourceLoadClientToView(WebKitWebView*); + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index b4b267d1b..8bec722b3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -105,7 +105,8 @@ enum { PROP_PRINT_BACKGROUNDS, PROP_ENABLE_WEBAUDIO, PROP_ENABLE_WEBGL, - PROP_ZOOM_TEXT_ONLY + PROP_ZOOM_TEXT_ONLY, + PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD }; static void webKitSettingsSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -215,6 +216,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu case PROP_ZOOM_TEXT_ONLY: webkit_settings_set_zoom_text_only(settings, g_value_get_boolean(value)); break; + case PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD: + webkit_settings_set_javascript_can_access_clipboard(settings, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -328,6 +332,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val case PROP_ZOOM_TEXT_ONLY: g_value_set_boolean(value, webkit_settings_get_zoom_text_only(settings)); break; + case PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD: + g_value_set_boolean(value, webkit_settings_get_javascript_can_access_clipboard(settings)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -840,6 +847,21 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) FALSE, readWriteConstructParamFlags)); + /** + * WebKitSettings:javascript-can-access-clipboard: + * + * Whether JavaScript can access the clipboard. The default value is %FALSE. If + * set to %TRUE, document.execCommand() allows cut, copy and paste commands. + * + */ + g_object_class_install_property(gObjectClass, + PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD, + g_param_spec_boolean("javascript-can-access-clipboard", + _("JavaScript can access clipboard"), + _("Whether JavaScript can access Clipboard"), + FALSE, + readWriteConstructParamFlags)); + g_type_class_add_private(klass, sizeof(WebKitSettingsPrivate)); } @@ -2133,3 +2155,41 @@ gboolean webkit_settings_get_zoom_text_only(WebKitSettings* settings) return settings->priv->zoomTextOnly; } +/** + * webkit_settings_get_javascript_can_access_clipboard: + * @settings: a #WebKitSettings + * + * Get the #WebKitSettings:javascript-can-access-clipboard property. + * + * Returns: %TRUE If javascript-can-access-clipboard is enabled or %FALSE otherwise. + */ +gboolean webkit_settings_get_javascript_can_access_clipboard(WebKitSettings* settings) +{ + g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); + + return WKPreferencesGetJavaScriptCanAccessClipboard(settings->priv->preferences.get()) + && WKPreferencesGetDOMPasteAllowed(settings->priv->preferences.get()); +} + +/** + * webkit_settings_set_javascript_can_access_clipboard: + * @settings: a #WebKitSettings + * @enabled: Value to be set + * + * Set the #WebKitSettings:javascript-can-access-clipboard property. + */ +void webkit_settings_set_javascript_can_access_clipboard(WebKitSettings* settings, gboolean enabled) +{ + g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); + + WebKitSettingsPrivate* priv = settings->priv; + bool currentValue = WKPreferencesGetJavaScriptCanAccessClipboard(priv->preferences.get()) + && WKPreferencesGetDOMPasteAllowed(priv->preferences.get()); + if (currentValue == enabled) + return; + + WKPreferencesSetJavaScriptCanAccessClipboard(priv->preferences.get(), enabled); + WKPreferencesSetDOMPasteAllowed(priv->preferences.get(), enabled); + + g_object_notify(G_OBJECT(settings), "javascript-can-access-clipboard"); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h index 25a78aca3..57bf3f17d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h @@ -314,6 +314,13 @@ webkit_settings_set_zoom_text_only (WebKitSettings * WEBKIT_API gboolean webkit_settings_get_zoom_text_only (WebKitSettings *settings); +WEBKIT_API gboolean +webkit_settings_get_javascript_can_access_clipboard (WebKitSettings *settings); + +WEBKIT_API void +webkit_settings_set_javascript_can_access_clipboard (WebKitSettings *settings, + gboolean enabled); + G_END_DECLS #endif /* WebKitSettings_h */ diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp index 6f0e11c82..9f78c9cbf 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp @@ -20,12 +20,14 @@ #include "config.h" #include "WebKitUIClient.h" +#include "WebKitFileChooserRequestPrivate.h" #include "WebKitPrivate.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebPageProxy.h" #include <WebCore/GtkUtilities.h> +#include <wtf/gobject/GRefPtr.h> using namespace WebKit; @@ -136,6 +138,12 @@ static void printFrame(WKPageRef page, WKFrameRef frame, const void*) webkitWebViewPrintFrame(WEBKIT_WEB_VIEW(toImpl(page)->viewWidget()), frame); } +static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void *clientInfo) +{ + GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkitFileChooserRequestCreate(parameters, listener)); + webkitWebViewRunFileChooserRequest(WEBKIT_WEB_VIEW(clientInfo), request.get()); +} + void attachUIClientToView(WebKitWebView* webView) { WKPageUIClient wkUIClient = { @@ -169,7 +177,7 @@ void attachUIClientToView(WebKitWebView* webView) 0, // didDraw 0, // pageDidScroll 0, // exceededDatabaseQuota - 0, // runOpenPanel + runOpenPanel, 0, // decidePolicyForGeolocationPermissionRequest 0, // headerHeight 0, // footerHeight diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 360b0a627..0b68c086d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -21,6 +21,7 @@ #include "WebKitWebContext.h" #include "WebContext.h" +#include "WebKitCookieManagerPrivate.h" #include "WebKitDownloadClient.h" #include "WebKitDownloadPrivate.h" #include "WebKitPrivate.h" @@ -39,6 +40,8 @@ enum { struct _WebKitWebContextPrivate { WKRetainPtr<WKContextRef> context; + + GRefPtr<WebKitCookieManager> cookieManager; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -84,12 +87,11 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass static gpointer createDefaultWebContext(gpointer) { - WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL)); + static GRefPtr<WebKitWebContext> webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL))); webContext->priv->context = WKContextGetSharedProcessContext(); WKContextSetCacheModel(webContext->priv->context.get(), kWKCacheModelPrimaryWebBrowser); - attachDownloadClientToContext(webContext); - - return webContext; + attachDownloadClientToContext(webContext.get()); + return webContext.get(); } /** @@ -215,6 +217,25 @@ WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const return download; } +/** + * webkit_web_context_get_cookie_manager: + * @context: a #WebKitWebContext + * + * Get the #WebKitCookieManager of @context. + * + * Returns: (transfer none): the #WebKitCookieManager of @context. + */ +WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + + WebKitWebContextPrivate* priv = context->priv; + if (!priv->cookieManager) + priv->cookieManager = adoptGRef(webkitCookieManagerCreate(WKContextGetCookieManager(priv->context.get()))); + + return priv->cookieManager.get(); +} + WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) { GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index b88bed0da..45b6e6c1d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -25,6 +25,7 @@ #define WebKitWebContext_h #include <glib-object.h> +#include <webkit2/WebKitCookieManager.h> #include <webkit2/WebKitDefines.h> #include <webkit2/WebKitDownload.h> @@ -79,20 +80,23 @@ struct _WebKitWebContextClass { }; WEBKIT_API GType -webkit_web_context_get_type (void); +webkit_web_context_get_type (void); WEBKIT_API WebKitWebContext * -webkit_web_context_get_default (void); +webkit_web_context_get_default (void); WEBKIT_API void -webkit_web_context_set_cache_model (WebKitWebContext *context, - WebKitCacheModel cache_model); +webkit_web_context_set_cache_model (WebKitWebContext *context, + WebKitCacheModel cache_model); WEBKIT_API WebKitCacheModel -webkit_web_context_get_cache_model (WebKitWebContext *context); +webkit_web_context_get_cache_model (WebKitWebContext *context); WEBKIT_API WebKitDownload * -webkit_web_context_download_uri (WebKitWebContext *context, - const gchar *uri); +webkit_web_context_download_uri (WebKitWebContext *context, + const gchar *uri); + +WEBKIT_API WebKitCookieManager * +webkit_web_context_get_cookie_manager (WebKitWebContext *context); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp new file mode 100644 index 000000000..6bd51fa08 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "WebKitWebResource.h" + +#include "WebKitMarshal.h" +#include "WebKitURIRequest.h" +#include "WebKitWebResourcePrivate.h" +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + SENT_REQUEST, + RECEIVED_DATA, + FINISHED, + FAILED, + + LAST_SIGNAL +}; + +enum { + PROP_0, + + PROP_URI, + PROP_RESPONSE +}; + + +struct _WebKitWebResourcePrivate { + WKRetainPtr<WKFrameRef> wkFrame; + CString uri; + GRefPtr<WebKitURIResponse> response; + bool isMainResource; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitWebResource, webkit_web_resource, G_TYPE_OBJECT) + +static void webkitWebResourceFinalize(GObject* object) +{ + WEBKIT_WEB_RESOURCE(object)->priv->~WebKitWebResourcePrivate(); + G_OBJECT_CLASS(webkit_web_resource_parent_class)->finalize(object); +} + +static void webkitWebResourceGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitWebResource* resource = WEBKIT_WEB_RESOURCE(object); + + switch (propId) { + case PROP_URI: + g_value_set_string(value, webkit_web_resource_get_uri(resource)); + break; + case PROP_RESPONSE: + g_value_set_object(value, webkit_web_resource_get_response(resource)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + } +} + +static void webkit_web_resource_init(WebKitWebResource* resource) +{ + WebKitWebResourcePrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(resource, WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResourcePrivate); + resource->priv = priv; + new (priv) WebKitWebResourcePrivate(); +} + +static void webkit_web_resource_class_init(WebKitWebResourceClass* resourceClass) +{ + GObjectClass* objectClass = G_OBJECT_CLASS(resourceClass); + objectClass->get_property = webkitWebResourceGetProperty; + objectClass->finalize = webkitWebResourceFinalize; + + /** + * WebKitWebResource:uri: + * + * The current active URI of the #WebKitWebResource. + * See webkit_web_resource_get_uri() for more details. + */ + g_object_class_install_property(objectClass, + PROP_URI, + g_param_spec_string("uri", + _("URI"), + _("The current active URI of the result"), + 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebResource:response: + * + * The #WebKitURIResponse associated with this resource. + */ + g_object_class_install_property(objectClass, + PROP_RESPONSE, + g_param_spec_object("response", + _("Response"), + _("The response of the resource"), + WEBKIT_TYPE_URI_RESPONSE, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebResource::sent-request: + * @resource: the #WebKitWebResource + * @request: a #WebKitURIRequest + * @redirected_response: a #WebKitURIResponse, or %NULL + * + * This signal is emitted when @request has been sent to the + * server. In case of a server redirection this signal is + * emitted again with the @request argument containing the new + * request sent to the server due to the redirection and the + * @redirected_response parameter containing the response + * received by the server for the initial request. + */ + signals[SENT_REQUEST] = + g_signal_new("sent-request", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + webkit_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, + WEBKIT_TYPE_URI_REQUEST, + WEBKIT_TYPE_URI_RESPONSE); + + /** + * WebKitWebResource::received-data: + * @resource: the #WebKitWebResource + * @data_length: the length of data received in bytes + * + * This signal is emitted after response is received, + * every time new data has been received. It's + * useful to know the progress of the resource load operation. + */ + signals[RECEIVED_DATA] = + g_signal_new("received-data", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + webkit_marshal_VOID__UINT64, + G_TYPE_NONE, 1, + G_TYPE_UINT64); + + /** + * WebKitWebResource::finished: + * @resource: the #WebKitWebResource + * + * This signal is emitted when the resource load finishes successfully + * or due to an error. In case of errors #WebKitWebResource::failed signal + * is emitted before this one. + */ + signals[FINISHED] = + g_signal_new("finished", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * WebKitWebResource::failed: + * @resource: the #WebKitWebResource + * @error: the #GError that was triggered + * + * This signal is emitted when an error occurs during the resource + * load operation. + */ + signals[FAILED] = + g_signal_new("failed", + G_TYPE_FROM_CLASS(objectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + g_type_class_add_private(resourceClass, sizeof(WebKitWebResourcePrivate)); +} + +static void webkitWebResourceUpdateURI(WebKitWebResource* resource, const CString& requestURI) +{ + if (resource->priv->uri == requestURI) + return; + + resource->priv->uri = requestURI; + g_object_notify(G_OBJECT(resource), "uri"); +} + +WebKitWebResource* webkitWebResourceCreate(WKFrameRef wkFrame, WebKitURIRequest* request, bool isMainResource) +{ + ASSERT(wkFrame); + WebKitWebResource* resource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, NULL)); + resource->priv->wkFrame = wkFrame; + resource->priv->uri = webkit_uri_request_get_uri(request); + resource->priv->isMainResource = isMainResource; + return resource; +} + +void webkitWebResourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) +{ + webkitWebResourceUpdateURI(resource, webkit_uri_request_get_uri(request)); + g_signal_emit(resource, signals[SENT_REQUEST], 0, request, redirectResponse); +} + +void webkitWebResourceSetResponse(WebKitWebResource* resource, WebKitURIResponse* response) +{ + resource->priv->response = response; + g_object_notify(G_OBJECT(resource), "response"); +} + +void webkitWebResourceNotifyProgress(WebKitWebResource* resource, guint64 bytesReceived) +{ + g_signal_emit(resource, signals[RECEIVED_DATA], 0, bytesReceived); +} + +void webkitWebResourceFinished(WebKitWebResource* resource) +{ + g_signal_emit(resource, signals[FINISHED], 0, NULL); +} + +void webkitWebResourceFailed(WebKitWebResource* resource, GError* error) +{ + g_signal_emit(resource, signals[FAILED], 0, error); + g_signal_emit(resource, signals[FINISHED], 0, NULL); +} + +/** + * webkit_web_resource_get_uri: + * @resource: a #WebKitWebResource + * + * Returns the current active URI of @web_view. The active URI might change during + * a load operation: + * + * <orderedlist> + * <listitem><para> + * When the resource load starts, the active URI is the requested URI + * </para></listitem> + * <listitem><para> + * When the initial request is sent to the server, #WebKitWebResource::sent-request + * signal is emitted without a redirected response, the active URI is the URI of + * the request sent to the server. + * </para></listitem> + * <listitem><para> + * In case of a server redirection, #WebKitWebResource::sent-request signal + * is emitted again with a redirected response, the active URI is the URI the request + * was redirected to. + * </para></listitem> + * <listitem><para> + * When the response is received from the server, the active URI is the final + * one and it will not change again. + * </para></listitem> + * </orderedlist> + * + * You can monitor the active URI by connecting to the notify::uri + * signal of @resource. + * + * Returns: the current active URI of @resource + */ +const char* webkit_web_resource_get_uri(WebKitWebResource* resource) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0); + + return resource->priv->uri.data(); +} + +/** + * webkit_web_resource_get_response: + * @resource: a #WebKitWebResource + * + * Retrieves the #WebKitURIResponse of the resource load operation. + * This method returns %NULL if called before the response + * is received from the server. You can connect to notify::response + * signal to be notified when the response is received. + * + * Returns: (transfer none): the #WebKitURIResponse, or %NULL if + * the response hasn't been received yet. + */ +WebKitURIResponse* webkit_web_resource_get_response(WebKitWebResource* resource) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0); + + return resource->priv->response.get(); +} + +static void resourceDataCallback(WKDataRef data, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + g_simple_async_result_set_op_res_gpointer(result.get(), const_cast<OpaqueWKData*>(data), 0); + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_web_resource_get_data: + * @resource: a #WebKitWebResource + * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously get the raw data for @resource. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_web_resource_get_data_finish() to get the result of the operation. + */ +void webkit_web_resource_get_data(WebKitWebResource* resource, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_WEB_RESOURCE(resource)); + + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(resource), callback, userData, + reinterpret_cast<gpointer>(webkit_web_resource_get_data)); + if (resource->priv->isMainResource) + WKFrameGetMainResourceData(resource->priv->wkFrame.get(), resourceDataCallback, result); + else { + WKRetainPtr<WKURLRef> url(AdoptWK, WKURLCreateWithUTF8CString(resource->priv->uri.data())); + WKFrameGetResourceData(resource->priv->wkFrame.get(), url.get(), resourceDataCallback, result); + } +} + +/** + * webkit_web_resource_get_data_finish: + * @resource: a #WebKitWebResource + * @result: a #GAsyncResult + * @length: (out): return location for the length of the resource data + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_web_resource_get_data(). + * + * Returns: (transfer full): a string with the data of @resource, or %NULL in case + * of error. if @length is not %NULL, the size of the data will be assigned to it. + */ +guchar* webkit_web_resource_get_data_finish(WebKitWebResource* resource, GAsyncResult* result, gsize* length, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_RESOURCE(resource), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_resource_get_data); + + if (g_simple_async_result_propagate_error(simple, error)) + return 0; + + WKDataRef wkData = static_cast<WKDataRef>(g_simple_async_result_get_op_res_gpointer(simple)); + if (length) + *length = WKDataGetSize(wkData); + return static_cast<guchar*>(g_memdup(WKDataGetBytes(wkData), WKDataGetSize(wkData))); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h new file mode 100644 index 000000000..34af76e2b --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitWebResource_h +#define WebKitWebResource_h + +#include <glib-object.h> +#include <gio/gio.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitURIResponse.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_RESOURCE (webkit_web_resource_get_type()) +#define WEBKIT_WEB_RESOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResource)) +#define WEBKIT_IS_WEB_RESOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_RESOURCE)) +#define WEBKIT_WEB_RESOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResourceClass)) +#define WEBKIT_IS_WEB_RESOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_RESOURCE)) +#define WEBKIT_WEB_RESOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_RESOURCE, WebKitWebResourceClass)) + +typedef struct _WebKitWebResource WebKitWebResource; +typedef struct _WebKitWebResourceClass WebKitWebResourceClass; +typedef struct _WebKitWebResourcePrivate WebKitWebResourcePrivate; + +struct _WebKitWebResource { + GObject parent; + + WebKitWebResourcePrivate *priv; +}; + +struct _WebKitWebResourceClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_web_resource_get_type (void); + +WEBKIT_API const gchar * +webkit_web_resource_get_uri (WebKitWebResource *resource); + +WEBKIT_API WebKitURIResponse * +webkit_web_resource_get_response (WebKitWebResource *resource); + +WEBKIT_API void +webkit_web_resource_get_data (WebKitWebResource *resource, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API guchar * +webkit_web_resource_get_data_finish (WebKitWebResource *resource, + GAsyncResult *result, + gsize *length, + GError **error); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h new file mode 100644 index 000000000..5011ae4dd --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitWebResourcePrivate_h +#define WebKitWebResourcePrivate_h + +#include "WebKitPrivate.h" +#include "WebKitWebResource.h" + +WebKitWebResource* webkitWebResourceCreate(WKFrameRef, WebKitURIRequest*, bool isMainResource); +void webkitWebResourceSentRequest(WebKitWebResource*, WebKitURIRequest*, WebKitURIResponse*); +void webkitWebResourceSetResponse(WebKitWebResource*, WebKitURIResponse*); +void webkitWebResourceNotifyProgress(WebKitWebResource*, guint64 bytesReceived); +void webkitWebResourceFinished(WebKitWebResource*); +void webkitWebResourceFailed(WebKitWebResource*, GError*); + + +#endif // WebKitWebResourcePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index 4f17d4669..56b21df49 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -24,20 +24,25 @@ #include "WebKitBackForwardListPrivate.h" #include "WebKitEnumTypes.h" #include "WebKitError.h" +#include "WebKitFullscreenClient.h" #include "WebKitHitTestResultPrivate.h" +#include "WebKitJavascriptResultPrivate.h" #include "WebKitLoaderClient.h" #include "WebKitMarshal.h" #include "WebKitPolicyClient.h" #include "WebKitPrintOperationPrivate.h" #include "WebKitPrivate.h" +#include "WebKitResourceLoadClient.h" #include "WebKitScriptDialogPrivate.h" #include "WebKitSettingsPrivate.h" #include "WebKitUIClient.h" #include "WebKitWebContextPrivate.h" +#include "WebKitWebResourcePrivate.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" #include "WebKitWindowPropertiesPrivate.h" #include "WebPageProxy.h" +#include <JavaScriptCore/APICast.h> #include <WebCore/DragIcon.h> #include <WebCore/GtkUtilities.h> #include <glib/gi18n-lib.h> @@ -64,6 +69,13 @@ enum { PRINT_REQUESTED, + RESOURCE_LOAD_STARTED, + + ENTER_FULLSCREEN, + LEAVE_FULLSCREEN, + + RUN_FILE_CHOOSER, + LAST_SIGNAL }; @@ -84,6 +96,9 @@ typedef enum { DidReplaceContent } ReplaceContentStatus; +typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap; +typedef HashMap<String, GRefPtr<WebKitWebResource> > ResourcesMap; + struct _WebKitWebViewPrivate { WebKitWebContext* context; CString title; @@ -100,6 +115,11 @@ struct _WebKitWebViewPrivate { unsigned mouseTargetModifiers; GRefPtr<WebKitFindController> findController; + JSGlobalContextRef javascriptGlobalContext; + + GRefPtr<WebKitWebResource> mainResource; + LoadingResourcesMap loadingResourcesMap; + ResourcesMap subresourcesMap; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -188,6 +208,49 @@ static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* set g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView); } +static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request) +{ + GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request); + if (responseID == GTK_RESPONSE_ACCEPT) { + GOwnPtr<GSList> filesList(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog))); + GRefPtr<GPtrArray> filesArray = adoptGRef(g_ptr_array_new()); + for (GSList* file = filesList.get(); file; file = g_slist_next(file)) + g_ptr_array_add(filesArray.get(), file->data); + g_ptr_array_add(filesArray.get(), 0); + webkit_file_chooser_request_select_files(adoptedRequest.get(), reinterpret_cast<const gchar* const*>(filesArray->pdata)); + } else + webkit_file_chooser_request_cancel(adoptedRequest.get()); + + gtk_widget_destroy(GTK_WIDGET(dialog)); +} + +static gboolean webkitWebViewRunFileChooser(WebKitWebView* webView, WebKitFileChooserRequest* request) +{ + GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(webView)); + if (!widgetIsOnscreenToplevelWindow(toplevel)) + toplevel = 0; + + gboolean allowsMultipleSelection = webkit_file_chooser_request_get_select_multiple(request); + GtkWidget* dialog = gtk_file_chooser_dialog_new(allowsMultipleSelection ? _("Select Files") : _("Select File"), + toplevel ? GTK_WINDOW(toplevel) : 0, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request)) + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), allowsMultipleSelection); + + if (const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request)) + gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), selectedFiles[0]); + + g_signal_connect(dialog, "response", G_CALLBACK(fileChooserDialogResponseCallback), g_object_ref(request)); + gtk_widget_show(dialog); + + return TRUE; +} + static void webkitWebViewConstructed(GObject* object) { if (G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed) @@ -202,6 +265,8 @@ static void webkitWebViewConstructed(GObject* object) attachLoaderClientToView(webView); attachUIClientToView(webView); attachPolicyClientToPage(webView); + attachResourceLoadClientToView(webView); + attachFullScreenClientToView(webView); WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page)))); @@ -255,7 +320,10 @@ static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* valu static void webkitWebViewFinalize(GObject* object) { - WEBKIT_WEB_VIEW(object)->priv->~WebKitWebViewPrivate(); + WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(object)->priv; + if (priv->javascriptGlobalContext) + JSGlobalContextRelease(priv->javascriptGlobalContext); + priv->~WebKitWebViewPrivate(); G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object); } @@ -290,6 +358,7 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webViewClass->create = webkitWebViewCreate; webViewClass->script_dialog = webkitWebViewScriptDialog; webViewClass->decide_policy = webkitWebViewDecidePolicy; + webViewClass->run_file_chooser = webkitWebViewRunFileChooser; g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate)); @@ -666,6 +735,104 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) webkit_marshal_BOOLEAN__OBJECT, G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_PRINT_OPERATION); + + /** + * WebKitWebView::resource-load-started: + * @web_view: the #WebKitWebView on which the signal is emitted + * @resource: a #WebKitWebResource + * @request: a #WebKitURIRequest + * + * Emitted when a new resource is going to be loaded. The @request parameter + * contains the #WebKitURIRequest that will be sent to the server. + * You can monitor the load operation by connecting to the different signals + * of @resource. + */ + signals[RESOURCE_LOAD_STARTED] = + g_signal_new("resource-load-started", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, resource_load_started), + 0, 0, + webkit_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, + WEBKIT_TYPE_WEB_RESOURCE, + WEBKIT_TYPE_URI_REQUEST); + + /** + * WebKitWebView::enter-fullscreen: + * @web_view: the #WebKitWebView on which the signal is emitted. + * + * Emitted when JavaScript code calls + * <function>element.webkitRequestFullScreen</function>. If the + * signal is not handled the #WebKitWebView will proceed to full screen + * its top level window. This signal can be used by client code to + * request permission to the user prior doing the full screen + * transition and eventually prepare the top-level window + * (e.g. hide some widgets that would otherwise be part of the + * full screen window). + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to continue emission of the event. + */ + signals[ENTER_FULLSCREEN] = + g_signal_new("enter-fullscreen", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, enter_fullscreen), + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitWebView::leave-fullscreen: + * @web_view: the #WebKitWebView on which the signal is emitted. + * + * Emitted when the #WebKitWebView is about to restore its top level + * window out of its full screen state. This signal can be used by + * client code to restore widgets hidden during the + * #WebKitWebView::enter-fullscreen stage for instance. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to continue emission of the event. + */ + signals[LEAVE_FULLSCREEN] = + g_signal_new("leave-fullscreen", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, leave_fullscreen), + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + /** + * WebKitWebView::run-file-chooser: + * @web_view: the #WebKitWebView on which the signal is emitted + * @request: a #WebKitFileChooserRequest + * + * This signal is emitted when the user interacts with a <input + * type='file' /> HTML element, requesting from WebKit to show + * a dialog to select one or more files to be uploaded. To let the + * application know the details of the file chooser, as well as to + * allow the client application to either cancel the request or + * perform an actual selection of files, the signal will pass an + * instance of the #WebKitFileChooserRequest in the @request + * argument. + * + * The default signal handler will asynchronously run a regular + * #GtkFileChooserDialog for the user to interact with. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + * + */ + signals[RUN_FILE_CHOOSER] = + g_signal_new("run-file-chooser", + G_TYPE_FROM_CLASS(webViewClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser), + g_signal_accumulator_true_handled, 0 /* accumulator data */, + webkit_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, /* number of parameters */ + WEBKIT_TYPE_FILE_CHOOSER_REQUEST); } static bool updateReplaceContentStatus(WebKitWebView* webView, WebKitLoadEvent loadEvent) @@ -689,6 +856,12 @@ static bool updateReplaceContentStatus(WebKitWebView* webView, WebKitLoadEvent l void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent) { + if (loadEvent == WEBKIT_LOAD_STARTED) { + webView->priv->loadingResourcesMap.clear(); + webView->priv->mainResource = 0; + } else if (loadEvent == WEBKIT_LOAD_COMMITTED) + webView->priv->subresourcesMap.clear(); + if (updateReplaceContentStatus(webView, loadEvent)) return; @@ -822,6 +995,77 @@ void webkitWebViewPrintFrame(WebKitWebView* webView, WKFrameRef wkFrame) g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0); } +static inline bool webkitWebViewIsReplacingContentOrDidReplaceContent(WebKitWebView* webView) +{ + return (webView->priv->replaceContentStatus == ReplacingContent || webView->priv->replaceContentStatus == DidReplaceContent); +} + +void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request, bool isMainResource) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return; + + WebKitWebViewPrivate* priv = webView->priv; + WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource); + if (WKFrameIsMainFrame(wkFrame) && isMainResource) + priv->mainResource = resource; + priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource)); + g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request); +} + +WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return 0; + + GRefPtr<WebKitWebResource> resource = webView->priv->loadingResourcesMap.get(resourceIdentifier); + ASSERT(resource.get()); + return resource.get(); +} + +void webkitWebViewRemoveLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return; + + WebKitWebViewPrivate* priv = webView->priv; + ASSERT(priv->loadingResourcesMap.contains(resourceIdentifier)); + priv->loadingResourcesMap.remove(resourceIdentifier); +} + +WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView* webView, uint64_t resourceIdentifier) +{ + if (webkitWebViewIsReplacingContentOrDidReplaceContent(webView)) + return 0; + + WebKitWebViewPrivate* priv = webView->priv; + WebKitWebResource* resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier); + if (resource != priv->mainResource) + priv->subresourcesMap.set(String::fromUTF8(webkit_web_resource_get_uri(resource)), resource); + webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier); + return resource; +} + +bool webkitWebViewEnterFullScreen(WebKitWebView* webView) +{ + gboolean returnValue; + g_signal_emit(webView, signals[ENTER_FULLSCREEN], 0, &returnValue); + return !returnValue; +} + +bool webkitWebViewLeaveFullScreen(WebKitWebView* webView) +{ + gboolean returnValue; + g_signal_emit(webView, signals[LEAVE_FULLSCREEN], 0, &returnValue); + return !returnValue; +} + +void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChooserRequest* request) +{ + gboolean returnValue; + g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue); +} + /** * webkit_web_view_new: * @@ -1466,3 +1710,179 @@ WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView return webView->priv->findController.get(); } + +/** + * webkit_web_view_get_javascript_global_context: + * @web_view: a #WebKitWebView + * + * Get the global JavaScript context used by @web_view to deserialize the + * result values of scripts executed with webkit_web_view_run_javascript(). + * + * Returns: the <function>JSGlobalContextRef</function> used by @web_view to deserialize + * the result values of scripts. + */ +JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + if (!webView->priv->javascriptGlobalContext) + webView->priv->javascriptGlobalContext = JSGlobalContextCreate(0); + return webView->priv->javascriptGlobalContext; +} + +static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSerializedScriptValue, WKErrorRef, void* context) +{ + GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); + if (wkSerializedScriptValue) { + GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get())))); + WebKitJavascriptResult* scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue); + g_simple_async_result_set_op_res_gpointer(result.get(), scriptResult, reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref)); + } else { + GError* error = 0; + g_set_error_literal(&error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED, _("An exception was raised in JavaScript")); + g_simple_async_result_take_error(result.get(), error); + } + g_simple_async_result_complete(result.get()); +} + +/** + * webkit_web_view_run_javascript: + * @web_view: a #WebKitWebView + * @script: the script to run + * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished + * @user_data: (closure): the data to pass to callback function + * + * Asynchronously run @script in the context of the current page in @web_view. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_web_view_run_javascript_finish() to get the result of the operation. + */ +void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); + g_return_if_fail(script); + + WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))); + WKRetainPtr<WKStringRef> wkScript = adoptWK(WKStringCreateWithUTF8CString(script)); + GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData, + reinterpret_cast<gpointer>(webkit_web_view_run_javascript)); + WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback); +} + +/** + * webkit_web_view_run_javascript_finish: + * @web_view: a #WebKitWebView + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_web_view_run_javascript(). + * + * This is an example of using webkit_web_view_run_javascript() with a script returning + * a string: + * + * <informalexample><programlisting> + * static void + * web_view_javascript_finished (GObject *object, + * GAsyncResult *result, + * gpointer user_data) + * { + * WebKitJavascriptResult *js_result; + * JSValueRef value; + * JSGlobalContextRef context; + * GError *error = NULL; + * + * js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error); + * if (!js_result) { + * g_warning ("Error running javascript: %s", error->message); + * g_error_free (error); + * return; + * } + * + * context = webkit_javascript_result_get_global_context (js_result); + * value = webkit_javascript_result_get_value (js_result); + * if (JSValueIsString (context, value)) { + * JSStringRef *js_str_value; + * gchar *str_value; + * gsize str_length; + * + * js_str_value = JSValueToStringCopy (context, value, NULL)); + * str_length = JSStringGetMaximumUTF8CStringSize (js_str_value); + * str_value = (gchar *)g_malloc (str_length)); + * JSStringGetUTF8CString (js_str_value, str_value, str_length); + * JSStringRelease (js_str_value); + * g_print ("Script result: %s\n", str_value); + * g_free (str_value); + * } else { + * g_warning ("Error running javascript: unexpected return value"); + * } + * webkit_javascript_result_unref (js_result); + * } + * + * static void + * web_view_get_link_url (WebKitWebView *web_view, + * const gchar *link_id) + * { + * gchar *script; + * + * script = g_strdup_printf ("window.document.getElementById('%s').href;", link_id); + * webkit_web_view_run_javascript (web_view, script, web_view_javascript_finished, NULL); + * g_free (script); + * } + * </programlisting></informalexample> + * + * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script + * or %NULL in case of error + */ +WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_view_run_javascript); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + WebKitJavascriptResult* scriptResult = static_cast<WebKitJavascriptResult*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return scriptResult ? webkit_javascript_result_ref(scriptResult) : 0; +} + +/** + * webkit_web_view_get_main_resource: + * @web_view: a #WebKitWebView + * + * Return the main resource of @web_view. + * See also webkit_web_view_get_subresources(): + * + * Returns: (transfer none): the main #WebKitWebResource of the view + * or %NULL if nothing has been loaded. + */ +WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + return webView->priv->mainResource.get(); +} + +/** + * webkit_web_view_get_subresources: + * @web_view: a #WebKitWebView + * + * Return the list of subresources of @web_view. + * See also webkit_web_view_get_main_resource(). + * + * Returns: (element-type WebKitWebResource) (transfer container): a list of #WebKitWebResource. + */ +GList* webkit_web_view_get_subresources(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + GList* subresources = 0; + WebKitWebViewPrivate* priv = webView->priv; + ResourcesMap::const_iterator end = priv->subresourcesMap.end(); + for (ResourcesMap::const_iterator it = priv->subresourcesMap.begin(); it != end; ++it) + subresources = g_list_prepend(subresources, it->second.get()); + + return g_list_reverse(subresources); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h index fb4c48a2d..c56205b96 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h @@ -28,17 +28,21 @@ #ifndef WebKitWebView_h #define WebKitWebView_h +#include <JavaScriptCore/JSBase.h> #include <webkit2/WebKitBackForwardList.h> #include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitFileChooserRequest.h> #include <webkit2/WebKitFindController.h> #include <webkit2/WebKitHitTestResult.h> +#include <webkit2/WebKitJavascriptResult.h> +#include <webkit2/WebKitPolicyDecision.h> #include <webkit2/WebKitScriptDialog.h> #include <webkit2/WebKitSettings.h> #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitWebContext.h> +#include <webkit2/WebKitWebResource.h> #include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> -#include <webkit2/WebKitPolicyDecision.h> G_BEGIN_DECLS @@ -121,28 +125,35 @@ struct _WebKitWebView { struct _WebKitWebViewClass { WebKitWebViewBaseClass parent; - void (* load_changed) (WebKitWebView *web_view, - WebKitLoadEvent load_event); - gboolean (* load_failed) (WebKitWebView *web_view, - WebKitLoadEvent load_event, - const gchar *failing_uri, - GError *error); - - GtkWidget *(* create) (WebKitWebView *web_view); - void (* ready_to_show) (WebKitWebView *web_view); - void (* close) (WebKitWebView *web_view); - - gboolean (* script_dialog) (WebKitWebView *web_view, - WebKitScriptDialog *dialog); - - gboolean (* decide_policy) (WebKitWebView *web_view, - WebKitPolicyDecision *decision, - WebKitPolicyDecisionType type); - void (* mouse_target_changed) (WebKitWebView *web_view, - WebKitHitTestResult *hit_test_result, - guint modifiers); - gboolean (* print_requested) (WebKitWebView *web_view, - WebKitPrintOperation *print_operation); + void (* load_changed) (WebKitWebView *web_view, + WebKitLoadEvent load_event); + gboolean (* load_failed) (WebKitWebView *web_view, + WebKitLoadEvent load_event, + const gchar *failing_uri, + GError *error); + + GtkWidget *(* create) (WebKitWebView *web_view); + void (* ready_to_show) (WebKitWebView *web_view); + void (* close) (WebKitWebView *web_view); + + gboolean (* script_dialog) (WebKitWebView *web_view, + WebKitScriptDialog *dialog); + + gboolean (* decide_policy) (WebKitWebView *web_view, + WebKitPolicyDecision *decision, + WebKitPolicyDecisionType type); + void (* mouse_target_changed) (WebKitWebView *web_view, + WebKitHitTestResult *hit_test_result, + guint modifiers); + gboolean (* print_requested) (WebKitWebView *web_view, + WebKitPrintOperation *print_operation); + void (* resource_load_started) (WebKitWebView *web_view, + WebKitWebResource *resource, + WebKitURIRequest *request); + gboolean (* enter_fullscreen) (WebKitWebView *web_view); + gboolean (* leave_fullscreen) (WebKitWebView *web_view); + gboolean (* run_file_chooser) (WebKitWebView *web_view, + WebKitFileChooserRequest *request); /* Padding for future expansion */ void (*_webkit_reserved0) (void); @@ -267,6 +278,24 @@ webkit_web_view_execute_editing_command (WebKitWebView *w WEBKIT_API WebKitFindController * webkit_web_view_get_find_controller (WebKitWebView *web_view); +WEBKIT_API JSGlobalContextRef +webkit_web_view_get_javascript_global_context (WebKitWebView *web_view); + +WEBKIT_API void +webkit_web_view_run_javascript (WebKitWebView *web_view, + const gchar *script, + GAsyncReadyCallback callback, + gpointer user_data); +WEBKIT_API WebKitJavascriptResult * +webkit_web_view_run_javascript_finish (WebKitWebView *web_view, + GAsyncResult *result, + GError **error); + +WEBKIT_API WebKitWebResource * +webkit_web_view_get_main_resource (WebKitWebView *web_view); + +WEBKIT_API GList * +webkit_web_view_get_subresources (WebKitWebView *web_view); G_END_DECLS #endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp index adcc34ae3..b2cdde564 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -35,6 +35,7 @@ #include "PageClientImpl.h" #include "WebContext.h" #include "WebEventFactory.h" +#include "WebFullScreenClientGtk.h" #include "WebKitPrivate.h" #include "WebKitWebViewBaseAccessible.h" #include "WebKitWebViewBasePrivate.h" @@ -52,14 +53,24 @@ #include <WebCore/PasteboardHelper.h> #include <WebCore/RefPtrCairo.h> #include <WebCore/Region.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> +#include <wtf/HashMap.h> #include <wtf/gobject/GOwnPtr.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> +#if ENABLE(FULLSCREEN_API) +#include "WebFullScreenManagerProxy.h" +#endif + using namespace WebKit; using namespace WebCore; +typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap; + struct _WebKitWebViewBasePrivate { + WebKitWebViewChildrenMap children; OwnPtr<PageClientImpl> pageClient; RefPtr<WebPageProxy> pageProxy; bool isPageActive; @@ -72,6 +83,10 @@ struct _WebKitWebViewBasePrivate { IntSize resizerSize; GRefPtr<AtkObject> accessible; bool needsResizeOnMap; +#if ENABLE(FULLSCREEN_API) + bool fullScreenModeActive; + WebFullScreenClientGtk fullScreenClient; +#endif }; G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER) @@ -152,9 +167,53 @@ static void webkitWebViewBaseRealize(GtkWidget* widget) static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget) { + WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); + WebKitWebViewBasePrivate* priv = webView->priv; + + GtkAllocation childAllocation; + gtk_widget_get_allocation(widget, &childAllocation); + priv->children.set(widget, childAllocation); + gtk_widget_set_parent(widget, GTK_WIDGET(container)); } +static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget) +{ + WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); + WebKitWebViewBasePrivate* priv = webView->priv; + GtkWidget* widgetContainer = GTK_WIDGET(container); + + ASSERT(priv->children.contains(widget)); + gboolean wasVisible = gtk_widget_get_visible(widget); + gtk_widget_unparent(widget); + + priv->children.remove(widget); + if (wasVisible && gtk_widget_get_visible(widgetContainer)) + gtk_widget_queue_resize(widgetContainer); +} + +static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData) +{ + WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); + WebKitWebViewBasePrivate* priv = webView->priv; + + WebKitWebViewChildrenMap children = priv->children; + WebKitWebViewChildrenMap::const_iterator end = children.end(); + for (WebKitWebViewChildrenMap::const_iterator current = children.begin(); current != end; ++current) + (*callback)(current->first, callbackData); +} + +void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect) +{ + const IntRect& geometry = webView->priv->children.get(child); + + if (geometry == childRect) + return; + + webView->priv->children.set(child, childRect); + gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView)); +} + static void webkitWebViewBaseFinalize(GObject* gobject) { WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(gobject); @@ -203,10 +262,27 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr) return FALSE; } -static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation) +static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData) { + if (!gtk_widget_get_visible(child)) + return; + + WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData); WebKitWebViewBasePrivate* priv = webViewBase->priv; + const IntRect& geometry = priv->children.get(child); + if (geometry.isEmpty()) + return; + + GtkAllocation childAllocation = geometry; + gtk_widget_size_allocate(child, &childAllocation); + priv->children.set(child, IntRect()); +} + +static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation) +{ + gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase); + WebKitWebViewBasePrivate* priv = webViewBase->priv; if (priv->pageProxy->drawingArea()) priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize()); @@ -239,7 +315,6 @@ static void webkitWebViewBaseMap(GtkWidget* widget) gtk_widget_get_allocation(widget, &allocation); resizeWebKitWebViewBaseFromAllocation(webViewBase, &allocation); webViewBase->priv->needsResizeOnMap = false; - } static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event) @@ -277,6 +352,20 @@ static gboolean webkitWebViewBaseKeyPressEvent(GtkWidget* widget, GdkEventKey* e WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget); WebKitWebViewBasePrivate* priv = webViewBase->priv; +#if ENABLE(FULLSCREEN_API) + if (priv->fullScreenModeActive) { + switch (event->keyval) { + case GDK_KEY_Escape: + case GDK_KEY_f: + case GDK_KEY_F: + webkitWebViewBaseExitFullScreen(webViewBase); + return TRUE; + default: + break; + } + } +#endif + // Since WebProcess key event handling is not synchronous, handle the event in two passes. // When WebProcess processes the input event, it will call PageClientImpl::doneWithKeyEvent // with event handled status which determines whether to pass the input event to parent or not @@ -467,7 +556,8 @@ static gboolean webkitWebViewBaseDragDrop(GtkWidget* widget, GdkDragContext* con return FALSE; SandboxExtension::Handle handle; - webViewBase->priv->pageProxy->performDrag(dragData.get(), String(), handle); + SandboxExtension::HandleArray sandboxExtensionForUpload; + webViewBase->priv->pageProxy->performDrag(dragData.get(), String(), handle, sandboxExtensionForUpload); gtk_drag_finish(context, TRUE, FALSE, time); return TRUE; } @@ -501,6 +591,8 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass); containerClass->add = webkitWebViewBaseContainerAdd; + containerClass->remove = webkitWebViewBaseContainerRemove; + containerClass->forall = webkitWebViewBaseContainerForall; g_type_class_add_private(webkitWebViewBaseClass, sizeof(WebKitWebViewBasePrivate)); } @@ -528,6 +620,10 @@ void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, WKCont priv->pageProxy = toImpl(context)->createWebPage(priv->pageClient.get(), toImpl(pageGroup)); priv->pageProxy->initializeWebPage(); + +#if ENABLE(FULLSCREEN_API) + priv->pageProxy->fullScreenManager()->setWebView(webkitWebViewBase); +#endif } void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char* tooltip) @@ -575,3 +671,50 @@ void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase* webkitWebViewBase) { webkitWebViewBase->priv->shouldForwardNextKeyEvent = TRUE; } + +void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase* webkitWebViewBase) +{ +#if ENABLE(FULLSCREEN_API) + WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv; + if (priv->fullScreenModeActive) + return; + + if (!priv->fullScreenClient.willEnterFullScreen()) + return; + + WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager(); + fullScreenManagerProxy->willEnterFullScreen(); + + GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase)); + if (gtk_widget_is_toplevel(topLevelWindow)) + gtk_window_fullscreen(GTK_WINDOW(topLevelWindow)); + fullScreenManagerProxy->didEnterFullScreen(); + priv->fullScreenModeActive = true; +#endif +} + +void webkitWebViewBaseExitFullScreen(WebKitWebViewBase* webkitWebViewBase) +{ +#if ENABLE(FULLSCREEN_API) + WebKitWebViewBasePrivate* priv = webkitWebViewBase->priv; + if (!priv->fullScreenModeActive) + return; + + if (!priv->fullScreenClient.willExitFullScreen()) + return; + + WebFullScreenManagerProxy* fullScreenManagerProxy = priv->pageProxy->fullScreenManager(); + fullScreenManagerProxy->willExitFullScreen(); + + GtkWidget* topLevelWindow = gtk_widget_get_toplevel(GTK_WIDGET(webkitWebViewBase)); + if (gtk_widget_is_toplevel(topLevelWindow)) + gtk_window_unfullscreen(GTK_WINDOW(topLevelWindow)); + fullScreenManagerProxy->didExitFullScreen(); + priv->fullScreenModeActive = false; +#endif +} + +void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase* webkitWebViewBase, const WKFullScreenClientGtk* wkClient) +{ + webkitWebViewBase->priv->fullScreenClient.initialize(wkClient); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h index 3a9a40b86..cd4c1a1b5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h @@ -28,28 +28,22 @@ #ifndef WebKitWebViewBasePrivate_h #define WebKitWebViewBasePrivate_h +#include "WebKitPrivate.h" #include "WebKitWebViewBase.h" #include "WebPageProxy.h" -#include <WebKit2/WebKit2.h> using namespace WebKit; -G_BEGIN_DECLS - WebKitWebViewBase* webkitWebViewBaseCreate(WebContext*, WebPageGroup*); - GtkIMContext* webkitWebViewBaseGetIMContext(WebKitWebViewBase*); - WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase*); - void webkitWebViewBaseCreateWebPage(WebKitWebViewBase*, WKContextRef, WKPageGroupRef); - void webkitWebViewBaseSetTooltipText(WebKitWebViewBase*, const char*); - void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase*); - void webkitWebViewBaseStartDrag(WebKitWebViewBase*, const WebCore::DragData&, PassRefPtr<ShareableBitmap> dragImage); - -G_END_DECLS +void webkitWebViewBaseChildMoveResize(WebKitWebViewBase*, GtkWidget*, const WebCore::IntRect&); +void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase*); +void webkitWebViewBaseExitFullScreen(WebKitWebViewBase*); +void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase*, const WKFullScreenClientGtk*); #endif // WebKitWebViewBasePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h index ad8ab2038..717d2c344 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h @@ -45,5 +45,12 @@ WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& mess void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); void webkitWebViewMouseTargetChanged(WebKitWebView*, WKHitTestResultRef, unsigned modifiers); void webkitWebViewPrintFrame(WebKitWebView*, WKFrameRef); +void webkitWebViewResourceLoadStarted(WebKitWebView*, WKFrameRef, uint64_t resourceIdentifier, WebKitURIRequest*, bool isMainResource); +void webkitWebViewRunFileChooserRequest(WebKitWebView*, WebKitFileChooserRequest*); +WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); +void webkitWebViewRemoveLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier); +WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView*, uint64_t resourceIdentifier); +bool webkitWebViewEnterFullScreen(WebKitWebView*); +bool webkitWebViewLeaveFullScreen(WebKitWebView*); #endif // WebKitWebViewPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index 4a9cc798c..821127f3d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -26,8 +26,11 @@ <xi:include href="xml/WebKitResponsePolicyDecision.xml"/> <xi:include href="xml/WebKitHitTestResult.xml"/> <xi:include href="xml/WebKitPrintOperation.xml"/> + <xi:include href="xml/WebKitWebResource.xml"/> <xi:include href="xml/WebKitError.xml"/> + <xi:include href="xml/WebKitFileChooserRequest.xml"/> <xi:include href="xml/WebKitFindController.xml"/> + <xi:include href="xml/WebKitCookieManager.xml"/> </chapter> <index id="index-all"> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt index a8f54083a..dc5e65ac6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -28,6 +28,7 @@ webkit_web_context_get_default webkit_web_context_get_cache_model webkit_web_context_set_cache_model webkit_web_context_download_uri +webkit_web_context_get_cookie_manager <SUBSECTION Standard> WebKitWebContextClass @@ -49,8 +50,6 @@ webkit_web_context_get_type WebKitWebView WebKitLoadEvent WebKitPolicyDecisionType -WebKitScriptDialog -WebKitScriptDialogType <SUBSECTION Editing Commands> WEBKIT_EDITING_COMMAND_CUT @@ -89,11 +88,27 @@ webkit_web_view_can_execute_editing_command webkit_web_view_can_execute_editing_command_finish webkit_web_view_execute_editing_command webkit_web_view_get_find_controller +webkit_web_view_get_javascript_global_context +webkit_web_view_run_javascript +webkit_web_view_run_javascript_finish + +<SUBSECTION WebKitJavascriptResult> +WebKitJavascriptResult +webkit_javascript_result_ref +webkit_javascript_result_unref +webkit_javascript_result_get_global_context +webkit_javascript_result_get_value + +<SUBSECTION WebKitScriptDialog> +WebKitScriptDialog +WebKitScriptDialogType webkit_script_dialog_get_dialog_type webkit_script_dialog_get_message webkit_script_dialog_confirm_set_confirmed webkit_script_dialog_prompt_get_default_text webkit_script_dialog_prompt_set_text +webkit_web_view_get_main_resource +webkit_web_view_get_subresources <SUBSECTION Standard> WebKitWebViewClass @@ -103,10 +118,12 @@ WEBKIT_TYPE_WEB_VIEW WEBKIT_WEB_VIEW_CLASS WEBKIT_IS_WEB_VIEW_CLASS WEBKIT_WEB_VIEW_GET_CLASS +WEBKIT_TYPE_JAVASCRIPT_RESULT WEBKIT_TYPE_SCRIPT_DIALOG <SUBSECTION Private> webkit_web_view_get_type +webkit_javascript_result_get_type webkit_script_dialog_get_type WebKitWebViewPrivate </SECTION> @@ -232,6 +249,8 @@ webkit_settings_get_enable_webgl webkit_settings_set_enable_webgl webkit_settings_get_zoom_text_only webkit_settings_set_zoom_text_only +webkit_settings_get_javascript_can_access_clipboard +webkit_settings_set_javascript_can_access_clipboard <SUBSECTION Standard> WebKitSettingsClass @@ -458,19 +477,71 @@ webkit_print_operation_get_type </SECTION> <SECTION> +<FILE>WebKitWebResource</FILE> +WebKitWebResource +webkit_web_resource_get_uri +webkit_web_resource_get_response +webkit_web_resource_get_data +webkit_web_resource_get_data_finish + +<SUBSECTION Standard> +WebKitWebResourceClass +WEBKIT_TYPE_WEB_RESOURCE +WEBKIT_WEB_RESOURCE +WEBKIT_IS_WEB_RESOURCE +WEBKIT_WEB_RESOURCE_CLASS +WEBKIT_IS_WEB_RESOURCE_CLASS +WEBKIT_WEB_RESOURCE_GET_CLASS + +<SUBSECTION Private> +WebKitWebResourcePrivate +webkit_web_resource_get_type +</SECTION> + +<SECTION> <FILE>WebKitError</FILE> WEBKIT_NETWORK_ERROR WEBKIT_PLUGIN_ERROR WEBKIT_POLICY_ERROR WEBKIT_DOWNLOAD_ERROR +WEBKIT_PRINT_ERROR +WEBKIT_JAVASCRIPT_ERROR WebKitNetworkError WebKitPluginError WebKitPolicyError WebKitDownloadError +WebKitPrintError +WebKitJavascriptError webkit_network_error_quark webkit_plugin_error_quark webkit_policy_error_quark webkit_download_error_quark +webkit_print_error_quark +webkit_javascript_error_quark +</SECTION> + +<SECTION> +<FILE>WebKitFileChooserRequest</FILE> +WebKitFileChooserRequest +webkit_file_chooser_request_get_mime_types +webkit_file_chooser_request_get_mime_types_filter +webkit_file_chooser_request_get_select_multiple +webkit_file_chooser_request_select_files +webkit_file_chooser_request_get_selected_files +webkit_file_chooser_request_cancel + +<SUBSECTION Standard> +WebKitFileChooserRequestClass +WEBKIT_TYPE_FILE_CHOOSER_REQUEST +WEBKIT_FILE_CHOOSER_REQUEST +WEBKIT_IS_FILE_CHOOSER_REQUEST +WEBKIT_FILE_CHOOSER_REQUEST_CLASS +WEBKIT_IS_FILE_CHOOSER_REQUEST_CLASS +WEBKIT_FILE_CHOOSER_REQUEST_GET_CLASS + +<SUBSECTION Private> +WebKitFileChooserRequestPrivate +webkit_file_chooser_request_get_type </SECTION> <SECTION> @@ -500,3 +571,29 @@ WEBKIT_FIND_CONTROLLER_GET_CLASS WebKitFindControllerPrivate webkit_find_controller_get_type </SECTION> + +<SECTION> +<FILE>WebKitCookieManager</FILE> +WebKitCookieManager +WebKitCookieAcceptPolicy +webkit_cookie_manager_set_accept_policy +webkit_cookie_manager_get_accept_policy +webkit_cookie_manager_get_accept_policy_finish +webkit_cookie_manager_get_domains_with_cookies +webkit_cookie_manager_get_domains_with_cookies_finish +webkit_cookie_manager_delete_cookies_for_domain +webkit_cookie_manager_delete_all_cookies + +<SUBSECTION Standard> +WebKitCookieManagerClass +WEBKIT_TYPE_COOKIE_MANAGER +WEBKIT_COOKIE_MANAGER +WEBKIT_IS_COOKIE_MANAGER +WEBKIT_COOKIE_MANAGER_CLASS +WEBKIT_IS_COOKIE_MANAGER_CLASS +WEBKIT_COOKIE_MANAGER_GET_CLASS + +<SUBSECTION Private> +WebKitCookieManagerPrivate +webkit_cookie_manager_get_type +</SECTION> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types index 8e8d7b13a..1ca821b47 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types @@ -9,5 +9,9 @@ webkit_uri_response_get_type webkit_uri_request_get_type webkit_window_properties_get_type webkit_download_get_type +webkit_file_chooser_request_get_type webkit_find_controller_get_type webkit_script_dialog_get_type +webkit_javascript_result_get_type +webkit_web_resource_get_type +webkit_cookie_manager_get_type diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index 6adb2d5cd..b389f4954 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -2,9 +2,11 @@ if ENABLE_WEBKIT2 TEST_PROGS += \ Programs/WebKit2APITests/TestBackForwardList \ + Programs/WebKit2APITests/TestCookieManager \ Programs/WebKit2APITests/TestDownloads \ Programs/WebKit2APITests/TestLoaderClient \ Programs/WebKit2APITests/TestPrinting \ + Programs/WebKit2APITests/TestResources \ Programs/WebKit2APITests/TestWebKitFindController \ Programs/WebKit2APITests/TestWebKitPolicyClient \ Programs/WebKit2APITests/TestWebKitSettings \ @@ -135,4 +137,16 @@ Programs_WebKit2APITests_TestWebKitFindController_CPPFLAGS = $(webkit2_tests_cpp Programs_WebKit2APITests_TestWebKitFindController_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestWebKitFindController_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestResources_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp +Programs_WebKit2APITests_TestResources_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestResources_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestResources_LDFLAGS = $(webkit2_tests_ldflags) + +Programs_WebKit2APITests_TestCookieManager_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp +Programs_WebKit2APITests_TestCookieManager_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestCookieManager_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestCookieManager_LDFLAGS = $(webkit2_tests_ldflags) + endif # ENABLE_WEBKIT2 diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp new file mode 100644 index 000000000..6d2ecf528 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "WebKitTestServer.h" +#include "WebViewTest.h" + +static WebKitTestServer* kServer; + +static const char* kFirstPartyDomain = "127.0.0.1"; +static const char* kThirdPartyDomain = "localhost"; +static const char* kIndexHtmlFormat = + "<html><body>" + " <p>WebKitGTK+ Cookie Manager test</p>" + " <img src='http://localhost:%u/image.png' width=5 height=5></img>" + "</body></html>"; + +class CookieManagerTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(CookieManagerTest); + + static void cookiesChangedCallback(WebKitCookieManager*, CookieManagerTest* test) + { + test->m_cookiesChanged = true; + if (test->m_finishLoopWhenCookiesChange) + g_main_loop_quit(test->m_mainLoop); + } + + CookieManagerTest() + : WebViewTest() + , m_cookieManager(webkit_web_context_get_cookie_manager(webkit_web_view_get_context(m_webView))) + , m_acceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY) + , m_domains(0) + , m_cookiesChanged(false) + , m_finishLoopWhenCookiesChange(false) + { + g_signal_connect(m_cookieManager, "changed", G_CALLBACK(cookiesChangedCallback), this); + } + + ~CookieManagerTest() + { + g_strfreev(m_domains); + g_signal_handlers_disconnect_matched(m_cookieManager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + } + + static void getAcceptPolicyReadyCallback(GObject* object, GAsyncResult* result, gpointer userData) + { + GOwnPtr<GError> error; + WebKitCookieAcceptPolicy policy = webkit_cookie_manager_get_accept_policy_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr()); + g_assert(!error.get()); + + CookieManagerTest* test = static_cast<CookieManagerTest*>(userData); + test->m_acceptPolicy = policy; + g_main_loop_quit(test->m_mainLoop); + } + + WebKitCookieAcceptPolicy getAcceptPolicy() + { + m_acceptPolicy = WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY; + webkit_cookie_manager_get_accept_policy(m_cookieManager, getAcceptPolicyReadyCallback, this); + g_main_loop_run(m_mainLoop); + + return m_acceptPolicy; + } + + void setAcceptPolicy(WebKitCookieAcceptPolicy policy) + { + webkit_cookie_manager_set_accept_policy(m_cookieManager, policy); + } + + static void getDomainsReadyCallback(GObject* object, GAsyncResult* result, gpointer userData) + { + GOwnPtr<GError> error; + char** domains = webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr()); + g_assert(!error.get()); + + CookieManagerTest* test = static_cast<CookieManagerTest*>(userData); + test->m_domains = domains; + g_main_loop_quit(test->m_mainLoop); + } + + char** getDomains() + { + g_strfreev(m_domains); + m_domains = 0; + webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, getDomainsReadyCallback, this); + g_main_loop_run(m_mainLoop); + + return m_domains; + } + + void deleteCookiesForDomain(const char* domain) + { + webkit_cookie_manager_delete_cookies_for_domain(m_cookieManager, domain); + } + + void deleteAllCookies() + { + webkit_cookie_manager_delete_all_cookies(m_cookieManager); + } + + void waitUntilCookiesChanged() + { + m_cookiesChanged = false; + m_finishLoopWhenCookiesChange = true; + g_main_loop_run(m_mainLoop); + m_finishLoopWhenCookiesChange = false; + } + + WebKitCookieManager* m_cookieManager; + WebKitCookieAcceptPolicy m_acceptPolicy; + char** m_domains; + bool m_cookiesChanged; + bool m_finishLoopWhenCookiesChange; +}; + +static void testCookieManagerAcceptPolicy(CookieManagerTest* test, gconstpointer) +{ + // Default policy is NO_THIRD_PARTY. + g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + char** domains = test->getDomains(); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 1); + g_assert_cmpstr(domains[0], ==, kFirstPartyDomain); + test->deleteAllCookies(); + + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + domains = test->getDomains(); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 2); + g_assert_cmpstr(domains[0], ==, kFirstPartyDomain); + g_assert_cmpstr(domains[1], ==, kThirdPartyDomain); + test->deleteAllCookies(); + + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_NEVER); + g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NEVER); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + domains = test->getDomains(); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 0); +} + +static void testCookieManagerDeleteCookies(CookieManagerTest* test, gconstpointer) +{ + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2); + + // Delete first party cookies. + test->deleteCookiesForDomain(kFirstPartyDomain); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1); + + // Delete third party cookies. + test->deleteCookiesForDomain(kThirdPartyDomain); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0); + + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2); + + // Delete all cookies. + test->deleteAllCookies(); + g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0); +} + +static void testCookieManagerCookiesChanged(CookieManagerTest* test, gconstpointer) +{ + g_assert(!test->m_cookiesChanged); + test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); + test->loadURI(kServer->getURIForPath("/index.html").data()); + test->waitUntilLoadFinished(); + g_assert(test->m_cookiesChanged); + + test->deleteCookiesForDomain(kFirstPartyDomain); + test->waitUntilCookiesChanged(); + g_assert(test->m_cookiesChanged); + + test->deleteAllCookies(); + test->waitUntilCookiesChanged(); + g_assert(test->m_cookiesChanged); +} + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + if (g_str_equal(path, "/index.html")) { + char* indexHtml = g_strdup_printf(kIndexHtmlFormat, soup_server_get_port(server)); + soup_message_headers_replace(message->response_headers, "Set-Cookie", "foo=bar"); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, indexHtml, strlen(indexHtml)); + } else if (g_str_equal(path, "/image.png")) + soup_message_headers_replace(message->response_headers, "Set-Cookie", "baz=qux"); + else + g_assert_not_reached(); + soup_message_body_complete(message->response_body); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + CookieManagerTest::add("WebKitCookieManager", "accept-policy", testCookieManagerAcceptPolicy); + CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies); + CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged); +} + +void afterAll() +{ + delete kServer; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp index 461cefa0e..a119e4477 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestDownloads.cpp @@ -173,15 +173,9 @@ public: guint64 m_downloadSize; }; -static CString getWebKit1TestResoucesDir() -{ - GOwnPtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Source", "WebKit", "gtk", "tests", "resources", NULL)); - return resourcesDir.get(); -} - static void testDownloadLocalFile(DownloadTest* test, gconstpointer) { - GOwnPtr<char> sourcePath(g_build_filename(getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GOwnPtr<char> sourcePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get())); GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0)); GOwnPtr<char> sourceURI(g_file_get_uri(source.get())); @@ -258,7 +252,7 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; - GOwnPtr<char> path(g_build_filename(getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GOwnPtr<char> path(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get())); GOwnPtr<char> uri(g_file_get_uri(file.get())); download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get())); @@ -301,7 +295,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - GOwnPtr<char> filePath(g_build_filename(getWebKit1TestResoucesDir().data(), path, NULL)); + GOwnPtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL)); char* contents; gsize contentsLength; if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) { diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h index 39a2000ac..219cb44ed 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h @@ -20,9 +20,10 @@ #ifndef TestMain_h #define TestMain_h -#include <JavaScriptCore/GOwnPtr.h> -#include <JavaScriptCore/HashSet.h> #include <glib-object.h> +#include <wtf/HashSet.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/text/CString.h> #define MAKE_GLIB_TEST_FIXTURE(ClassName) \ static void setUp(ClassName* fixture, gconstpointer data) \ @@ -45,6 +46,15 @@ public: ~Test() { + if (m_watchedObjects.isEmpty()) + return; + + g_print("Leaked objects:"); + HashSet<GObject*>::const_iterator end = m_watchedObjects.end(); + for (HashSet<GObject*>::const_iterator it = m_watchedObjects.begin(); it != end; ++it) + g_print(" %s(%p)", g_type_name_from_instance(reinterpret_cast<GTypeInstance*>(*it)), *it); + g_print("\n"); + g_assert(m_watchedObjects.isEmpty()); } @@ -59,6 +69,12 @@ public: g_object_weak_ref(object, reinterpret_cast<GWeakNotify>(objectFinalized), this); } + static CString getWebKit1TestResoucesDir() + { + GOwnPtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Source", "WebKit", "gtk", "tests", "resources", NULL)); + return resourcesDir.get(); + } + HashSet<GObject*> m_watchedObjects; }; diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp index 1ddde0858..150c31bd3 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestPrinting.cpp @@ -72,37 +72,63 @@ static void testWebViewPrintRequested(WebViewTest* test, gconstpointer) } #ifdef HAVE_GTK_UNIX_PRINTING -static void testPrintOperationPrintLoadChanged(WebKitWebView*, WebKitLoadEvent loadEvent, WebViewTest* test) -{ - if (loadEvent != WEBKIT_LOAD_FINISHED) - return; - g_main_loop_quit(test->m_mainLoop); -} +class PrintTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(PrintTest); -static void testPrintOperationPrintFinished(WebKitPrintOperation* printOperation, WebViewTest* test) -{ - g_object_unref(printOperation); - g_main_loop_quit(test->m_mainLoop); -} + static void printFinishedCallback(WebKitPrintOperation*, PrintTest* test) + { + g_main_loop_quit(test->m_mainLoop); + } -static gboolean testPrintOperationPrintPrinter(GtkPrinter* printer, gpointer userData) -{ - if (strcmp(gtk_printer_get_name(printer), "Print to File")) - return FALSE; + static void printFailedCallback(WebKitPrintOperation*, GError* error, PrintTest* test) + { + g_assert(test->m_expectedError); + g_assert(error); + g_assert(g_error_matches(error, WEBKIT_PRINT_ERROR, test->m_expectedError)); + } - GtkPrinter** foundPrinter = static_cast<GtkPrinter**>(userData); - *foundPrinter = static_cast<GtkPrinter*>(g_object_ref(printer)); - return TRUE; -} + PrintTest() + : m_expectedError(0) + { + m_printOperation = adoptGRef(webkit_print_operation_new(m_webView)); + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_printOperation.get())); + g_signal_connect(m_printOperation.get(), "finished", G_CALLBACK(printFinishedCallback), this); + g_signal_connect(m_printOperation.get(), "failed", G_CALLBACK(printFailedCallback), this); + } + + static gboolean testPrintOperationPrintPrinter(GtkPrinter* printer, gpointer userData) + { + if (strcmp(gtk_printer_get_name(printer), "Print to File")) + return FALSE; + + GtkPrinter** foundPrinter = static_cast<GtkPrinter**>(userData); + *foundPrinter = static_cast<GtkPrinter*>(g_object_ref(printer)); + return TRUE; + } + + GtkPrinter* findPrintToFilePrinter() + { + GtkPrinter* printer = 0; + gtk_enumerate_printers(testPrintOperationPrintPrinter, &printer, 0, TRUE); + return printer; + } -static void testPrintOperationPrint(WebViewTest* test, gconstpointer) + void waitUntilPrintFinished() + { + g_main_loop_run(m_mainLoop); + } + + GRefPtr<WebKitPrintOperation> m_printOperation; + unsigned int m_expectedError; +}; + +static void testPrintOperationPrint(PrintTest* test, gconstpointer) { - g_signal_connect(test->m_webView, "load-changed", G_CALLBACK(testPrintOperationPrintLoadChanged), test); test->loadHtml("<html><body>WebKitGTK+ printing test</body></html>", 0); - g_main_loop_run(test->m_mainLoop); + test->waitUntilLoadFinished(); - GtkPrinter* printer = 0; - gtk_enumerate_printers(testPrintOperationPrintPrinter, &printer, 0, TRUE); + GRefPtr<GtkPrinter> printer = adoptGRef(test->findPrintToFilePrinter()); if (!printer) { g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found"); return; @@ -113,16 +139,12 @@ static void testPrintOperationPrint(WebViewTest* test, gconstpointer) GOwnPtr<char> outputURI(g_file_get_uri(outputFile.get())); GRefPtr<GtkPrintSettings> printSettings = adoptGRef(gtk_print_settings_new()); - gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer)); + gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get())); gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, outputURI.get()); - g_object_unref(printer); - GRefPtr<WebKitPrintOperation> printOperation = webkit_print_operation_new(test->m_webView); - test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(printOperation.get())); - g_signal_connect(printOperation.get(), "finished", G_CALLBACK(testPrintOperationPrintFinished), test); - webkit_print_operation_set_print_settings(printOperation.get(), printSettings.get()); - webkit_print_operation_print(printOperation.get()); - g_main_loop_run(test->m_mainLoop); + webkit_print_operation_set_print_settings(test->m_printOperation.get(), printSettings.get()); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); GRefPtr<GFileInfo> fileInfo = adoptGRef(g_file_query_info(outputFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE","G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, static_cast<GFileQueryInfoFlags>(0), 0, 0)); @@ -132,6 +154,40 @@ static void testPrintOperationPrint(WebViewTest* test, gconstpointer) g_file_delete(outputFile.get(), 0, 0); } + +static void testPrintOperationErrors(PrintTest* test, gconstpointer) +{ + test->loadHtml("<html><body>WebKitGTK+ printing errors test</body></html>", 0); + test->waitUntilLoadFinished(); + + GRefPtr<GtkPrinter> printer = adoptGRef(test->findPrintToFilePrinter()); + if (!printer) { + g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found"); + return; + } + + // General Error: invalid filename. + test->m_expectedError = WEBKIT_PRINT_ERROR_GENERAL; + GRefPtr<GtkPrintSettings> printSettings = adoptGRef(gtk_print_settings_new()); + gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get())); + gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, "file:///foo/bar"); + webkit_print_operation_set_print_settings(test->m_printOperation.get(), printSettings.get()); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); + + // Printer not found error. + test->m_expectedError = WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND; + gtk_print_settings_set_printer(printSettings.get(), "The fake WebKit printer"); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); + + // No pages to print: print even pages for a single page document. + test->m_expectedError = WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE; + gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get())); + gtk_print_settings_set_page_set(printSettings.get(), GTK_PAGE_SET_EVEN); + webkit_print_operation_print(test->m_printOperation.get()); + test->waitUntilPrintFinished(); +} #endif // HAVE_GTK_UNIX_PRINTING void beforeAll() @@ -142,7 +198,8 @@ void beforeAll() WebViewTest::add("WebKitPrintOperation", "printing-settings", testPrintOperationPrintSettings); WebViewTest::add("WebKitWebView", "print-requested", testWebViewPrintRequested); #ifdef HAVE_GTK_UNIX_PRINTING - WebViewTest::add("WebKitPrintOperation", "print", testPrintOperationPrint); + PrintTest::add("WebKitPrintOperation", "print", testPrintOperationPrint); + PrintTest::add("WebKitPrintOperation", "print-errors", testPrintOperationErrors); #endif } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp new file mode 100644 index 000000000..cc272c9e8 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "WebKitTestServer.h" +#include "WebViewTest.h" +#include <wtf/gobject/GRefPtr.h> + +static WebKitTestServer* kServer; + +static const char* kIndexHtml = + "<html><head>" + " <link rel='stylesheet' href='/style.css' type='text/css'>" + " <script language='javascript' src='/javascript.js'></script>" + "</head><body>WebKitGTK+ resources test</body></html>"; + +static const char* kStyleCSS = + "body {" + " margin: 0px;" + " padding: 0px;" + " font-family: sans-serif;" + " background: url(/blank.ico) 0 0 no-repeat;" + " color: black;" + "}"; + +static const char* kJavascript = "function foo () { var a = 1; }"; + +class ResourcesTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(ResourcesTest); + + static void resourceSentRequestCallback(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse, ResourcesTest* test) + { + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + if (redirectResponse) + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(redirectResponse)); + test->resourceSentRequest(resource, request, redirectResponse); + } + + static void resourceReceivedResponseCallback(WebKitWebResource* resource, GParamSpec*, ResourcesTest* test) + { + g_assert(webkit_web_resource_get_response(resource)); + test->resourceReceivedResponse(resource); + } + + static void resourceReceivedDataCallback(WebKitWebResource* resource, guint64 bytesReceived, ResourcesTest* test) + { + test->resourceReceivedData(resource, bytesReceived); + } + + static void resourceFinishedCallback(WebKitWebResource* resource, ResourcesTest* test) + { + test->resourceFinished(resource); + } + + static void resourceFailedCallback(WebKitWebResource* resource, GError* error, ResourcesTest* test) + { + g_assert(error); + test->resourceFailed(resource, error); + } + + static void resourceLoadStartedCallback(WebKitWebView* webView, WebKitWebResource* resource, WebKitURIRequest* request, ResourcesTest* test) + { + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resource)); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + test->resourceLoadStarted(resource, request); + g_signal_connect(resource, "sent-request", G_CALLBACK(resourceSentRequestCallback), test); + g_signal_connect(resource, "notify::response", G_CALLBACK(resourceReceivedResponseCallback), test); + g_signal_connect(resource, "received-data", G_CALLBACK(resourceReceivedDataCallback), test); + g_signal_connect(resource, "finished", G_CALLBACK(resourceFinishedCallback), test); + g_signal_connect(resource, "failed", G_CALLBACK(resourceFailedCallback), test); + } + + ResourcesTest() + : WebViewTest() + , m_resourcesLoaded(0) + , m_resourcesToLoad(0) + , m_resourceDataSize(0) + { + g_signal_connect(m_webView, "resource-load-started", G_CALLBACK(resourceLoadStartedCallback), this); + } + + virtual void resourceLoadStarted(WebKitWebResource* resource, WebKitURIRequest* request) + { + } + + virtual void resourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) + { + } + + virtual void resourceReceivedResponse(WebKitWebResource* resource) + { + } + + virtual void resourceReceivedData(WebKitWebResource* resource, guint64 bytesReceived) + { + } + + virtual void resourceFinished(WebKitWebResource* resource) + { + g_signal_handlers_disconnect_matched(resource, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + if (++m_resourcesLoaded == m_resourcesToLoad) + g_main_loop_quit(m_mainLoop); + } + + virtual void resourceFailed(WebKitWebResource* resource, GError* error) + { + g_assert_not_reached(); + } + + void waitUntilResourcesLoaded(size_t resourcesCount) + { + m_resourcesLoaded = 0; + m_resourcesToLoad = resourcesCount; + g_main_loop_run(m_mainLoop); + } + + static void resourceGetDataCallback(GObject* object, GAsyncResult* result, gpointer userData) + { + size_t dataSize; + GOwnPtr<GError> error; + unsigned char* data = webkit_web_resource_get_data_finish(WEBKIT_WEB_RESOURCE(object), result, &dataSize, &error.outPtr()); + g_assert(!error.get()); + g_assert(data); + g_assert_cmpint(dataSize, >, 0); + + ResourcesTest* test = static_cast<ResourcesTest*>(userData); + test->m_resourceData.set(reinterpret_cast<char*>(data)); + test->m_resourceDataSize = dataSize; + g_main_loop_quit(test->m_mainLoop); + } + + void checkResourceData(WebKitWebResource* resource) + { + m_resourceDataSize = 0; + webkit_web_resource_get_data(resource, resourceGetDataCallback, this); + g_main_loop_run(m_mainLoop); + + const char* uri = webkit_web_resource_get_uri(resource); + if (uri == kServer->getURIForPath("/")) { + g_assert_cmpint(m_resourceDataSize, ==, strlen(kIndexHtml)); + g_assert(!strncmp(m_resourceData.get(), kIndexHtml, m_resourceDataSize)); + } else if (uri == kServer->getURIForPath("/style.css")) { + g_assert_cmpint(m_resourceDataSize, ==, strlen(kStyleCSS)); + g_assert(!strncmp(m_resourceData.get(), kStyleCSS, m_resourceDataSize)); + } else if (uri == kServer->getURIForPath("/javascript.js")) { + g_assert_cmpint(m_resourceDataSize, ==, strlen(kJavascript)); + g_assert(!strncmp(m_resourceData.get(), kJavascript, m_resourceDataSize)); + } else + g_assert_not_reached(); + m_resourceData.clear(); + } + + size_t m_resourcesLoaded; + size_t m_resourcesToLoad; + GOwnPtr<char> m_resourceData; + size_t m_resourceDataSize; +}; + +static void testWebViewResources(ResourcesTest* test, gconstpointer) +{ + // Nothing loaded yet, there shoulnd't be resources. + g_assert(!webkit_web_view_get_main_resource(test->m_webView)); + g_assert(!webkit_web_view_get_subresources(test->m_webView)); + + // Load simple page without subresources. + test->loadHtml("<html><body>Testing WebKitGTK+</body></html>", 0); + test->waitUntilLoadFinished(); + WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_view_get_uri(test->m_webView), ==, webkit_web_resource_get_uri(resource)); + g_assert(!webkit_web_view_get_subresources(test->m_webView)); + + // Load simple page with subresources. + test->loadURI(kServer->getURIForPath("/").data()); + test->waitUntilResourcesLoaded(4); + + resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + g_assert_cmpstr(webkit_web_view_get_uri(test->m_webView), ==, webkit_web_resource_get_uri(resource)); + GOwnPtr<GList> subresources(webkit_web_view_get_subresources(test->m_webView)); + g_assert(subresources); + g_assert_cmpint(g_list_length(subresources.get()), ==, 3); + +#if 0 + // Load the same URI again. + // FIXME: we need a workaround for bug https://bugs.webkit.org/show_bug.cgi?id=78510. + test->loadURI(kServer->getURIForPath("/").data()); + test->waitUntilResourcesLoaded(4); +#endif + + // Reload. + webkit_web_view_reload(test->m_webView); + test->waitUntilResourcesLoaded(4); +} + +class SingleResourceLoadTest: public ResourcesTest { +public: + MAKE_GLIB_TEST_FIXTURE(SingleResourceLoadTest); + + enum LoadEvents { + Started, + SentRequest, + Redirected, + ReceivedResponse, + ReceivedData, + Finished, + Failed + }; + + SingleResourceLoadTest() + : ResourcesTest() + , m_resourceDataReceived(0) + { + m_resourcesToLoad = 2; + } + + void resourceLoadStarted(WebKitWebResource* resource, WebKitURIRequest* request) + { + if (resource == webkit_web_view_get_main_resource(m_webView)) + return; + + m_resourceDataReceived = 0; + m_resource = resource; + m_loadEvents.append(Started); + } + + void resourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) + { + if (resource != m_resource) + return; + + if (redirectResponse) + m_loadEvents.append(Redirected); + else + m_loadEvents.append(SentRequest); + } + + void resourceReceivedResponse(WebKitWebResource* resource) + { + if (resource != m_resource) + return; + + m_loadEvents.append(ReceivedResponse); + } + + void resourceReceivedData(WebKitWebResource* resource, guint64 bytesReceived) + { + if (resource != m_resource) + return; + + m_resourceDataReceived += bytesReceived; + if (!m_loadEvents.contains(ReceivedData)) + m_loadEvents.append(ReceivedData); + } + + void resourceFinished(WebKitWebResource* resource) + { + if (resource != m_resource) { + ResourcesTest::resourceFinished(resource); + return; + } + + if (!m_loadEvents.contains(Failed)) { + WebKitURIResponse* response = webkit_web_resource_get_response(m_resource.get()); + g_assert(response); + g_assert_cmpint(webkit_uri_response_get_content_length(response), ==, m_resourceDataReceived); + } + m_loadEvents.append(Finished); + ResourcesTest::resourceFinished(resource); + } + + void resourceFailed(WebKitWebResource* resource, GError* error) + { + if (resource == m_resource) + m_loadEvents.append(Failed); + } + + void waitUntilResourceLoadFinsihed() + { + m_resource = 0; + m_resourcesLoaded = 0; + g_main_loop_run(m_mainLoop); + } + + int waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse() + { + waitUntilResourceLoadFinsihed(); + g_assert(m_resource); + WebKitURIResponse* response = webkit_web_resource_get_response(m_resource.get()); + g_assert(response); + return webkit_uri_response_get_status_code(response); + } + + GRefPtr<WebKitWebResource> m_resource; + Vector<LoadEvents> m_loadEvents; + guint64 m_resourceDataReceived; +}; + +static void testWebResourceLoading(SingleResourceLoadTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/javascript.html").data()); + test->waitUntilResourceLoadFinsihed(); + g_assert(test->m_resource); + Vector<SingleResourceLoadTest::LoadEvents>& events = test->m_loadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, SingleResourceLoadTest::Started); + g_assert_cmpint(events[1], ==, SingleResourceLoadTest::SentRequest); + g_assert_cmpint(events[2], ==, SingleResourceLoadTest::ReceivedResponse); + g_assert_cmpint(events[3], ==, SingleResourceLoadTest::ReceivedData); + g_assert_cmpint(events[4], ==, SingleResourceLoadTest::Finished); + events.clear(); + + test->loadURI(kServer->getURIForPath("/redirected-css.html").data()); + test->waitUntilResourceLoadFinsihed(); + g_assert(test->m_resource); + g_assert_cmpint(events.size(), ==, 6); + g_assert_cmpint(events[0], ==, SingleResourceLoadTest::Started); + g_assert_cmpint(events[1], ==, SingleResourceLoadTest::SentRequest); + g_assert_cmpint(events[2], ==, SingleResourceLoadTest::Redirected); + g_assert_cmpint(events[3], ==, SingleResourceLoadTest::ReceivedResponse); + g_assert_cmpint(events[4], ==, SingleResourceLoadTest::ReceivedData); + g_assert_cmpint(events[5], ==, SingleResourceLoadTest::Finished); + events.clear(); + + test->loadURI(kServer->getURIForPath("/invalid-css.html").data()); + test->waitUntilResourceLoadFinsihed(); + g_assert(test->m_resource); + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, SingleResourceLoadTest::Started); + g_assert_cmpint(events[1], ==, SingleResourceLoadTest::SentRequest); + g_assert_cmpint(events[2], ==, SingleResourceLoadTest::Failed); + g_assert_cmpint(events[3], ==, SingleResourceLoadTest::Finished); + events.clear(); +} + +static void testWebResourceResponse(SingleResourceLoadTest* test, gconstpointer) +{ + // No cached resource: First load. + test->loadURI(kServer->getURIForPath("/javascript.html").data()); + gint statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // No cached resource: Second load. + test->loadURI(kServer->getURIForPath("/javascript.html").data()); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // No cached resource: Reload. + webkit_web_view_reload(test->m_webView); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // Cached resource: First load. + test->loadURI(kServer->getURIForPath("/image.html").data()); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // Cached resource: Second load. + test->loadURI(kServer->getURIForPath("/image.html").data()); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_OK); + + // Cached resource: Reload. + webkit_web_view_reload(test->m_webView); + statusCode = test->waitUntilResourceLoadFinsihedAndReturnHTTPStatusResponse(); + g_assert_cmpint(statusCode, ==, SOUP_STATUS_NOT_MODIFIED); +} + +class ResourceURITrackingTest: public SingleResourceLoadTest { +public: + MAKE_GLIB_TEST_FIXTURE(ResourceURITrackingTest); + + ResourceURITrackingTest() + : SingleResourceLoadTest() + { + } + + static void uriChanged(WebKitWebResource* resource, GParamSpec*, ResourceURITrackingTest* test) + { + g_assert(resource == test->m_resource.get()); + g_assert_cmpstr(test->m_activeURI.data(), !=, webkit_web_resource_get_uri(test->m_resource.get())); + test->m_activeURI = webkit_web_resource_get_uri(test->m_resource.get()); + } + + void resourceLoadStarted(WebKitWebResource* resource, WebKitURIRequest* request) + { + if (resource == webkit_web_view_get_main_resource(m_webView)) + return; + + m_resource = resource; + m_activeURI = webkit_web_resource_get_uri(resource); + checkActiveURI("/redirected.css"); + g_assert_cmpstr(m_activeURI.data(), ==, webkit_uri_request_get_uri(request)); + g_signal_connect(resource, "notify::uri", G_CALLBACK(uriChanged), this); + } + + void resourceSentRequest(WebKitWebResource* resource, WebKitURIRequest* request, WebKitURIResponse* redirectResponse) + { + if (resource != m_resource) + return; + + if (redirectResponse) + checkActiveURI("/simple-style.css"); + else + checkActiveURI("/redirected.css"); + g_assert_cmpstr(m_activeURI.data(), ==, webkit_uri_request_get_uri(request)); + } + + void resourceReceivedResponse(WebKitWebResource* resource) + { + if (resource != m_resource) + return; + + checkActiveURI("/simple-style.css"); + } + + void resourceReceivedData(WebKitWebResource* resource, guint64 bytesReceived) + { + } + + void resourceFinished(WebKitWebResource* resource) + { + if (resource == m_resource) + checkActiveURI("/simple-style.css"); + ResourcesTest::resourceFinished(resource); + } + + void resourceFailed(WebKitWebResource*, GError*) + { + g_assert_not_reached(); + } + + CString m_activeURI; + +private: + void checkActiveURI(const char* uri) + { + // g_assert_cmpstr is a macro, so we need to cache the temporary string. + CString serverURI = kServer->getURIForPath(uri); + g_assert_cmpstr(m_activeURI.data(), ==, serverURI.data()); + } +}; + +static void testWebResourceActiveURI(ResourceURITrackingTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/redirected-css.html").data()); + test->waitUntilResourceLoadFinsihed(); +} + +static void testWebResourceGetData(ResourcesTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/").data()); + // FIXME: this should be 4 instead of 3, but we don't get the css image resource + // due to bug https://bugs.webkit.org/show_bug.cgi?id=78510. + test->waitUntilResourcesLoaded(3); + + WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView); + g_assert(resource); + test->checkResourceData(resource); + + GOwnPtr<GList> subresources(webkit_web_view_get_subresources(test->m_webView)); + for (GList* item = subresources.get(); item; item = g_list_next(item)) + test->checkResourceData(WEBKIT_WEB_RESOURCE(item->data)); +} + +static void replacedContentResourceLoadStartedCallback() +{ + g_assert_not_reached(); +} + +static void testWebViewResourcesReplacedContent(ResourcesTest* test, gconstpointer) +{ + test->loadURI(kServer->getURIForPath("/").data()); + // FIXME: this should be 4 instead of 3, but we don't get the css image resource + // due to bug https://bugs.webkit.org/show_bug.cgi?id=78510. + test->waitUntilResourcesLoaded(3); + + static const char* replacedHtml = + "<html><head>" + " <title>Content Replaced</title>" + " <link rel='stylesheet' href='data:text/css,body { margin: 0px; padding: 0px; }' type='text/css'>" + " <script language='javascript' src='data:application/javascript,function foo () { var a = 1; }'></script>" + "</head><body onload='document.title=\"Loaded\"'>WebKitGTK+ resources on replaced content test</body></html>"; + g_signal_connect(test->m_webView, "resource-load-started", G_CALLBACK(replacedContentResourceLoadStartedCallback), test); + test->replaceContent(replacedHtml, "http://error-page.foo", 0); + test->waitUntilTitleChangedTo("Loaded"); + + g_assert(!webkit_web_view_get_main_resource(test->m_webView)); + g_assert(!webkit_web_view_get_subresources(test->m_webView)); +} + +static void addCacheHTTPHeadersToResponse(SoupMessage* message) +{ + // The actual date doesn't really matter. + SoupDate* soupDate = soup_date_new_from_now(0); + GOwnPtr<char> date(soup_date_to_string(soupDate, SOUP_DATE_HTTP)); + soup_message_headers_append(message->response_headers, "Last-Modified", date.get()); + soup_date_free(soupDate); + soup_message_headers_append(message->response_headers, "Cache-control", "public, max-age=31536000"); + soupDate = soup_date_new_from_now(3600); + date.set(soup_date_to_string(soupDate, SOUP_DATE_HTTP)); + soup_message_headers_append(message->response_headers, "Expires", date.get()); + soup_date_free(soupDate); +} + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status(message, SOUP_STATUS_OK); + + if (soup_message_headers_get(message->request_headers, "If-Modified-Since")) { + soup_message_set_status(message, SOUP_STATUS_NOT_MODIFIED); + soup_message_body_complete(message->response_body); + return; + } + + if (g_str_equal(path, "/")) { + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kIndexHtml, strlen(kIndexHtml)); + } else if (g_str_equal(path, "/javascript.html")) { + static const char* javascriptHtml = "<html><head><script language='javascript' src='/javascript.js'></script></head><body></body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, javascriptHtml, strlen(javascriptHtml)); + } else if (g_str_equal(path, "/image.html")) { + static const char* imageHTML = "<html><body><img src='/blank.ico'></img></body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, imageHTML, strlen(imageHTML)); + } else if (g_str_equal(path, "/redirected-css.html")) { + static const char* redirectedCSSHtml = "<html><head><link rel='stylesheet' href='/redirected.css' type='text/css'></head><body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, redirectedCSSHtml, strlen(redirectedCSSHtml)); + } else if (g_str_equal(path, "/invalid-css.html")) { + static const char* invalidCSSHtml = "<html><head><link rel='stylesheet' href='/invalid.css' type='text/css'></head><body></html>"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, invalidCSSHtml, strlen(invalidCSSHtml)); + } else if (g_str_equal(path, "/style.css")) { + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleCSS, strlen(kStyleCSS)); + addCacheHTTPHeadersToResponse(message); + } else if (g_str_equal(path, "/javascript.js")) { + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kJavascript, strlen(kJavascript)); + } else if (g_str_equal(path, "/blank.ico")) { + GOwnPtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL)); + char* contents; + gsize contentsLength; + g_file_get_contents(filePath.get(), &contents, &contentsLength, 0); + soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength); + addCacheHTTPHeadersToResponse(message); + } else if (g_str_equal(path, "/simple-style.css")) { + static const char* simpleCSS = + "body {" + " margin: 0px;" + " padding: 0px;" + "}"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, simpleCSS, strlen(simpleCSS)); + } else if (g_str_equal(path, "/redirected.css")) { + soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); + soup_message_headers_append(message->response_headers, "Location", "/simple-style.css"); + } else if (g_str_equal(path, "/invalid.css")) + soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT); + soup_message_body_complete(message->response_body); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + ResourcesTest::add("WebKitWebView", "resources", testWebViewResources); + SingleResourceLoadTest::add("WebKitWebResource", "loading", testWebResourceLoading); + SingleResourceLoadTest::add("WebKitWebResource", "response", testWebResourceResponse); + ResourceURITrackingTest::add("WebKitWebResource", "active-uri", testWebResourceActiveURI); + ResourcesTest::add("WebKitWebResource", "get-data", testWebResourceGetData); + ResourcesTest::add("WebKitWebView", "replaced-content", testWebViewResourcesReplacedContent); +} + +void afterAll() +{ + delete kServer; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp index 03c5f2fe8..19491c201 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "TestMain.h" -#include <JavaScriptCore/GRefPtr.h> #include <gtk/gtk.h> #include <webkit2/webkit2.h> +#include <wtf/gobject/GRefPtr.h> static void testWebKitSettings(Test*, gconstpointer) { @@ -204,6 +204,11 @@ static void testWebKitSettings(Test*, gconstpointer) webkit_settings_set_zoom_text_only(settings, TRUE); g_assert(webkit_settings_get_zoom_text_only(settings)); + // By default, JavaScript cannot access the clipboard. + g_assert(!webkit_settings_get_javascript_can_access_clipboard(settings)); + webkit_settings_set_javascript_can_access_clipboard(settings, TRUE); + g_assert(webkit_settings_get_javascript_can_access_clipboard(settings)); + g_object_unref(G_OBJECT(settings)); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp index bfeda169f..d65e8a641 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp @@ -332,6 +332,14 @@ static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer) g_assert_cmpint(events[2], ==, UIClientTest::Close); } +static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType) +{ + GtkFileFilterInfo filterInfo; + filterInfo.contains = GTK_FILE_FILTER_MIME_TYPE; + filterInfo.mime_type = mimeType; + return gtk_file_filter_filter(filter, &filterInfo); +} + static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer) { static const char* htmlOnLoadFormat = "<html><body onLoad=\"%s\"></body></html>"; @@ -452,6 +460,252 @@ static void testWebViewZoomLevel(WebViewTest* test, gconstpointer) g_assert_cmpfloat(webkit_web_view_get_zoom_level(test->m_webView), ==, 2.5); } +static void testWebViewRunJavaScript(WebViewTest* test, gconstpointer) +{ + static const char* html = "<html><body><a id='WebKitLink' href='http://www.webkitgtk.org/' title='WebKitGTK+ Title'>WebKitGTK+ Website</a></body></html>"; + test->loadHtml(html, 0); + test->waitUntilLoadFinished(); + + GOwnPtr<GError> error; + WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').title;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + GOwnPtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Title"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').href;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.set(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "http://www.webkitgtk.org/"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').textContent", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.set(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Website"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = 25;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 25); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = 2.5;", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 2.5); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = true", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(WebViewTest::javascriptResultToBoolean(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = false", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(!WebViewTest::javascriptResultToBoolean(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = null", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(WebViewTest::javascriptResultIsNull(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("function Foo() { a = 25; } Foo();", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + g_assert(WebViewTest::javascriptResultIsUndefined(javascriptResult)); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("foo();", &error.outPtr()); + g_assert(!javascriptResult); + g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); +} + +class FileChooserTest: public UIClientTest { +public: + MAKE_GLIB_TEST_FIXTURE(FileChooserTest); + + FileChooserTest() + { + g_signal_connect(m_webView, "run-file-chooser", G_CALLBACK(runFileChooserCallback), this); + } + + static gboolean runFileChooserCallback(WebKitWebView*, WebKitFileChooserRequest* request, FileChooserTest* test) + { + test->runFileChooser(request); + return TRUE; + } + + void runFileChooser(WebKitFileChooserRequest* request) + { + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + m_fileChooserRequest = request; + g_main_loop_quit(m_mainLoop); + } + + WebKitFileChooserRequest* clickMouseButtonAndWaitForFileChooserRequest(int x, int y) + { + clickMouseButton(x, y); + g_main_loop_run(m_mainLoop); + return m_fileChooserRequest.get(); + } + +private: + GRefPtr<WebKitFileChooserRequest> m_fileChooserRequest; +}; + +static void testWebViewFileChooserRequest(FileChooserTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + static const char* fileChooserHTMLFormat = "<html><body><input style='position:absolute;left:0;top:0;margin:0;padding:0' type='file' %s/></body></html>"; + + // Multiple selections not allowed, no MIME filtering. + GOwnPtr<char> simpleFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "")); + test->loadHtml(simpleFileUploadHTML.get(), 0); + test->waitUntilLoadFinished(); + WebKitFileChooserRequest* fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + g_assert(!webkit_file_chooser_request_get_select_multiple(fileChooserRequest)); + + const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest); + g_assert(!mimeTypes); + GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest); + g_assert(!filter); + const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(!selectedFiles); + webkit_file_chooser_request_cancel(fileChooserRequest); + + // Multiple selections allowed, no MIME filtering, some pre-selected files. + GOwnPtr<char> multipleSelectionFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "multiple")); + test->loadHtml(multipleSelectionFileUploadHTML.get(), 0); + test->waitUntilLoadFinished(); + fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + g_assert(webkit_file_chooser_request_get_select_multiple(fileChooserRequest)); + + mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest); + g_assert(!mimeTypes); + filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest); + g_assert(!filter); + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(!selectedFiles); + + // Select some files. + const gchar* filesToSelect[4] = { "/foo", "/foo/bar", "/foo/bar/baz", 0 }; + webkit_file_chooser_request_select_files(fileChooserRequest, filesToSelect); + + // Check the files that have been just selected. + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(selectedFiles); + g_assert_cmpstr(selectedFiles[0], ==, "/foo"); + g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar"); + g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz"); + g_assert(!selectedFiles[3]); + + // Perform another request to check if the list of files selected + // in the previous step appears now as part of the new request. + fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(selectedFiles); + g_assert_cmpstr(selectedFiles[0], ==, "/foo"); + g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar"); + g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz"); + g_assert(!selectedFiles[3]); + webkit_file_chooser_request_cancel(fileChooserRequest); + + // Multiple selections not allowed, only accept images, audio and video files.. + GOwnPtr<char> mimeFilteredFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "accept='audio/*,video/*,image/*'")); + test->loadHtml(mimeFilteredFileUploadHTML.get(), 0); + test->waitUntilLoadFinished(); + fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5); + g_assert(!webkit_file_chooser_request_get_select_multiple(fileChooserRequest)); + + mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest); + g_assert(mimeTypes); + g_assert_cmpstr(mimeTypes[0], ==, "audio/*"); + g_assert_cmpstr(mimeTypes[1], ==, "video/*"); + g_assert_cmpstr(mimeTypes[2], ==, "image/*"); + g_assert(!mimeTypes[3]); + + filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest); + g_assert(GTK_IS_FILE_FILTER(filter)); + g_assert(checkMimeTypeForFilter(filter, "audio/*")); + g_assert(checkMimeTypeForFilter(filter, "video/*")); + g_assert(checkMimeTypeForFilter(filter, "image/*")); + + selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest); + g_assert(!selectedFiles); + webkit_file_chooser_request_cancel(fileChooserRequest); +} + +class FullScreenClientTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(FullScreenClientTest); + + enum FullScreenEvent { + None, + Enter, + Leave + }; + + static gboolean viewEnterFullScreenCallback(WebKitWebView*, FullScreenClientTest* test) + { + test->m_event = Enter; + g_main_loop_quit(test->m_mainLoop); + return FALSE; + } + + static gboolean viewLeaveFullScreenCallback(WebKitWebView*, FullScreenClientTest* test) + { + test->m_event = Leave; + g_main_loop_quit(test->m_mainLoop); + return FALSE; + } + + FullScreenClientTest() + : m_event(None) + { + webkit_settings_set_enable_fullscreen(webkit_web_view_get_settings(m_webView), TRUE); + g_signal_connect(m_webView, "enter-fullscreen", G_CALLBACK(viewEnterFullScreenCallback), this); + g_signal_connect(m_webView, "leave-fullscreen", G_CALLBACK(viewLeaveFullScreenCallback), this); + } + + ~FullScreenClientTest() + { + g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + } + + void requestFullScreenAndWaitUntilEnteredFullScreen() + { + m_event = None; + webkit_web_view_run_javascript(m_webView, "document.documentElement.webkitRequestFullScreen();", 0, 0); + g_main_loop_run(m_mainLoop); + } + + static gboolean leaveFullScreenIdle(FullScreenClientTest* test) + { + test->keyStroke(GDK_KEY_Escape); + return FALSE; + } + + void leaveFullScreenAndWaitUntilLeftFullScreen() + { + m_event = None; + g_idle_add(reinterpret_cast<GSourceFunc>(leaveFullScreenIdle), this); + g_main_loop_run(m_mainLoop); + } + + FullScreenEvent m_event; +}; + +static void testWebViewFullScreen(FullScreenClientTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + test->loadHtml("<html><body>FullScreen test</body></html>", 0); + test->waitUntilLoadFinished(); + test->requestFullScreenAndWaitUntilEnteredFullScreen(); + g_assert_cmpint(test->m_event, ==, FullScreenClientTest::Enter); + test->leaveFullScreenAndWaitUntilLeftFullScreen(); + g_assert_cmpint(test->m_event, ==, FullScreenClientTest::Leave); +} + void beforeAll() { WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext); @@ -463,6 +717,9 @@ void beforeAll() UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties); UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget); WebViewTest::add("WebKitWebView", "zoom-level", testWebViewZoomLevel); + WebViewTest::add("WebKitWebView", "run-javascript", testWebViewRunJavaScript); + FileChooserTest::add("WebKitWebView", "file-chooser-request", testWebViewFileChooserRequest); + FullScreenClientTest::add("WebKitWebView", "fullscreen", testWebViewFullScreen); } void afterAll() diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp index 31de72911..7a9e49bc6 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp @@ -21,12 +21,14 @@ #include "config.h" #include "WebViewTest.h" +#include <JavaScriptCore/JSRetainPtr.h> #include <WebCore/GOwnPtrGtk.h> WebViewTest::WebViewTest() : m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new()))) , m_mainLoop(g_main_loop_new(0, TRUE)) , m_parentWindow(0) + , m_javascriptResult(0) { assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView)); } @@ -35,6 +37,8 @@ WebViewTest::~WebViewTest() { if (m_parentWindow) gtk_widget_destroy(m_parentWindow); + if (m_javascriptResult) + webkit_javascript_result_unref(m_javascriptResult); g_object_unref(m_webView); g_main_loop_unref(m_mainLoop); } @@ -74,15 +78,7 @@ void WebViewTest::loadRequest(WebKitURIRequest* request) void WebViewTest::replaceContent(const char* html, const char* contentURI, const char* baseURI) { - // FIXME: The active uri should be the contentURI, - // but WebPageProxy doesn't return the unreachableURL - // when the page has been loaded with AlternateHTML() - // See https://bugs.webkit.org/show_bug.cgi?id=75465. -#if 0 m_activeURI = contentURI; -#else - m_activeURI = "about:blank"; -#endif webkit_web_view_replace_content(m_webView, html, contentURI, baseURI); } @@ -202,3 +198,142 @@ void WebViewTest::mouseMoveTo(int x, int y, unsigned int mouseModifiers) gtk_main_do_event(event.get()); } +void WebViewTest::clickMouseButton(int x, int y, unsigned int button, unsigned int mouseModifiers) +{ + doMouseButtonEvent(GDK_BUTTON_PRESS, x, y, button, mouseModifiers); + doMouseButtonEvent(GDK_BUTTON_RELEASE, x, y, button, mouseModifiers); +} + +void WebViewTest::keyStroke(unsigned int keyVal, unsigned int keyModifiers) +{ + g_assert(m_parentWindow); + GtkWidget* viewWidget = GTK_WIDGET(m_webView); + g_assert(gtk_widget_get_realized(viewWidget)); + + GOwnPtr<GdkEvent> event(gdk_event_new(GDK_KEY_PRESS)); + event->key.keyval = keyVal; + + event->key.time = GDK_CURRENT_TIME; + event->key.window = gtk_widget_get_window(viewWidget); + g_object_ref(event->key.window); + gdk_event_set_device(event.get(), gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget)))); + event->key.state = keyModifiers; + + // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+. + GOwnPtr<GdkKeymapKey> keys; + int keysCount; + if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), keyVal, &keys.outPtr(), &keysCount)) + event->key.hardware_keycode = keys.get()[0].keycode; + + gtk_main_do_event(event.get()); + event->key.type = GDK_KEY_RELEASE; + gtk_main_do_event(event.get()); +} + +void WebViewTest::doMouseButtonEvent(GdkEventType eventType, int x, int y, unsigned int button, unsigned int mouseModifiers) +{ + g_assert(m_parentWindow); + GtkWidget* viewWidget = GTK_WIDGET(m_webView); + g_assert(gtk_widget_get_realized(viewWidget)); + + GOwnPtr<GdkEvent> event(gdk_event_new(eventType)); + event->button.window = gtk_widget_get_window(viewWidget); + g_object_ref(event->button.window); + + event->button.time = GDK_CURRENT_TIME; + event->button.x = x; + event->button.y = y; + event->button.axes = 0; + event->button.state = mouseModifiers; + event->button.button = button; + + event->button.device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(viewWidget))); + + int xRoot, yRoot; + gdk_window_get_root_coords(gtk_widget_get_window(viewWidget), x, y, &xRoot, &yRoot); + event->button.x_root = xRoot; + event->button.y_root = yRoot; + gtk_main_do_event(event.get()); +} + +static void runJavaScriptReadyCallback(GObject*, GAsyncResult* result, WebViewTest* test) +{ + test->m_javascriptResult = webkit_web_view_run_javascript_finish(test->m_webView, result, test->m_javascriptError); + g_main_loop_quit(test->m_mainLoop); +} + +WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* javascript, GError** error) +{ + if (m_javascriptResult) + webkit_javascript_result_unref(m_javascriptResult); + m_javascriptResult = 0; + m_javascriptError = error; + webkit_web_view_run_javascript(m_webView, javascript, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this); + g_main_loop_run(m_mainLoop); + + return m_javascriptResult; +} + +static char* jsValueToCString(JSGlobalContextRef context, JSValueRef value) +{ + g_assert(value); + g_assert(JSValueIsString(context, value)); + + JSRetainPtr<JSStringRef> stringValue(Adopt, JSValueToStringCopy(context, value, 0)); + g_assert(stringValue); + + size_t cStringLength = JSStringGetMaximumUTF8CStringSize(stringValue.get()); + char* cString = static_cast<char*>(g_malloc(cStringLength)); + JSStringGetUTF8CString(stringValue.get(), cString, cStringLength); + return cString; +} + +char* WebViewTest::javascriptResultToCString(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + return jsValueToCString(context, webkit_javascript_result_get_value(javascriptResult)); +} + +double WebViewTest::javascriptResultToNumber(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + g_assert(JSValueIsNumber(context, value)); + + return JSValueToNumber(context, value, 0); +} + +bool WebViewTest::javascriptResultToBoolean(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + g_assert(JSValueIsBoolean(context, value)); + + return JSValueToBoolean(context, value); +} + +bool WebViewTest::javascriptResultIsNull(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + + return JSValueIsNull(context, value); +} + +bool WebViewTest::javascriptResultIsUndefined(WebKitJavascriptResult* javascriptResult) +{ + JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult); + g_assert(context); + JSValueRef value = webkit_javascript_result_get_value(javascriptResult); + g_assert(value); + + return JSValueIsUndefined(context, value); +} + diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h index 01f468562..92e123630 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h @@ -47,12 +47,28 @@ public: void showInWindowAndWaitUntilMapped(); void mouseMoveTo(int x, int y, unsigned int mouseModifiers = 0); + void clickMouseButton(int x, int y, unsigned int button = 1, unsigned int mouseModifiers = 0); + void keyStroke(unsigned int keyVal, unsigned int keyModifiers = 0); + + WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**); + + // Javascript result helpers. + static char* javascriptResultToCString(WebKitJavascriptResult*); + static double javascriptResultToNumber(WebKitJavascriptResult*); + static bool javascriptResultToBoolean(WebKitJavascriptResult*); + static bool javascriptResultIsNull(WebKitJavascriptResult*); + static bool javascriptResultIsUndefined(WebKitJavascriptResult*); WebKitWebView* m_webView; GMainLoop* m_mainLoop; CString m_activeURI; GtkWidget* m_parentWindow; CString m_expectedTitle; + WebKitJavascriptResult* m_javascriptResult; + GError** m_javascriptError; + +private: + void doMouseButtonEvent(GdkEventType, int, int, unsigned int, unsigned int); }; #endif // WebViewTest_h diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index 0a807bc3d..c5460f333 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -25,21 +25,25 @@ #include <webkit2/WebKitBackForwardList.h> #include <webkit2/WebKitBackForwardListItem.h> +#include <webkit2/WebKitCookieManager.h> #include <webkit2/WebKitDefines.h> #include <webkit2/WebKitDownload.h> #include <webkit2/WebKitEditingCommands.h> #include <webkit2/WebKitEnumTypes.h> #include <webkit2/WebKitError.h> +#include <webkit2/WebKitFileChooserRequest.h> #include <webkit2/WebKitFindController.h> #include <webkit2/WebKitHitTestResult.h> +#include <webkit2/WebKitJavascriptResult.h> #include <webkit2/WebKitPrintOperation.h> #include <webkit2/WebKitScriptDialog.h> #include <webkit2/WebKitSettings.h> #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitURIResponse.h> #include <webkit2/WebKitWebContext.h> -#include <webkit2/WebKitWebViewBase.h> +#include <webkit2/WebKitWebResource.h> #include <webkit2/WebKitWebView.h> +#include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> #undef __WEBKIT2_H_INSIDE__ diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list index 5f7356039..de3032819 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list @@ -3,8 +3,10 @@ BOOLEAN:ENUM,STRING,POINTER BOOLEAN:OBJECT BOOLEAN:OBJECT,ENUM BOOLEAN:STRING +BOOLEAN:VOID OBJECT:VOID VOID:OBJECT,UINT +VOID:OBJECT,OBJECT VOID:OBJECT,POINTER VOID:UINT64 diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.h b/Source/WebKit2/UIProcess/API/mac/PDFViewController.h index 3a4f2f600..46aaf8458 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.h +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.h @@ -62,6 +62,8 @@ public: static Class pdfPreviewViewClass(); + bool forwardScrollWheelEvent(NSEvent *); + NSPrintOperation *makePrintOperation(NSPrintInfo *); void openPDFInFinder(); void savePDFToDownloadsFolder(); diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm index c5441a49f..91fcf34b2 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm @@ -36,6 +36,7 @@ #import "WebPreferences.h" #import <PDFKit/PDFKit.h> #import <WebCore/LocalizedStrings.h> +#import <objc/runtime.h> #import <wtf/text/CString.h> #import <wtf/text/WTFString.h> @@ -114,6 +115,7 @@ static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selec - (PDFView *)pdfView; - (void)setDocument:(PDFDocument *)pdfDocument; +- (BOOL)forwardScrollWheelEvent:(NSEvent *)wheelEvent; - (void)_applyPDFPreferences; - (PDFSelection *)_nextMatchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag fromSelection:(PDFSelection *)initialSelection startInSelection:(BOOL)startInSelection; @end @@ -383,6 +385,11 @@ static void insertOpenWithDefaultPDFMenuItem(NSMenu *menu, NSUInteger index) _pdfViewController->print(); } +- (BOOL)forwardScrollWheelEvent:(NSEvent *)wheelEvent +{ + return _pdfViewController->forwardScrollWheelEvent(wheelEvent); +} + @end namespace WebKit { @@ -486,7 +493,54 @@ Class PDFViewController::pdfPreviewViewClass() return pdfPreviewViewClass; } + +bool PDFViewController::forwardScrollWheelEvent(NSEvent *wheelEvent) +{ + CGFloat deltaX = [wheelEvent deltaX]; + if ((deltaX > 0 && !page()->canGoBack()) || (deltaX < 0 && !page()->canGoForward())) + return false; + + [m_wkView scrollWheel:wheelEvent]; + return true; +} + +#ifndef BUILDING_ON_SNOW_LEOPARD +static IMP oldPDFViewScrollView_scrollWheel; + +static WKPDFView *findEnclosingWKPDFView(NSView *view) +{ + for (NSView *superview = [view superview]; superview; superview = [superview superview]) { + if ([superview isKindOfClass:[WKPDFView class]]) + return static_cast<WKPDFView *>(superview); + } + + return nil; +} + +static void PDFViewScrollView_scrollWheel(NSScrollView* self, SEL _cmd, NSEvent *wheelEvent) +{ + CGFloat deltaX = [wheelEvent deltaX]; + CGFloat deltaY = [wheelEvent deltaY]; + + NSSize contentsSize = [[self documentView] bounds].size; + NSRect visibleRect = [self documentVisibleRect]; + + // We only want to forward the wheel events if the horizontal delta is non-zero, + // and only if we're pinned to either the left or right side. + // We also never want to forward momentum scroll events. + if ([wheelEvent momentumPhase] == NSEventPhaseNone && deltaX && fabsf(deltaY) < fabsf(deltaX) + && ((deltaX > 0 && visibleRect.origin.x <= 0) || (deltaX < 0 && contentsSize.width <= NSMaxX(visibleRect)))) { + if (WKPDFView *pdfView = findEnclosingWKPDFView(self)) { + if ([pdfView forwardScrollWheelEvent:wheelEvent]) + return; + } + } + + oldPDFViewScrollView_scrollWheel(self, _cmd, wheelEvent); +} +#endif + NSBundle* PDFViewController::pdfKitBundle() { static NSBundle *pdfKitBundle; @@ -502,6 +556,14 @@ NSBundle* PDFViewController::pdfKitBundle() pdfKitBundle = [NSBundle bundleWithPath:pdfKitPath]; if (![pdfKitBundle load]) LOG_ERROR("Couldn't load PDFKit.framework"); + +#ifndef BUILDING_ON_SNOW_LEOPARD + if (Class pdfViewScrollViewClass = [pdfKitBundle classNamed:@"PDFViewScrollView"]) { + if (Method scrollWheel = class_getInstanceMethod(pdfViewScrollViewClass, @selector(scrollWheel:))) + oldPDFViewScrollView_scrollWheel = method_setImplementation(scrollWheel, reinterpret_cast<IMP>(PDFViewScrollView_scrollWheel)); + } +#endif + return pdfKitBundle; } diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h index dbe947a39..a9d7a9fa9 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h @@ -55,7 +55,7 @@ private: virtual bool isViewFocused(); virtual bool isViewVisible(); virtual bool isViewInWindow(); - virtual LayerHostingMode layerHostingMode(); + virtual LayerHostingMode viewLayerHostingMode() OVERRIDE; virtual void processDidCrash(); virtual void pageClosed(); @@ -63,7 +63,7 @@ private: virtual void toolTipChanged(const String& oldToolTip, const String& newToolTip); virtual void setCursor(const WebCore::Cursor&); virtual void setCursorHiddenUntilMouseMoves(bool); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); @@ -72,6 +72,8 @@ private: virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>&); virtual bool executeSavedCommandBySelector(const String& selector); virtual void setDragImage(const WebCore::IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag); + virtual void setPromisedData(const String& pasteboardName, PassRefPtr<WebCore::SharedBuffer> imageBuffer, const String& filename, const String& extension, const String& title, + const String& url, const String& visibleUrl, PassRefPtr<WebCore::SharedBuffer> archiveBuffer); virtual void updateTextInputState(bool updateSecureInputState); virtual void resetTextInputState(); @@ -118,10 +120,10 @@ private: virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&); virtual void dismissDictionaryLookupPanel(); - virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); - virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel); - virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel); - virtual void recordAutocorrectionResponse(WebCore::EditorClient::AutocorrectionResponseType, const String& replacedString, const String& replacementString); + virtual void showCorrectionPanel(WebCore::AlternativeTextType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); + virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingAlternativeText); + virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText); + virtual void recordAutocorrectionResponse(WebCore::AutocorrectionResponseType, const String& replacedString, const String& replacementString); virtual void recommendedScrollbarStyleDidChange(int32_t newStyle); diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm index 71a1a5075..72ea3493e 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm @@ -37,12 +37,15 @@ #import "WebContextMenuProxyMac.h" #import "WebEditCommandProxy.h" #import "WebPopupMenuProxyMac.h" +#import <WebCore/BitmapImage.h> #import <WebCore/Cursor.h> #import <WebCore/FloatRect.h> #import <WebCore/FoundationExtras.h> #import <WebCore/GraphicsContext.h> +#import <WebCore/Image.h> #import <WebCore/KeyboardEvent.h> #import <WebCore/NotImplemented.h> +#import <WebCore/SharedBuffer.h> #import <wtf/PassOwnPtr.h> #import <wtf/text/CString.h> #import <wtf/text/WTFString.h> @@ -190,7 +193,7 @@ bool PageClientImpl::isViewInWindow() return [m_wkView window]; } -LayerHostingMode PageClientImpl::layerHostingMode() +LayerHostingMode PageClientImpl::viewLayerHostingMode() { #if HAVE(LAYER_HOSTING_IN_WINDOW_SERVER) if (![m_wkView window]) @@ -233,7 +236,7 @@ void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves) [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves]; } -void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportArguments&) +void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&) { } @@ -278,6 +281,13 @@ void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<Sha [m_wkView _setDragImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag]; } +void PageClientImpl::setPromisedData(const String& pasteboardName, PassRefPtr<SharedBuffer> imageBuffer, const String& filename, const String& extension, const String& title, const String& url, const String& visibleUrl, PassRefPtr<SharedBuffer> archiveBuffer) +{ + RefPtr<Image> image = BitmapImage::create(); + image->setData(imageBuffer.get(), true); + [m_wkView _setPromisedData:image.get() withFileName:filename withExtension:extension withTitle:title withURL:url withVisibleURL:visibleUrl withArchive:archiveBuffer.get() forPasteboard:pasteboardName]; +} + void PageClientImpl::updateTextInputState(bool updateSecureInputState) { [m_wkView _updateTextInputStateIncludingSecureInputState:updateSecureInputState]; @@ -453,7 +463,7 @@ void PageClientImpl::dismissDictionaryLookupPanel() #endif } -void PageClientImpl::showCorrectionPanel(CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) +void PageClientImpl::showCorrectionPanel(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) { #if !defined(BUILDING_ON_SNOW_LEOPARD) if (!isViewVisible() || !isViewInWindow()) @@ -462,14 +472,14 @@ void PageClientImpl::showCorrectionPanel(CorrectionPanelInfo::PanelType type, co #endif } -void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reason) +void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingAlternativeText reason) { #if !defined(BUILDING_ON_SNOW_LEOPARD) m_correctionPanel.dismiss(reason); #endif } -String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel reason) +String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText reason) { #if !defined(BUILDING_ON_SNOW_LEOPARD) return m_correctionPanel.dismiss(reason); @@ -478,10 +488,10 @@ String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCo #endif } -void PageClientImpl::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString) +void PageClientImpl::recordAutocorrectionResponse(AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString) { #if !defined(BUILDING_ON_SNOW_LEOPARD) - NSCorrectionResponse response = responseType == EditorClient::AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited; + NSCorrectionResponse response = responseType == AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited; CorrectionPanel::recordAutocorrectionResponse(m_wkView, response, replacedString, replacementString); #endif } diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm index 13aefb82b..63c58895f 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm @@ -27,6 +27,7 @@ #import "WKPrintingView.h" #import "Logging.h" +#import "PDFKitImports.h" #import "PrintInfo.h" #import "WebData.h" #import "WebPageProxy.h" @@ -228,8 +229,8 @@ static void pageDidDrawToPDF(WKDataRef dataRef, WKErrorRef, void* untypedContext ASSERT([view _isPrintingPreview]); if (data) { - pair<HashMap<WebCore::IntRect, Vector<uint8_t> >::iterator, bool> entry = view->_pagePreviews.add(iter->second, Vector<uint8_t>()); - entry.first->second.append(data->bytes(), data->size()); + HashMap<WebCore::IntRect, Vector<uint8_t> >::AddResult entry = view->_pagePreviews.add(iter->second, Vector<uint8_t>()); + entry.iterator->second.append(data->bytes(), data->size()); } view->_expectedPreviewCallbacks.remove(context->callbackID); bool receivedResponseToLatestRequest = view->_latestExpectedPreviewCallback == context->callbackID; @@ -411,33 +412,6 @@ static void prepareDataForPrintingOnSecondaryThread(void* untypedContext) return 0; // Invalid page number. } -static NSString *pdfKitFrameworkPath() -{ - NSString *systemLibraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSSystemDomainMask, NO) objectAtIndex:0]; - return [systemLibraryPath stringByAppendingPathComponent:@"Frameworks/Quartz.framework/Frameworks/PDFKit.framework"]; -} - -static Class classFromPDFKit(NSString *className) -{ - static NSBundle *pdfKitBundle = [NSBundle bundleWithPath:pdfKitFrameworkPath()]; - [pdfKitBundle load]; - return [pdfKitBundle classNamed:className]; -} - -static Class pdfAnnotationLinkClass() -{ - static Class pdfAnnotationLinkClass = classFromPDFKit(@"PDFAnnotationLink"); - ASSERT(pdfAnnotationLinkClass); - return pdfAnnotationLinkClass; -} - -static Class pdfDocumentClass() -{ - static Class pdfDocumentClass = classFromPDFKit(@"PDFDocument"); - ASSERT(pdfDocumentClass); - return pdfDocumentClass; -} - - (void)_drawPDFDocument:(PDFDocument *)pdfDocument page:(unsigned)page atPoint:(NSPoint)point { if (!pdfDocument) { diff --git a/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm b/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm index 8c69b08b6..2be0cfd3c 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm @@ -28,6 +28,23 @@ #import <WebKitSystemInterface.h> +@interface WKTextInputView : NSTextView { +} +@end + +@implementation WKTextInputView + +- (NSArray *)validAttributesForMarkedText +{ + // Let TSM know that a bottom input window would be created for marked text. + NSArray *regularAttributes = [super validAttributesForMarkedText]; + NSMutableArray *floatingWindowAttributes = [NSMutableArray arrayWithArray:regularAttributes]; + [floatingWindowAttributes addObject:@"__NSUsesFloatingInputWindow"]; + return floatingWindowAttributes; +} + +@end + @interface WKTextInputPanel : NSPanel { NSTextView *_inputTextView; } @@ -65,7 +82,7 @@ [self setFrame:frame display:NO]; - _inputTextView = [[NSTextView alloc] initWithFrame:[(NSView *)self.contentView frame]]; + _inputTextView = [[WKTextInputView alloc] initWithFrame:[(NSView *)self.contentView frame]]; _inputTextView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable | NSViewMaxXMargin | NSViewMinXMargin | NSViewMaxYMargin | NSViewMinYMargin; NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:[(NSView *)self.contentView frame]]; @@ -91,6 +108,7 @@ *string = nil; // Let TSM know that a bottom input window would be created for marked text. + // FIXME: Can be removed once we can rely on __NSUsesFloatingInputWindow (or a better API) being available everywhere. EventRef carbonEvent = static_cast<EventRef>(const_cast<void*>([event eventRef])); if (carbonEvent) { Boolean ignorePAH = true; diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index a326dd089..8cd3027a3 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -64,6 +64,7 @@ #import <WebCore/DragData.h> #import <WebCore/DragSession.h> #import <WebCore/FloatRect.h> +#import <WebCore/Image.h> #import <WebCore/IntRect.h> #import <WebCore/KeyboardEvent.h> #import <WebCore/LocalizedStrings.h> @@ -71,7 +72,11 @@ #import <WebCore/PlatformScreen.h> #import <WebCore/Region.h> #import <WebCore/RunLoop.h> +#import <WebCore/SharedBuffer.h> +#import <WebCore/WebCoreNSStringExtras.h> +#import <WebCore/FileSystem.h> #import <WebKitSystemInterface.h> +#import <sys/stat.h> #import <wtf/RefPtr.h> #import <wtf/RetainPtr.h> @@ -92,10 +97,13 @@ @end @interface NSWindow (WKNSWindowDetails) +#if defined(BUILDING_ON_SNOW_LEOPARD) - (NSRect)_growBoxRect; - (id)_growBoxOwner; - (void)_setShowOpaqueGrowBoxForOwner:(id)owner; - (BOOL)_updateGrowBoxForWindowFrameChange; +#endif + - (NSRect)_intersectBottomCornersWithRect:(NSRect)viewRect; - (void)_maskRoundedBottomCorners:(NSRect)clipRect; @end @@ -169,7 +177,6 @@ struct WKViewInterpretKeyEventsParameters { bool _inResignFirstResponder; NSEvent *_mouseDownEvent; BOOL _ignoringMouseDraggedEvents; - BOOL _dragHasStarted; id _flagsChangedEventMonitor; #if ENABLE(GESTURE_EVENTS) @@ -194,6 +201,9 @@ struct WKViewInterpretKeyEventsParameters { // 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; + RefPtr<WebCore::Image> _promisedImage; + String _promisedFilename; + String _promisedURL; } @end @@ -374,7 +384,6 @@ struct WKViewInterpretKeyEventsParameters { // Send back an empty string to the plug-in. This will disable text input. _data->_page->sendComplexTextInputToPlugin(_data->_pluginComplexTextInputIdentifier, String()); - _data->_pluginComplexTextInputIdentifier = 0; // Always reset the identifier when the plugin is disabled. } typedef HashMap<SEL, String> SelectorNameMap; @@ -527,11 +536,17 @@ WEBCORE_COMMAND(yankAndSelect) - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pasteboard types:(NSArray *)types { - Vector<String> pasteboardTypes; size_t numTypes = [types count]; - for (size_t i = 0; i < numTypes; ++i) - pasteboardTypes.append([types objectAtIndex:i]); - return _data->_page->writeSelectionToPasteboard([pasteboard name], pasteboardTypes); + [pasteboard declareTypes:types owner:nil]; + for (size_t i = 0; i < numTypes; ++i) { + if ([[types objectAtIndex:i] isEqualTo:NSStringPboardType]) + [pasteboard setString:_data->_page->stringSelectionForPasteboard() forType:NSStringPboardType]; + else { + RefPtr<SharedBuffer> buffer = _data->_page->dataSelectionForPasteboard([types objectAtIndex:i]); + [pasteboard setData:buffer ? [buffer->createNSData() autorelease] : nil forType:[types objectAtIndex:i]]; + } + } + return YES; } - (void)centerSelectionInVisibleArea:(id)sender @@ -711,9 +726,9 @@ static void validateCommandCallback(WKStringRef commandName, bool isEnabled, int return YES; // Add this item to the vector of items for a given command that are awaiting validation. - pair<ValidationMap::iterator, bool> addResult = _data->_validationMap.add(commandName, ValidationVector()); - addResult.first->second.append(item); - if (addResult.second) { + ValidationMap::AddResult addResult = _data->_validationMap.add(commandName, ValidationVector()); + addResult.iterator->second.append(item); + if (addResult.isNewEntry) { // If we are not already awaiting validation for this command, start the asynchronous validation process. // FIXME: Theoretically, there is a race here; when we get the answer it might be old, from a previous time // we asked for the same command; there is no guarantee the answer is still valid. @@ -1024,7 +1039,6 @@ NATIVE_EVENT_HANDLER(scrollWheel, Wheel) { [self _setMouseDownEvent:event]; _data->_ignoringMouseDraggedEvents = NO; - _data->_dragHasStarted = NO; [self mouseDownInternal:event]; } @@ -1124,9 +1138,11 @@ static const short kIOHIDEventTypeScroll = 6; // As in insertText:replacementRange:, we assume that the call comes from an input method if there is marked text. bool isFromInputMethod = _data->_page->editorState().hasComposition; - if (parameters && !isFromInputMethod) - parameters->commands->append(KeypressCommand(NSStringFromSelector(selector))); - else { + if (parameters && !isFromInputMethod) { + KeypressCommand command(NSStringFromSelector(selector)); + parameters->commands->append(command); + _data->_page->registerKeypressCommandName(command.commandName); + } else { // FIXME: Send the command to Editor synchronously and only send it along the // responder chain if it's a selector that does not correspond to an editing command. [super doCommandBySelector:selector]; @@ -1171,7 +1187,9 @@ static const short kIOHIDEventTypeScroll = 6; // then we also execute it immediately, as there will be no other chance. if (parameters && !isFromInputMethod) { ASSERT(replacementRange.location == NSNotFound); - parameters->commands->append(KeypressCommand("insertText:", text)); + KeypressCommand command("insertText:", text); + parameters->commands->append(command); + _data->_page->registerKeypressCommandName(command.commandName); return; } @@ -1264,10 +1282,8 @@ static const short kIOHIDEventTypeScroll = 6; if (string) { _data->_page->sendComplexTextInputToPlugin(_data->_pluginComplexTextInputIdentifier, string); - if (!usingLegacyCocoaTextInput) { + if (!usingLegacyCocoaTextInput) _data->_pluginComplexTextInputState = PluginComplexTextInputDisabled; - _data->_pluginComplexTextInputIdentifier = 0; // Always reset the identifier when the plugin is disabled. - } } return didHandleEvent; @@ -1678,6 +1694,23 @@ static bool maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, return true; } +static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, SandboxExtension::HandleArray& handles) +{ + NSArray *types = [pasteboard types]; + if (![types containsObject:NSFilenamesPboardType]) + return; + + NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType]; + handles.allocate([files count]); + for (unsigned i = 0; i < [files count]; i++) { + NSString *file = [files objectAtIndex:i]; + if (![[NSFileManager defaultManager] fileExistsAtPath:file]) + continue; + SandboxExtension::Handle handle; + SandboxExtension::createHandle(file, SandboxExtension::ReadOnly, handles[i]); + } +} + - (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo { IntPoint client([self convertPoint:[draggingInfo draggingLocation] fromView:nil]); @@ -1689,7 +1722,10 @@ static bool maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, if (createdExtension) _data->_page->process()->willAcquireUniversalFileReadSandboxExtension(); - _data->_page->performDrag(&dragData, [[draggingInfo draggingPasteboard] name], sandboxExtensionHandle); + SandboxExtension::HandleArray sandboxExtensionForUpload; + createSandboxExtensionsForFileUpload([draggingInfo draggingPasteboard], sandboxExtensionForUpload); + + _data->_page->performDrag(&dragData, [[draggingInfo draggingPasteboard] name], sandboxExtensionHandle, sandboxExtensionForUpload); return YES; } @@ -1716,6 +1752,8 @@ static bool maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, _data->_page->updateWindowIsVisible([[self window] isVisible]); } + +#if defined(BUILDING_ON_SNOW_LEOPARD) - (BOOL)_ownsWindowGrowBox { NSWindow* window = [self window]; @@ -1764,6 +1802,7 @@ static bool maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, return ownsGrowBox; } +#endif // FIXME: Use AppKit constants for these when they are available. static NSString * const windowDidChangeBackingPropertiesNotification = @"NSWindowDidChangeBackingPropertiesNotification"; @@ -1821,9 +1860,11 @@ static NSString * const backingPropertyOldScaleFactorKey = @"NSBackingPropertyOl [self removeWindowObservers]; [self addWindowObserversForWindow:window]; - + +#if defined(BUILDING_ON_SNOW_LEOPARD) if ([currentWindow _growBoxOwner] == self) [currentWindow _setShowOpaqueGrowBoxForOwner:nil]; +#endif } - (void)viewDidMoveToWindow @@ -1989,8 +2030,7 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I [self getRectsBeingDrawn:&rectsBeingDrawn count:&numRectsBeingDrawn]; for (NSInteger i = 0; i < numRectsBeingDrawn; ++i) { Region unpaintedRegion; - IntRect rect = enclosingIntRect(rectsBeingDrawn[i]); - drawingArea->paint(context, rect, unpaintedRegion); + drawingArea->paint(context, enclosingIntRect(rectsBeingDrawn[i]), unpaintedRegion); // 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. @@ -2117,7 +2157,8 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved location:[[flagsChangedEvent window] convertScreenToBase:[NSEvent mouseLocation]] modifierFlags:[flagsChangedEvent modifierFlags] timestamp:[flagsChangedEvent timestamp] windowNumber:[flagsChangedEvent windowNumber] context:[flagsChangedEvent context] eventNumber:0 clickCount:0 pressure:0]; - [self mouseMoved:fakeEvent]; + NativeWebMouseEvent webEvent(fakeEvent, self); + _data->_page->handleMouseEvent(webEvent); } - (NSInteger)conversationIdentifier @@ -2167,8 +2208,10 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (PassOwnPtr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy { +#if ENABLE(THREADED_SCROLLING) if ([self _shouldUseTiledDrawingArea]) return TiledCoreAnimationDrawingAreaProxy::create(_data->_page.get()); +#endif return DrawingAreaProxyImpl::create(_data->_page.get()); } @@ -2184,6 +2227,9 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (void)_processDidCrash { + if (_data->_layerHostingView) + [self _exitAcceleratedCompositingMode]; + [self _updateRemoteAccessibilityRegistration:NO]; } @@ -2434,7 +2480,8 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I [CATransaction begin]; [CATransaction setDisableActions:YES]; - [self addSubview:_data->_layerHostingView.get()]; + + [self addSubview:_data->_layerHostingView.get() positioned:NSWindowBelow relativeTo:nil]; // Create a root layer that will back the NSView. RetainPtr<CALayer> rootLayer(AdoptNS, [[CALayer alloc] init]); @@ -2519,7 +2566,7 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I if (pageHasCustomRepresentation) _data->_pdfViewController = PDFViewController::create(self); - + if (pageHasCustomRepresentation != hadPDFView) _data->_page->drawingArea()->pageCustomRepresentationChanged(); } @@ -2565,12 +2612,6 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag { - // We need to prevent re-entering this call to avoid crashing in AppKit. - // Given the asynchronous nature of WebKit2 this can now happen. - if (_data->_dragHasStarted) - return; - - _data->_dragHasStarted = YES; IntSize size([image size]); size.scale(1.0 / _data->_page->deviceScaleFactor()); [image setSize:size]; @@ -2585,7 +2626,121 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard] source:self slideBack:YES]; - _data->_dragHasStarted = NO; +} + +static bool matchesExtensionOrEquivalent(NSString *filename, NSString *extension) +{ + NSString *extensionAsSuffix = [@"." stringByAppendingString:extension]; + return hasCaseInsensitiveSuffix(filename, extensionAsSuffix) || (stringIsCaseInsensitiveEqualToString(extension, @"jpeg") + && hasCaseInsensitiveSuffix(filename, @".jpg")); +} + +- (void)_setPromisedData:(WebCore::Image *)image withFileName:(NSString *)filename withExtension:(NSString *)extension withTitle:(NSString *)title withURL:(NSString *)url withVisibleURL:(NSString *)visibleUrl withArchive:(WebCore::SharedBuffer*) archiveBuffer forPasteboard:(NSString *)pasteboardName + +{ + NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:pasteboardName]; + RetainPtr<NSMutableArray> types(AdoptNS, [[NSMutableArray alloc] initWithObjects:NSFilesPromisePboardType, nil]); + + [types.get() addObjectsFromArray:archiveBuffer ? PasteboardTypes::forImagesWithArchive() : PasteboardTypes::forImages()]; + [pasteboard declareTypes:types.get() owner:self]; + if (!matchesExtensionOrEquivalent(filename, extension)) + filename = [[filename stringByAppendingString:@"."] stringByAppendingString:extension]; + + [pasteboard setString:url forType:NSURLPboardType]; + [pasteboard setString:visibleUrl forType:PasteboardTypes::WebURLPboardType]; + [pasteboard setString:title forType:PasteboardTypes::WebURLNamePboardType]; + [pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:url], [NSArray arrayWithObject:title], nil] forType:PasteboardTypes::WebURLsWithTitlesPboardType]; + [pasteboard setPropertyList:[NSArray arrayWithObject:extension] forType:NSFilesPromisePboardType]; + + if (archiveBuffer) + [pasteboard setData:[archiveBuffer->createNSData() autorelease] forType:PasteboardTypes::WebArchivePboardType]; + + _data->_promisedImage = image; + _data->_promisedFilename = filename; + _data->_promisedURL = url; +} + +- (void)pasteboardChangedOwner:(NSPasteboard *)pasteboard +{ + _data->_promisedImage = 0; + _data->_promisedFilename = ""; + _data->_promisedURL = ""; +} + +- (void)pasteboard:(NSPasteboard *)pasteboard provideDataForType:(NSString *)type +{ + // FIXME: need to support NSRTFDPboardType + + if ([type isEqual:NSTIFFPboardType] && _data->_promisedImage) { + [pasteboard setData:(NSData *)_data->_promisedImage->getTIFFRepresentation() forType:NSTIFFPboardType]; + _data->_promisedImage = 0; + } +} + +static BOOL fileExists(NSString *path) +{ + struct stat statBuffer; + return !lstat([path fileSystemRepresentation], &statBuffer); +} + +static NSString *pathWithUniqueFilenameForPath(NSString *path) +{ + // "Fix" the filename of the path. + NSString *filename = filenameByFixingIllegalCharacters([path lastPathComponent]); + path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:filename]; + + if (fileExists(path)) { + // Don't overwrite existing file by appending "-n", "-n.ext" or "-n.ext.ext" to the filename. + NSString *extensions = nil; + NSString *pathWithoutExtensions; + NSString *lastPathComponent = [path lastPathComponent]; + NSRange periodRange = [lastPathComponent rangeOfString:@"."]; + + if (periodRange.location == NSNotFound) { + pathWithoutExtensions = path; + } else { + extensions = [lastPathComponent substringFromIndex:periodRange.location + 1]; + lastPathComponent = [lastPathComponent substringToIndex:periodRange.location]; + pathWithoutExtensions = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:lastPathComponent]; + } + + for (unsigned i = 1; ; i++) { + NSString *pathWithAppendedNumber = [NSString stringWithFormat:@"%@-%d", pathWithoutExtensions, i]; + path = [extensions length] ? [pathWithAppendedNumber stringByAppendingPathExtension:extensions] : pathWithAppendedNumber; + if (!fileExists(path)) + break; + } + } + + return path; +} + +- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination +{ + RetainPtr<NSFileWrapper> wrapper; + RetainPtr<NSData> data; + + if (_data->_promisedImage) { + data.adoptNS(_data->_promisedImage->data()->createNSData()); + wrapper.adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:data.get()]); + [wrapper.get() setPreferredFilename:_data->_promisedFilename]; + } + + if (!wrapper) { + LOG_ERROR("Failed to create image file."); + return nil; + } + + // FIXME: Report an error if we fail to create a file. + NSString *path = [[dropDestination path] stringByAppendingPathComponent:[wrapper.get() preferredFilename]]; + path = pathWithUniqueFilenameForPath(path); + if (![wrapper.get() writeToFile:path atomically:NO updateFilenames:YES]) + LOG_ERROR("Failed to create image file via -[NSFileWrapper writeToFile:atomically:updateFilenames:]"); + + if (!_data->_promisedURL.isEmpty()) + WebCore::setMetadataURL(_data->_promisedURL, "", String(path)); + + return [NSArray arrayWithObject:[path lastPathComponent]]; } - (void)_updateSecureInputState @@ -2643,10 +2798,17 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (void)_didChangeScrollbarsForMainFrame { +#if defined(BUILDING_ON_SNOW_LEOPARD) [self _updateGrowBoxForWindowFrameChange]; +#endif } #if ENABLE(FULLSCREEN_API) +- (BOOL)hasFullScreenWindowController +{ + return (bool)_data->_fullScreenWindowController; +} + - (WKFullScreenWindowController*)fullScreenWindowController { if (!_data->_fullScreenWindowController) { @@ -2700,7 +2862,7 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (void)handleCorrectionPanelResult:(NSString*)result { - _data->_page->handleCorrectionPanelResult(result); + _data->_page->handleAlternativeTextUIResult(result); } @end @@ -2748,8 +2910,8 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I _data->_pageClient = PageClientImpl::create(self); _data->_page = toImpl(contextRef)->createWebPage(_data->_pageClient.get(), toImpl(pageGroupRef)); - _data->_page->initializeWebPage(); _data->_page->setIntrinsicDeviceScaleFactor([self _intrinsicDeviceScaleFactor]); + _data->_page->initializeWebPage(); #if ENABLE(FULLSCREEN_API) _data->_page->fullScreenManager()->setWebView(self); #endif @@ -2759,12 +2921,10 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I [self _registerDraggedTypes]; if ([self _shouldUseTiledDrawingArea]) { - CALayer *layer = [CALayer layer]; - layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite); - self.layer = layer; - - self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawNever; self.wantsLayer = YES; + + // Explicitly set the layer contents placement so AppKit will make sure that our layer has masksToBounds set to YES. + self.layerContentsPlacement = NSViewLayerContentsPlacementTopLeft; } WebContext::statistics().wkViewCount++; @@ -2772,6 +2932,21 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I return self; } +#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +- (BOOL)wantsUpdateLayer +{ + return [self _shouldUseTiledDrawingArea]; +} + +- (void)updateLayer +{ + self.layer.backgroundColor = CGColorGetConstantColor(kCGColorWhite); + + if (DrawingAreaProxy* drawingArea = _data->_page->drawingArea()) + drawingArea->waitForPossibleGeometryUpdate(); +} +#endif + - (WKPageRef)pageRef { return toAPI(_data->_page.get()); diff --git a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h index 83346d3f1..6b6eb6bf4 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h +++ b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h @@ -35,6 +35,8 @@ namespace CoreIPC { namespace WebCore { struct KeypressCommand; + class Image; + class SharedBuffer; } namespace WebKit { @@ -78,6 +80,7 @@ namespace WebKit { - (void)_findStringInCustomRepresentation:(NSString *)string withFindOptions:(WebKit::FindOptions)options maxMatchCount:(NSUInteger)count; - (void)_countStringMatchesInCustomRepresentation:(NSString *)string withFindOptions:(WebKit::FindOptions)options maxMatchCount:(NSUInteger)count; - (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag; +- (void)_setPromisedData:(WebCore::Image *)image withFileName:(NSString *)filename withExtension:(NSString *)extension withTitle:(NSString *)title withURL:(NSString *)url withVisibleURL:(NSString *)visibleUrl withArchive:(WebCore::SharedBuffer*) archiveBuffer forPasteboard:(NSString *)pasteboardName; - (void)_updateSecureInputState; - (void)_updateTextInputStateIncludingSecureInputState:(BOOL)updateSecureInputState; - (void)_resetTextInputState; @@ -85,6 +88,7 @@ namespace WebKit { - (void)_didChangeScrollbarsForMainFrame; #if ENABLE(FULLSCREEN_API) +- (BOOL)hasFullScreenWindowController; - (WKFullScreenWindowController*)fullScreenWindowController; - (void)closeFullScreenWindowController; #endif diff --git a/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h b/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h index 1007f3a78..4c32d0f1b 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquicknetworkreply_p.h @@ -29,7 +29,7 @@ #include <QNetworkAccessManager> #include <QObject> #include <QWeakPointer> -#include <QtDeclarative/qdeclarativelist.h> +#include <QtQml/qqmllist.h> #include <QtQuick/qquickitem.h> class QWEBKIT_EXPORT QQuickNetworkReply : public QObject { diff --git a/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h b/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h index 7df66f569..69a2d48df 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquicknetworkrequest_p.h @@ -22,10 +22,10 @@ #define qquicknetworkrequest_p_h #include "QtNetworkRequestData.h" -#include "RefPtr.h" +#include "wtf/RefPtr.h" #include "qwebkitglobal.h" #include <QObject> -#include <QtDeclarative/qdeclarativelist.h> +#include <QtQml/qqmllist.h> #include <QtQuick/qquickitem.h> class QWEBKIT_EXPORT QQuickNetworkRequest : public QObject { diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp index 9293c972f..203c72b7e 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp @@ -23,18 +23,18 @@ #include "LayerTreeHostProxy.h" #include "QtWebPageEventHandler.h" +#include "QtWebPageSGNode.h" #include "TransformationMatrix.h" #include "WebLayerTreeRenderer.h" +#include "WebPageProxy.h" #include "qquickwebpage_p_p.h" #include "qquickwebview_p.h" -#include <QPolygonF> #include <QtQuick/QQuickCanvas> -#include <QtQuick/QSGGeometryNode> -#include <QtQuick/QSGMaterial> -#include <private/qsgrendernode_p.h> + +using namespace WebKit; QQuickWebPage::QQuickWebPage(QQuickWebView* viewportItem) - : QQuickItem(viewportItem) + : QQuickItem(viewportItem->contentItem()) , d(new QQuickWebPagePrivate(this, viewportItem)) { setFlag(ItemHasContents); @@ -66,98 +66,16 @@ void QQuickWebPagePrivate::initialize(WebKit::WebPageProxy* webPageProxy) eventHandler.reset(new QtWebPageEventHandler(toAPI(webPageProxy), q, viewportItem)); } -void QQuickWebPagePrivate::setDrawingAreaSize(const QSize& size) +void QQuickWebPagePrivate::paint(QPainter* painter) { - DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); - if (!drawingArea) + if (!webPageProxy->drawingArea()) return; - drawingArea->setSize(WebCore::IntSize(size), WebCore::IntSize()); -} -void QQuickWebPagePrivate::paint(QPainter* painter) -{ - if (webPageProxy->drawingArea()) - webPageProxy->drawingArea()->paintLayerTree(painter); + LayerTreeHostProxy* layerTreeHostProxy = webPageProxy->drawingArea()->layerTreeHostProxy(); + if (layerTreeHostProxy->layerTreeRenderer()) + layerTreeHostProxy->layerTreeRenderer()->paintToGraphicsContext(painter); } -struct PageProxyNode : public QSGRenderNode { - PageProxyNode(PassRefPtr<WebLayerTreeRenderer> renderer) - : m_renderer(renderer) - , m_scale(1) - { - } - - virtual StateFlags changedStates() - { - return StateFlags(StencilState) | ColorState | BlendState; - } - - virtual void render(const RenderState&) - { - QMatrix4x4 renderMatrix = matrix() ? *matrix() : QMatrix4x4(); - - // Have to apply render scale manualy because it is not applied on page item. - // http://trac.webkit.org/changeset/104450 - renderMatrix.scale(m_scale); - - // FIXME: Support non-rectangular clippings. - layerTreeRenderer()->paintToCurrentGLContext(renderMatrix, inheritedOpacity(), clipRect()); - } - - ~PageProxyNode() - { - layerTreeRenderer()->purgeGLResources(); - } - - WebLayerTreeRenderer* layerTreeRenderer() const { return m_renderer.get(); } - void setScale(float scale) { m_scale = scale; } - -private: - QRectF clipRect() const - { - // Start with an invalid rect. - QRectF resultRect(0, 0, -1, -1); - - for (const QSGClipNode* clip = clipList(); clip; clip = clip->clipList()) { - QMatrix4x4 clipMatrix; - if (clip->matrix()) - clipMatrix = *clip->matrix(); - QRectF currentClip; - - if (clip->isRectangular()) - currentClip = clipMatrix.mapRect(clip->clipRect()); - else { - const QSGGeometry* geometry = clip->geometry(); - // Assume here that clipNode has only coordinate data. - const QSGGeometry::Point2D* geometryPoints = geometry->vertexDataAsPoint2D(); - - // Clip region should be at least triangle to make valid clip. - if (geometry->vertexCount() < 3) - continue; - - QPolygonF polygon; - - for (int i = 0; i < geometry->vertexCount(); i++) - polygon.append(clipMatrix.map(QPoint(geometryPoints[i].x, geometryPoints[i].y))); - currentClip = polygon.boundingRect(); - } - - if (currentClip.isEmpty()) - continue; - - if (resultRect.isValid()) - resultRect &= currentClip; - else - resultRect = currentClip; - } - - return resultRect; - } - - RefPtr<WebLayerTreeRenderer> m_renderer; - float m_scale; -}; - QSGNode* QQuickWebPage::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) { if (!d->webPageProxy->drawingArea()) @@ -166,21 +84,16 @@ QSGNode* QQuickWebPage::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) LayerTreeHostProxy* layerTreeHostProxy = d->webPageProxy->drawingArea()->layerTreeHostProxy(); WebLayerTreeRenderer* renderer = layerTreeHostProxy->layerTreeRenderer(); - PageProxyNode* node = static_cast<PageProxyNode*>(oldNode); - - if (node && node->layerTreeRenderer() != renderer) { - // This means that LayerTreeHostProxy was deleted and recreated while old paint node survived. - // This could happen if web process have crashed. In this case we have to recreate paint node. - delete node; - node = 0; - } - - renderer->syncRemoteContent(); - + QtWebPageSGNode* node = static_cast<QtWebPageSGNode*>(oldNode); if (!node) - node = new PageProxyNode(renderer); + node = new QtWebPageSGNode(); + node->setRenderer(renderer); + renderer->syncRemoteContent(); node->setScale(d->contentsScale); + QColor backgroundColor = d->webPageProxy->drawsTransparentBackground() ? Qt::transparent : Qt::white; + QRectF backgroundRect(QPointF(0, 0), d->contentsSize); + node->setBackground(backgroundRect, backgroundColor); return node; } @@ -197,7 +110,6 @@ void QQuickWebPage::setContentsSize(const QSizeF& size) d->contentsSize = size; d->updateSize(); - d->setDrawingAreaSize(d->contentsSize.toSize()); } const QSizeF& QQuickWebPage::contentsSize() const @@ -234,6 +146,9 @@ void QQuickWebPagePrivate::updateSize() QSizeF scaledSize = contentsSize * contentsScale; q->setSize(scaledSize); viewportItem->updateContentsSize(scaledSize); + DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); + if (drawingArea && drawingArea->layerTreeHostProxy()) + drawingArea->layerTreeHostProxy()->setContentsSize(WebCore::FloatSize(contentsSize.width(), contentsSize.height())); } QQuickWebPagePrivate::~QQuickWebPagePrivate() diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h index 9d791ac25..3a112d62b 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p.h @@ -28,9 +28,12 @@ class QQuickWebPagePrivate; class QQuickWebView; -class QtWebPageEventHandler; class QWebPreferences; +namespace WebKit { +class QtWebPageEventHandler; +} + class QWEBKIT_EXPORT QQuickWebPage : public QQuickItem { Q_OBJECT public: @@ -45,7 +48,7 @@ public: QTransform transformFromItem() const; QTransform transformToItem() const; - QtWebPageEventHandler* eventHandler() const; + WebKit::QtWebPageEventHandler* eventHandler() const; protected: virtual QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h index b28174124..e4be37364 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage_p_p.h @@ -27,9 +27,8 @@ namespace WebKit { class WebPageProxy; class QtViewportInteractionEngine; -} - class QtWebPageEventHandler; +} class QQuickWebPagePrivate { public: @@ -37,15 +36,13 @@ public: ~QQuickWebPagePrivate(); void initialize(WebKit::WebPageProxy*); - void setDrawingAreaSize(const QSize&); void updateSize(); - void paintToCurrentGLContext(const QTransform&, float opacity, const QRectF& clipRect); void paint(QPainter*); void resetPaintNode(); - QScopedPointer<QtWebPageEventHandler> eventHandler; + QScopedPointer<WebKit::QtWebPageEventHandler> eventHandler; QQuickWebPage* const q; QQuickWebView* const viewportItem; WebKit::WebPageProxy* webPageProxy; diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp index 6e518ff12..b1b465526 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp @@ -23,12 +23,19 @@ #include "DownloadProxy.h" #include "DrawingAreaProxyImpl.h" +#include "QtDialogRunner.h" #include "QtDownloadManager.h" +#include "QtViewportInteractionEngine.h" #include "QtWebContext.h" #include "QtWebIconDatabaseClient.h" #include "QtWebPageEventHandler.h" +#include "QtWebPageLoadClient.h" +#include "QtWebPagePolicyClient.h" #include "UtilsQt.h" #include "WebBackForwardList.h" +#if ENABLE(FULLSCREEN_API) +#include "WebFullScreenManagerProxy.h" +#endif #include "WebPageGroup.h" #include "WebPreferences.h" @@ -45,18 +52,21 @@ #include "qwebviewportinfo_p.h" #include <JavaScriptCore/InitializeThreading.h> -#include <QDeclarativeEngine> -#include <QFileDialog> -#include <QtQuick/QQuickCanvas> +#include <QDateTime> #include <WebCore/IntPoint.h> #include <WebCore/IntRect.h> #include <WKOpenPanelResultListener.h> #include <wtf/Assertions.h> +#include <wtf/MainThread.h> #include <wtf/text/WTFString.h> using namespace WebCore; +using namespace WebKit; static bool s_flickableViewportEnabled = true; +static const int kAxisLockSampleCount = 5; +static const qreal kAxisLockVelocityThreshold = 300; +static const qreal kAxisLockVelocityDirectionThreshold = 50; static QQuickWebViewPrivate* createPrivateObject(QQuickWebView* publicObject) { @@ -65,9 +75,80 @@ static QQuickWebViewPrivate* createPrivateObject(QQuickWebView* publicObject) return new QQuickWebViewLegacyPrivate(publicObject); } +QQuickWebViewPrivate::FlickableAxisLocker::FlickableAxisLocker() + : m_allowedDirection(QQuickFlickable::AutoFlickDirection) + , m_sampleCount(0) +{ +} + +QVector2D QQuickWebViewPrivate::FlickableAxisLocker::touchVelocity(const QTouchEvent* event) +{ + static bool touchVelocityAvailable = event->device()->capabilities().testFlag(QTouchDevice::Velocity); + const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first(); + + if (touchVelocityAvailable) + return touchPoint.velocity(); + + const QLineF movementLine(touchPoint.screenPos(), m_initialScreenPosition); + const qint64 elapsed = m_time.elapsed(); + + if (!elapsed) + return QVector2D(0, 0); + + // Calculate an approximate velocity vector in the unit of pixel / second. + return QVector2D(1000 * movementLine.dx() / elapsed, 1000 * movementLine.dy() / elapsed); +} + +void QQuickWebViewPrivate::FlickableAxisLocker::update(const QTouchEvent* event) +{ + ASSERT(event->touchPoints().size() == 1); + const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first(); + + ++m_sampleCount; + + if (m_sampleCount == 1) { + m_initialScreenPosition = touchPoint.screenPos(); + m_time.restart(); + return; + } + + if (m_sampleCount > kAxisLockSampleCount + || m_allowedDirection == QQuickFlickable::HorizontalFlick + || m_allowedDirection == QQuickFlickable::VerticalFlick) + return; + + QVector2D velocity = touchVelocity(event); + + qreal directionIndicator = qAbs(velocity.x()) - qAbs(velocity.y()); + + if (velocity.length() > kAxisLockVelocityThreshold && qAbs(directionIndicator) > kAxisLockVelocityDirectionThreshold) + m_allowedDirection = (directionIndicator > 0) ? QQuickFlickable::HorizontalFlick : QQuickFlickable::VerticalFlick; +} + +void QQuickWebViewPrivate::FlickableAxisLocker::setReferencePosition(const QPointF& position) +{ + m_lockReferencePosition = position; +} + +void QQuickWebViewPrivate::FlickableAxisLocker::reset() +{ + m_allowedDirection = QQuickFlickable::AutoFlickDirection; + m_sampleCount = 0; +} + +QPointF QQuickWebViewPrivate::FlickableAxisLocker::adjust(const QPointF& position) +{ + if (m_allowedDirection == QQuickFlickable::HorizontalFlick) + return QPointF(position.x(), m_lockReferencePosition.y()); + + if (m_allowedDirection == QQuickFlickable::VerticalFlick) + return QPointF(m_lockReferencePosition.x(), position.y()); + + return position; +} + QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport) : q_ptr(viewport) - , flickProvider(0) , alertDialog(0) , confirmDialog(0) , promptDialog(0) @@ -75,14 +156,15 @@ QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport) , certificateVerificationDialog(0) , itemSelector(0) , proxyAuthenticationDialog(0) - , userDidOverrideContentWidth(false) - , userDidOverrideContentHeight(false) + , filePicker(0) + , databaseQuotaDialog(0) + , m_useDefaultContentItemSize(true) , m_navigatorQtObjectEnabled(false) , m_renderToOffscreenBuffer(false) - , m_loadStartedSignalSent(false) - , m_dialogRunnerActive(false) + , m_dialogActive(false) { - viewport->setFlags(QQuickItem::ItemClipsChildrenToShape); + viewport->setClip(true); + viewport->setPixelAligned(true); QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged())); QObject::connect(viewport, SIGNAL(urlChanged()), viewport, SLOT(_q_onUrlChanged())); pageView.reset(new QQuickWebPage(viewport)); @@ -104,6 +186,9 @@ void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pa context = contextRef ? QtWebContext::create(toImpl(contextRef)) : QtWebContext::defaultContext(); webPageProxy = context->createWebPage(&pageClient, pageGroup.get()); +#if ENABLE(FULLSCREEN_API) + webPageProxy->fullScreenManager()->setWebView(q_ptr); +#endif QQuickWebPagePrivate* const pageViewPrivate = pageView.data()->d; pageViewPrivate->initialize(webPageProxy.get()); @@ -135,26 +220,16 @@ bool QQuickWebViewPrivate::transparentBackground() const return webPageProxy->drawsTransparentBackground(); } -void QQuickWebViewPrivate::enableMouseEvents() -{ - Q_Q(QQuickWebView); - q->setAcceptedMouseButtons(Qt::MouseButtonMask); - q->setAcceptHoverEvents(true); -} - -void QQuickWebViewPrivate::disableMouseEvents() -{ - Q_Q(QQuickWebView); - q->setAcceptedMouseButtons(Qt::NoButton); - q->setAcceptHoverEvents(false); -} - QPointF QQuickWebViewPrivate::pageItemPos() { ASSERT(pageView); return pageView->pos(); } +/*! + \qmlsignal WebView::loadingChanged(WebLoadRequest request) +*/ + void QQuickWebViewPrivate::loadDidSucceed() { Q_Q(QQuickWebView); @@ -194,14 +269,6 @@ void QQuickWebViewPrivate::_q_onIconChangedForPageURL(const QUrl& pageURL, const setIcon(iconURL); } -void QQuickWebViewPrivate::didChangeLoadingState(QWebLoadRequest* loadRequest) -{ - Q_Q(QQuickWebView); - ASSERT(q->loading() == (loadRequest->status() == QQuickWebView::LoadStartedStatus)); - emit q->loadingChanged(loadRequest); - m_loadStartedSignalSent = loadRequest->status() == QQuickWebView::LoadStartedStatus; -} - void QQuickWebViewPrivate::didChangeBackForwardList() { navigationHistory->d->reset(); @@ -210,18 +277,18 @@ void QQuickWebViewPrivate::didChangeBackForwardList() void QQuickWebViewPrivate::processDidCrash() { pageView->eventHandler()->resetGestureRecognizers(); + pageLoadClient->completeLoadWhenProcessDidCrashIfNeeded(); + QUrl url(KURL(WebCore::ParsedURLString, webPageProxy->urlAtProcessExit())); - if (m_loadStartedSignalSent) { - QWebLoadRequest loadRequest(url, QQuickWebView::LoadFailedStatus, QLatin1String("The web process crashed."), QQuickWebView::InternalErrorDomain, 0); - didChangeLoadingState(&loadRequest); - } qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(url.toString(QUrl::RemoveUserInfo))); } void QQuickWebViewPrivate::didRelaunchProcess() { qWarning("WARNING: The web process has been successfully restarted."); - pageView->d->setDrawingAreaSize(viewSize()); + + webPageProxy->drawingArea()->setSize(viewSize(), IntSize()); + updateViewportSize(); } PassOwnPtr<DrawingAreaProxy> QQuickWebViewPrivate::createDrawingAreaProxy() @@ -365,59 +432,52 @@ void QQuickWebViewPrivate::execDialogRunner(QtDialogRunner& dialogRunner) setViewInAttachedProperties(dialogRunner.dialog()); disableMouseEvents(); - m_dialogRunnerActive = true; + m_dialogActive = true; dialogRunner.exec(); - m_dialogRunnerActive = false; + m_dialogActive = false; enableMouseEvents(); } void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type) { -#ifndef QT_NO_FILEDIALOG Q_Q(QQuickWebView); - openPanelResultListener = listenerRef; - - // Qt does not support multiple files suggestion, so we get just the first suggestion. - QString selectedFileName; - if (!selectedFileNames.isEmpty()) - selectedFileName = selectedFileNames.at(0); - Q_ASSERT(!fileDialog); + if (!filePicker) + return; - QWindow* window = q->canvas(); - if (!window) + QtDialogRunner dialogRunner; + if (!dialogRunner.initForFilePicker(filePicker, q, selectedFileNames, (type == QtWebPageUIClient::MultipleFilesSelection))) return; - fileDialog = new QFileDialog(0, QString(), selectedFileName); - fileDialog->window()->winId(); // Ensure that the dialog has a window - Q_ASSERT(fileDialog->window()->windowHandle()); - fileDialog->window()->windowHandle()->setTransientParent(window); + execDialogRunner(dialogRunner); - fileDialog->open(q, SLOT(_q_onOpenPanelFilesSelected())); + if (dialogRunner.wasAccepted()) { + QStringList selectedPaths = dialogRunner.filePaths(); - q->connect(fileDialog, SIGNAL(finished(int)), SLOT(_q_onOpenPanelFinished(int))); -#endif -} - -void QQuickWebViewPrivate::_q_onOpenPanelFilesSelected() -{ - const QStringList fileList = fileDialog->selectedFiles(); - Vector<RefPtr<APIObject> > wkFiles(fileList.size()); + Vector<RefPtr<APIObject> > wkFiles(selectedPaths.size()); + for (unsigned i = 0; i < selectedPaths.size(); ++i) + wkFiles[i] = WebURL::create(QUrl::fromLocalFile(selectedPaths.at(i)).toString()); - for (unsigned i = 0; i < fileList.size(); ++i) - wkFiles[i] = WebURL::create(QUrl::fromLocalFile(fileList.at(i)).toString()); + WKOpenPanelResultListenerChooseFiles(listenerRef, toAPI(ImmutableArray::adopt(wkFiles).leakRef())); + } else + WKOpenPanelResultListenerCancel(listenerRef); - WKOpenPanelResultListenerChooseFiles(openPanelResultListener, toAPI(ImmutableArray::adopt(wkFiles).leakRef())); } -void QQuickWebViewPrivate::_q_onOpenPanelFinished(int result) +quint64 QQuickWebViewPrivate::exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) { - if (result == QDialog::Rejected) - WKOpenPanelResultListenerCancel(openPanelResultListener); + if (!databaseQuotaDialog) + return 0; + + Q_Q(QQuickWebView); + QtDialogRunner dialogRunner; + if (!dialogRunner.initForDatabaseQuotaDialog(databaseQuotaDialog, q, databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage)) + return 0; + + execDialogRunner(dialogRunner); - fileDialog->deleteLater(); - fileDialog = 0; + return dialogRunner.wasAccepted() ? dialogRunner.databaseQuota() : 0; } void QQuickWebViewPrivate::setViewInAttachedProperties(QObject* object) @@ -462,12 +522,27 @@ void QQuickWebViewPrivate::setNavigatorQtObjectEnabled(bool enabled) context->setNavigatorQtObjectEnabled(webPageProxy.get(), enabled); } +QPointF QQuickWebViewPrivate::contentPos() const +{ + Q_Q(const QQuickWebView); + return QPointF(q->contentX(), q->contentY()); +} + +void QQuickWebViewPrivate::setContentPos(const QPointF& pos) +{ + Q_Q(QQuickWebView); + q->setContentX(pos.x()); + q->setContentY(pos.y()); +} + QRect QQuickWebViewPrivate::visibleContentsRect() const { Q_Q(const QQuickWebView); const QRectF visibleRect(q->boundingRect().intersected(pageView->boundingRect())); - return q->mapRectToWebContent(visibleRect).toAlignedRect(); + // We avoid using toAlignedRect() because it produces inconsistent width and height. + QRectF mappedRect(q->mapRectToWebContent(visibleRect)); + return QRect(floor(mappedRect.x()), floor(mappedRect.y()), floor(mappedRect.width()), floor(mappedRect.height())); } WebCore::IntSize QQuickWebViewPrivate::viewSize() const @@ -475,6 +550,15 @@ WebCore::IntSize QQuickWebViewPrivate::viewSize() const return WebCore::IntSize(pageView->width(), pageView->height()); } +/*! + \internal + + \qmlsignal WebViewExperimental::onMessageReceived(var message) + + \brief Emitted when JavaScript code executing on the web page calls navigator.qt.postMessage(). + + \sa postMessage +*/ void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& message) { QVariantMap variantMap; @@ -486,6 +570,12 @@ void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& QQuickWebViewLegacyPrivate::QQuickWebViewLegacyPrivate(QQuickWebView* viewport) : QQuickWebViewPrivate(viewport) { + // Default values for the Legacy view. + attributes.devicePixelRatio = 1; + attributes.initialScale = 1; + attributes.minimumScale = 1; + attributes.maximumScale = 1; + attributes.userScalable = 0; } void QQuickWebViewLegacyPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef) @@ -505,16 +595,46 @@ void QQuickWebViewLegacyPrivate::updateViewportSize() // The fixed layout is handled by the FrameView and the drawing area doesn't behave differently // whether 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()->setVisibleContentsRectForScaling(IntRect(IntPoint(), viewportSize), 1); + webPageProxy->drawingArea()->setSize(viewportSize, IntSize()); + webPageProxy->drawingArea()->setVisibleContentsRect(IntRect(IntPoint(), viewportSize), 1, FloatPoint()); +} + +void QQuickWebViewLegacyPrivate::enableMouseEvents() +{ + Q_Q(QQuickWebView); + q->setAcceptedMouseButtons(Qt::MouseButtonMask); + q->setAcceptHoverEvents(true); +} + +void QQuickWebViewLegacyPrivate::disableMouseEvents() +{ + Q_Q(QQuickWebView); + q->setAcceptedMouseButtons(Qt::NoButton); + q->setAcceptHoverEvents(false); +} + +qreal QQuickWebViewLegacyPrivate::zoomFactor() const +{ + return webPageProxy->pageZoomFactor(); +} + +void QQuickWebViewLegacyPrivate::setZoomFactor(qreal factor) +{ + webPageProxy->setPageZoomFactor(factor); } QQuickWebViewFlickablePrivate::QQuickWebViewFlickablePrivate(QQuickWebView* viewport) : QQuickWebViewPrivate(viewport) - , postTransitionState(adoptPtr(new PostTransitionState(this))) - , isTransitioningToNewPage(false) , pageIsSuspended(true) , loadSuccessDispatchIsPending(false) { + // Disable mouse events on the flickable web view so we do not + // select text during pan gestures on platforms which send both + // touch and mouse events simultaneously. + // FIXME: Temporary workaround code which should be removed when + // bug http://codereview.qt-project.org/21896 is fixed. + viewport->setAcceptedMouseButtons(Qt::NoButton); + viewport->setAcceptHoverEvents(false); } QQuickWebViewFlickablePrivate::~QQuickWebViewFlickablePrivate() @@ -530,50 +650,42 @@ void QQuickWebViewFlickablePrivate::initialize(WKContextRef contextRef, WKPageGr QPointF QQuickWebViewFlickablePrivate::pageItemPos() { + Q_Q(QQuickWebView); // Flickable moves its contentItem so we need to take that position into account, // as well as the potential displacement of the page on the contentItem because // of additional QML items. - qreal xPos = flickProvider->contentItem()->x() + pageView->x(); - qreal yPos = flickProvider->contentItem()->y() + pageView->y(); + qreal xPos = q->contentItem()->x() + pageView->x(); + qreal yPos = q->contentItem()->y() + pageView->y(); return QPointF(xPos, yPos); } void QQuickWebViewFlickablePrivate::updateContentsSize(const QSizeF& size) { - ASSERT(flickProvider); + Q_Q(QQuickWebView); // Make sure that the contentItem is sized to the page // if the user did not add other flickable items in QML. // If the user adds items in QML he has to make sure to - // also bind the contentWidth and contentHeight accordingly. + // disable the default content item size property on the WebView + // and bind the contentWidth and contentHeight accordingly. // This is in accordance with normal QML Flickable behaviour. - if (!userDidOverrideContentWidth) - flickProvider->setContentWidth(size.width()); - if (!userDidOverrideContentHeight) - flickProvider->setContentHeight(size.height()); + if (!m_useDefaultContentItemSize) + return; + + q->setContentWidth(size.width()); + q->setContentHeight(size.height()); } void QQuickWebViewFlickablePrivate::onComponentComplete() { Q_Q(QQuickWebView); - ASSERT(!flickProvider); - flickProvider = new QtFlickProvider(q, pageView.data()); - - // Propagate flickable signals. - const QQuickWebViewExperimental* experimental = q->experimental(); - QObject::connect(flickProvider, SIGNAL(contentWidthChanged()), experimental, SIGNAL(contentWidthChanged())); - QObject::connect(flickProvider, SIGNAL(contentHeightChanged()), experimental, SIGNAL(contentHeightChanged())); - QObject::connect(flickProvider, SIGNAL(contentXChanged()), experimental, SIGNAL(contentXChanged())); - QObject::connect(flickProvider, SIGNAL(contentYChanged()), experimental, SIGNAL(contentYChanged())); - - interactionEngine.reset(new QtViewportInteractionEngine(q, pageView.data(), flickProvider)); + interactionEngine.reset(new QtViewportInteractionEngine(q, pageView.data())); pageView->eventHandler()->setViewportInteractionEngine(interactionEngine.data()); QObject::connect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), q, SLOT(_q_suspend())); QObject::connect(interactionEngine.data(), SIGNAL(contentResumeRequested()), q, SLOT(_q_resume())); - QObject::connect(interactionEngine.data(), SIGNAL(contentWasMoved(const QPointF&)), q, SLOT(_q_commitPositionChange(const QPointF&))); - QObject::connect(interactionEngine.data(), SIGNAL(contentWasScaled()), q, SLOT(_q_commitScaleChange())); + QObject::connect(interactionEngine.data(), SIGNAL(contentViewportChanged(QPointF)), q, SLOT(_q_contentViewportChanged(QPointF))); _q_resume(); @@ -594,33 +706,47 @@ void QQuickWebViewFlickablePrivate::loadDidSucceed() QQuickWebViewPrivate::loadDidSucceed(); else loadSuccessDispatchIsPending = true; - } void QQuickWebViewFlickablePrivate::loadDidCommit() { // Due to entering provisional load before committing, we // might actually be suspended here. - - isTransitioningToNewPage = true; } void QQuickWebViewFlickablePrivate::didFinishFirstNonEmptyLayout() { - if (!pageIsSuspended) { - isTransitioningToNewPage = false; - postTransitionState->apply(); - } } -void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::ViewportArguments& args) +void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::ViewportAttributes& newAttributes) { - viewportArguments = args; + Q_Q(QQuickWebView); - if (isTransitioningToNewPage) - return; + QSize viewportSize = q->boundingRect().size().toSize(); + + // FIXME: Revise these when implementing fit-to-width. + WebCore::ViewportAttributes attr = newAttributes; + WebCore::restrictMinimumScaleFactorToViewportSize(attr, viewportSize); + WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attr); + + // FIXME: Resetting here can reset more than needed. For instance it will end deferrers. + // This needs to be revised at some point. + interactionEngine->reset(); + + interactionEngine->setContentToDevicePixelRatio(attr.devicePixelRatio); - interactionEngine->applyConstraints(computeViewportConstraints()); + interactionEngine->setAllowsUserScaling(!!attr.userScalable); + interactionEngine->setCSSScaleBounds(attr.minimumScale, attr.maximumScale); + + if (!interactionEngine->hadUserInteraction() && !pageIsSuspended) + interactionEngine->setCSSScale(attr.initialScale); + + this->attributes = attr; + q->experimental()->viewportInfo()->didUpdateViewportConstraints(); + + // If the web app successively changes the viewport on purpose + // it wants to be in control and we should disable animations. + interactionEngine->ensureContentWithinViewportBoundary(/*immediate*/ true); } void QQuickWebViewFlickablePrivate::updateViewportSize() @@ -631,46 +757,36 @@ void QQuickWebViewFlickablePrivate::updateViewportSize() if (viewportSize.isEmpty() || !interactionEngine) return; - flickProvider->setViewportSize(viewportSize); + WebPreferences* wkPrefs = webPageProxy->pageGroup()->preferences(); + wkPrefs->setDeviceWidth(viewportSize.width()); + wkPrefs->setDeviceHeight(viewportSize.height()); // Let the WebProcess know about the new viewport size, so that // it can resize the content accordingly. webPageProxy->setViewportSize(viewportSize); - interactionEngine->applyConstraints(computeViewportConstraints()); - _q_commitScaleChange(); + _q_contentViewportChanged(QPointF()); } -void QQuickWebViewFlickablePrivate::_q_commitScaleChange() +void QQuickWebViewFlickablePrivate::_q_contentViewportChanged(const QPointF& trajectoryVector) { - DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); - if (!drawingArea) - return; - Q_Q(QQuickWebView); // This is only for our QML ViewportInfo debugging API. q->experimental()->viewportInfo()->didUpdateCurrentScale(); - const QRect visibleRect(visibleContentsRect()); - float scale = pageView->contentsScale(); - - drawingArea->setVisibleContentsRectForScaling(visibleRect, scale); - webPageProxy->setFixedVisibleContentRect(visibleRect); -} - -void QQuickWebViewPrivate::_q_commitPositionChange(const QPointF& trajectoryVector) -{ DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); if (!drawingArea) return; const QRect visibleRect(visibleContentsRect()); - drawingArea->setVisibleContentsRectForPanning(visibleRect, trajectoryVector); + float scale = pageView->contentsScale(); - if (!trajectoryVector.isNull()) - return; + QRectF accurateVisibleRect(q->boundingRect()); + accurateVisibleRect.translate(contentPos()); + drawingArea->setVisibleContentsRect(visibleRect, scale, trajectoryVector, FloatPoint(accurateVisibleRect.x(), accurateVisibleRect.y())); - webPageProxy->setFixedVisibleContentRect(visibleRect); + // Ensure that updatePaintNode is always called before painting. + pageView->update(); } void QQuickWebViewFlickablePrivate::_q_suspend() @@ -687,99 +803,35 @@ void QQuickWebViewFlickablePrivate::_q_resume() pageIsSuspended = false; webPageProxy->resumeActiveDOMObjectsAndAnimations(); - if (isTransitioningToNewPage) { - isTransitioningToNewPage = false; - postTransitionState->apply(); - } - - // FIXME: Revise this. - _q_commitScaleChange(); + _q_contentViewportChanged(QPointF()); } void QQuickWebViewFlickablePrivate::pageDidRequestScroll(const QPoint& pos) { - if (isTransitioningToNewPage) { - postTransitionState->position = pos; - return; - } - interactionEngine->pagePositionRequest(pos); } void QQuickWebViewFlickablePrivate::didChangeContentsSize(const QSize& newSize) { Q_Q(QQuickWebView); - // FIXME: We probably want to handle suspend here as well - if (isTransitioningToNewPage) { - postTransitionState->contentsSize = newSize; - return; - } - pageView->setContentsSize(newSize); q->experimental()->viewportInfo()->didUpdateContentsSize(); } -QtViewportInteractionEngine::Constraints QQuickWebViewFlickablePrivate::computeViewportConstraints() -{ - Q_Q(QQuickWebView); - - QtViewportInteractionEngine::Constraints newConstraints; - QSize availableSize = q->boundingRect().size().toSize(); - - // Return default values for zero sized viewport. - if (availableSize.isEmpty()) - return newConstraints; - - WebPreferences* wkPrefs = webPageProxy->pageGroup()->preferences(); - - // FIXME: Remove later; Hardcode some values for now to make sure the DPI adjustment is being tested. - wkPrefs->setDeviceDPI(240); - wkPrefs->setDeviceWidth(480); - wkPrefs->setDeviceHeight(720); - - int minimumLayoutFallbackWidth = qMax<int>(wkPrefs->layoutFallbackWidth(), availableSize.width()); - - WebCore::ViewportAttributes attr = WebCore::computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, wkPrefs->deviceWidth(), wkPrefs->deviceHeight(), wkPrefs->deviceDPI(), availableSize); - WebCore::restrictMinimumScaleFactorToViewportSize(attr, availableSize); - WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attr); - - newConstraints.initialScale = attr.initialScale; - newConstraints.minimumScale = attr.minimumScale; - newConstraints.maximumScale = attr.maximumScale; - newConstraints.devicePixelRatio = attr.devicePixelRatio; - newConstraints.isUserScalable = !!attr.userScalable; - newConstraints.layoutSize = attr.layoutSize; - - q->experimental()->viewportInfo()->didUpdateViewportConstraints(); - - return newConstraints; -} - -void QQuickWebViewFlickablePrivate::PostTransitionState::apply() -{ - p->interactionEngine->reset(); - p->interactionEngine->applyConstraints(p->computeViewportConstraints()); - p->interactionEngine->pagePositionRequest(position); - - if (contentsSize.isValid()) { - p->pageView->setContentsSize(contentsSize); - p->q_ptr->experimental()->viewportInfo()->didUpdateContentsSize(); - } - - position = QPoint(); - contentsSize = QSize(); -} - /*! - \qmlsignal WebView::onNavigationRequested(request) + \qmlsignal WebView::onNavigationRequested(WebNavigationRequest request) - This signal is emitted for every navigation request. The request object contains url, button and modifiers properties - describing the navigation action, e.g. "a middle click with shift key pressed to 'http://qt-project.org'". + This signal is emitted for every navigation request. The request object contains url, + button and modifiers properties describing the navigation action, e.g. "a middle click + with shift key pressed to 'http://qt-project.org'". - The navigation will be accepted by default. To change that, one can set the action property to WebView.IgnoreRequest to reject - the request or WebView.DownloadRequest to trigger a download instead of navigating to the url. + The navigation will be accepted by default. To change that, one can set the action + property to WebView.IgnoreRequest to reject the request or WebView.DownloadRequest to + trigger a download instead of navigating to the url. The request object cannot be used after the signal handler function ends. + + \sa WebNavigationRequest */ QQuickWebViewAttached::QQuickWebViewAttached(QObject* object) @@ -833,6 +885,49 @@ void QQuickWebViewExperimental::setTransparentBackground(bool enable) d->setTransparentBackground(enable); } +bool QQuickWebViewExperimental::useDefaultContentItemSize() const +{ + Q_D(const QQuickWebView); + return d->m_useDefaultContentItemSize; +} + +void QQuickWebViewExperimental::setUseDefaultContentItemSize(bool enable) +{ + Q_D(QQuickWebView); + d->m_useDefaultContentItemSize = enable; +} + +/*! + \internal + + \qmlproperty int WebViewExperimental::preferredMinimumContentsWidth + \brief Minimum contents width when not overriden by the page itself. + + Unless the page defines how contents should be laid out, using e.g. + the viewport meta tag, it is laid out given the width of the viewport + (in CSS units). + + This setting can be used to enforce a minimum width when the page + does not define a width itself. This is useful for laying out pages + designed for big screens, commonly knows as desktop pages, on small + devices. + + The default value is 0, but the value of 980 is recommented for small + screens as it provides a good trade off between legitable pages and + non-broken content. + */ +int QQuickWebViewExperimental::preferredMinimumContentsWidth() const +{ + Q_D(const QQuickWebView); + return d->webPageProxy->pageGroup()->preferences()->layoutFallbackWidth(); +} + +void QQuickWebViewExperimental::setPreferredMinimumContentsWidth(int width) +{ + Q_D(QQuickWebView); + d->webPageProxy->pageGroup()->preferences()->setLayoutFallbackWidth(width); +} + void QQuickWebViewExperimental::setFlickableViewportEnabled(bool enable) { s_flickableViewportEnabled = enable; @@ -843,6 +938,17 @@ bool QQuickWebViewExperimental::flickableViewportEnabled() return s_flickableViewportEnabled; } +/*! + \internal + + \qmlmethod void WebViewExperimental::postMessage(string message) + + \brief Post a message to an onmessage function registered with the navigator.qt object + by JavaScript code executing on the page. + + \sa onMessageReceived +*/ + void QQuickWebViewExperimental::postMessage(const QString& message) { Q_D(QQuickWebView); @@ -966,6 +1072,105 @@ void QQuickWebViewExperimental::setItemSelector(QDeclarativeComponent* itemSelec emit itemSelectorChanged(); } +QDeclarativeComponent* QQuickWebViewExperimental::filePicker() const +{ + Q_D(const QQuickWebView); + return d->filePicker; +} + +void QQuickWebViewExperimental::setFilePicker(QDeclarativeComponent* filePicker) +{ + Q_D(QQuickWebView); + if (d->filePicker == filePicker) + return; + d->filePicker = filePicker; + emit filePickerChanged(); +} + +QDeclarativeComponent* QQuickWebViewExperimental::databaseQuotaDialog() const +{ + Q_D(const QQuickWebView); + return d->databaseQuotaDialog; +} + +void QQuickWebViewExperimental::setDatabaseQuotaDialog(QDeclarativeComponent* databaseQuotaDialog) +{ + Q_D(QQuickWebView); + if (d->databaseQuotaDialog == databaseQuotaDialog) + return; + d->databaseQuotaDialog = databaseQuotaDialog; + emit databaseQuotaDialogChanged(); +} + +QString QQuickWebViewExperimental::userAgent() const +{ + Q_D(const QQuickWebView); + return d->webPageProxy->userAgent(); +} + +void QQuickWebViewExperimental::setUserAgent(const QString& userAgent) +{ + Q_D(QQuickWebView); + if (userAgent == QString(d->webPageProxy->userAgent())) + return; + + d->webPageProxy->setUserAgent(userAgent); + emit userAgentChanged(); +} + +/*! + \internal + + \qmlproperty real WebViewExperimental::devicePixelRatio + \brief The ratio between the CSS units and device pixels when the content is unscaled. + + When designing touch-friendly contents, knowing the approximated target size on a device + is important for contents providers in order to get the intented layout and element + sizes. + + As most first generation touch devices had a PPI of approximately 160, this became a + de-facto value, when used in conjunction with the viewport meta tag. + + Devices with a higher PPI learning towards 240 or 320, applies a pre-scaling on all + content, of either 1.5 or 2.0, not affecting the CSS scale or pinch zooming. + + This value can be set using this property and it is exposed to CSS media queries using + the -webkit-device-pixel-ratio query. + + For instance, if you want to load an image without having it upscaled on a web view + using a device pixel ratio of 2.0 it can be done by loading an image of say 100x100 + pixels but showing it at half the size. + + FIXME: Move documentation example out in separate files + + @media (-webkit-min-device-pixel-ratio: 1.5) { + .icon { + width: 50px; + height: 50px; + url: "/images/icon@2x.png"; // This is actually a 100x100 image + } + } + + If the above is used on a device with device pixel ratio of 1.5, it will be scaled + down but still provide a better looking image. + */ + +double QQuickWebViewExperimental::devicePixelRatio() const +{ + Q_D(const QQuickWebView); + return d->webPageProxy->pageGroup()->preferences()->devicePixelRatio(); +} + +void QQuickWebViewExperimental::setDevicePixelRatio(double devicePixelRatio) +{ + Q_D(QQuickWebView); + if (devicePixelRatio == this->devicePixelRatio()) + return; + + d->webPageProxy->pageGroup()->preferences()->setDevicePixelRatio(devicePixelRatio); + emit devicePixelRatioChanged(); +} + QQuickUrlSchemeDelegate* QQuickWebViewExperimental::schemeDelegates_At(QDeclarativeListProperty<QQuickUrlSchemeDelegate>* property, int index) { const QObjectList children = property->object->children(); @@ -1052,80 +1257,18 @@ QQuickWebPage* QQuickWebViewExperimental::page() return q_ptr->page(); } -QDeclarativeListProperty<QObject> QQuickWebViewExperimental::flickableData() -{ - Q_D(const QQuickWebView); - ASSERT(d->flickProvider); - return d->flickProvider->flickableData(); -} - -QQuickItem* QQuickWebViewExperimental::contentItem() -{ - Q_D(QQuickWebView); - ASSERT(d->flickProvider); - return d->flickProvider->contentItem(); -} - -qreal QQuickWebViewExperimental::contentWidth() const -{ - Q_D(const QQuickWebView); - ASSERT(d->flickProvider); - return d->flickProvider->contentWidth(); -} - -void QQuickWebViewExperimental::setContentWidth(qreal width) -{ - Q_D(QQuickWebView); - ASSERT(d->flickProvider); - d->userDidOverrideContentWidth = true; - d->flickProvider->setContentWidth(width); -} - -qreal QQuickWebViewExperimental::contentHeight() const -{ - Q_D(const QQuickWebView); - ASSERT(d->flickProvider); - return d->flickProvider->contentHeight(); -} - -void QQuickWebViewExperimental::setContentHeight(qreal height) -{ - Q_D(QQuickWebView); - ASSERT(d->flickProvider); - d->userDidOverrideContentHeight = true; - d->flickProvider->setContentHeight(height); -} - -qreal QQuickWebViewExperimental::contentX() const -{ - Q_D(const QQuickWebView); - ASSERT(d->flickProvider); - return d->flickProvider->contentX(); -} - -void QQuickWebViewExperimental::setContentX(qreal x) -{ - Q_D(QQuickWebView); - ASSERT(d->flickProvider); - d->flickProvider->setContentX(x); -} - -qreal QQuickWebViewExperimental::contentY() const -{ - Q_D(const QQuickWebView); - ASSERT(d->flickProvider); - return d->flickProvider->contentY(); -} +/*! + \qmlclass WebView QWebView + \inqmlmodule QtWebKit 3.0 +*/ -void QQuickWebViewExperimental::setContentY(qreal y) -{ - Q_D(QQuickWebView); - ASSERT(d->flickProvider); - d->flickProvider->setContentY(y); -} +/*! + \qmlmethod WebView(Item parent) + \brief Constructs a WebView with a parent. +*/ QQuickWebView::QQuickWebView(QQuickItem* parent) - : QQuickItem(parent) + : QQuickFlickable(parent) , d_ptr(createPrivateObject(this)) , m_experimental(new QQuickWebViewExperimental(this)) { @@ -1134,13 +1277,12 @@ QQuickWebView::QQuickWebView(QQuickItem* parent) } QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent) - : QQuickItem(parent) + : QQuickFlickable(parent) , d_ptr(createPrivateObject(this)) , m_experimental(new QQuickWebViewExperimental(this)) { Q_D(QQuickWebView); d->initialize(contextRef, pageGroupRef); - setClip(true); } QQuickWebView::~QQuickWebView() @@ -1208,6 +1350,13 @@ QUrl QQuickWebView::icon() const return d->m_iconURL; } +/*! + \qmlproperty int WebView::loadProgress + \brief The progress of loading the current web page. + + The range is from 0 to 100. +*/ + int QQuickWebView::loadProgress() const { Q_D(const QQuickWebView); @@ -1226,6 +1375,11 @@ bool QQuickWebView::canGoForward() const return d->webPageProxy->canGoForward(); } +/*! + \qmlproperty bool WebView::loading + \brief True if the web view is currently loading a web page, false otherwise. +*/ + bool QQuickWebView::loading() const { Q_D(const QQuickWebView); @@ -1233,30 +1387,50 @@ bool QQuickWebView::loading() const return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState()); } +/*! + \internal + */ + QPointF QQuickWebView::mapToWebContent(const QPointF& pointInViewCoordinates) const { Q_D(const QQuickWebView); return d->pageView->transformFromItem().map(pointInViewCoordinates); } +/*! + \internal + */ + QRectF QQuickWebView::mapRectToWebContent(const QRectF& rectInViewCoordinates) const { Q_D(const QQuickWebView); return d->pageView->transformFromItem().mapRect(rectInViewCoordinates); } +/*! + \internal + */ + QPointF QQuickWebView::mapFromWebContent(const QPointF& pointInCSSCoordinates) const { Q_D(const QQuickWebView); return d->pageView->transformToItem().map(pointInCSSCoordinates); } +/*! + \internal + */ QRectF QQuickWebView::mapRectFromWebContent(const QRectF& rectInCSSCoordinates) const { Q_D(const QQuickWebView); return d->pageView->transformToItem().mapRect(rectInCSSCoordinates); } +/*! + \qmlproperty string WebView::title + \brief The title of the loaded page. +*/ + QString QQuickWebView::title() const { Q_D(const QQuickWebView); @@ -1287,10 +1461,16 @@ QVariant QQuickWebView::inputMethodQuery(Qt::InputMethodQuery property) const return int(Qt::InputMethodHints(state.inputMethodHints)); default: // Rely on the base implementation for ImEnabled, ImHints and ImPreferredLanguage. - return QQuickItem::inputMethodQuery(property); + return QQuickFlickable::inputMethodQuery(property); } } +/*! + \preliminary + + The experimental module consisting on experimental API which will break + from version to version. +*/ QQuickWebViewExperimental* QQuickWebView::experimental() const { return m_experimental; @@ -1301,6 +1481,9 @@ QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object) return new QQuickWebViewAttached(object); } +/*! + \internal +*/ void QQuickWebView::platformInitialize() { JSC::initializeThreading(); @@ -1310,7 +1493,7 @@ void QQuickWebView::platformInitialize() void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) { Q_D(QQuickWebView); - QQuickItem::geometryChanged(newGeometry, oldGeometry); + QQuickFlickable::geometryChanged(newGeometry, oldGeometry); if (newGeometry.size() != oldGeometry.size()) d->updateViewportSize(); } @@ -1318,7 +1501,7 @@ void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& old void QQuickWebView::componentComplete() { Q_D(QQuickWebView); - QQuickItem::componentComplete(); + QQuickFlickable::componentComplete(); d->onComponentComplete(); d->updateViewportSize(); @@ -1357,11 +1540,21 @@ void QQuickWebView::focusOutEvent(QFocusEvent* event) void QQuickWebView::touchEvent(QTouchEvent* event) { Q_D(QQuickWebView); - if (d->m_dialogRunnerActive) { + if (d->m_dialogActive) { event->ignore(); return; } + bool lockingDisabled = flickableDirection() != AutoFlickDirection + || event->touchPoints().size() != 1 + || width() >= contentWidth() + || height() >= contentHeight(); + + if (!lockingDisabled) + d->axisLocker.update(event); + else + d->axisLocker.reset(); + forceActiveFocus(); d->pageView->eventHandler()->handleTouchEvent(event); } @@ -1445,7 +1638,7 @@ void QQuickWebView::dropEvent(QDropEvent* event) bool QQuickWebView::event(QEvent* ev) { // Re-implemented for possible future use without breaking binary compatibility. - return QQuickItem::event(ev); + return QQuickFlickable::event(ev); } WKPageRef QQuickWebView::pageRef() const @@ -1454,13 +1647,52 @@ WKPageRef QQuickWebView::pageRef() const return toAPI(d->webPageProxy.get()); } +QPointF QQuickWebView::contentPos() const +{ + Q_D(const QQuickWebView); + return d->contentPos(); +} + +void QQuickWebView::setContentPos(const QPointF& pos) +{ + Q_D(QQuickWebView); + d->setContentPos(pos); +} + +void QQuickWebView::handleFlickableMousePress(const QPointF& position, qint64 eventTimestampMillis) +{ + Q_D(QQuickWebView); + d->axisLocker.setReferencePosition(position); + QMouseEvent mouseEvent(QEvent::MouseButtonPress, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + mouseEvent.setTimestamp(eventTimestampMillis); + QQuickFlickable::mousePressEvent(&mouseEvent); +} + +void QQuickWebView::handleFlickableMouseMove(const QPointF& position, qint64 eventTimestampMillis) +{ + Q_D(QQuickWebView); + QMouseEvent mouseEvent(QEvent::MouseMove, d->axisLocker.adjust(position), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + mouseEvent.setTimestamp(eventTimestampMillis); + QQuickFlickable::mouseMoveEvent(&mouseEvent); +} + +void QQuickWebView::handleFlickableMouseRelease(const QPointF& position, qint64 eventTimestampMillis) +{ + Q_D(QQuickWebView); + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, d->axisLocker.adjust(position), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + d->axisLocker.reset(); + mouseEvent.setTimestamp(eventTimestampMillis); + QQuickFlickable::mouseReleaseEvent(&mouseEvent); +} + /*! - Loads the specified \a html as the content of the web view. + \qmlmethod void WebView::loadHtml(string html, url baseUrl, url unreachableUrl) + \brief Loads the specified \a html as the content of the web view. External objects such as stylesheets or images referenced in the HTML document are located relative to \a baseUrl. - \sa load() + \sa WebView::url */ void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl) { @@ -1480,4 +1712,38 @@ void QQuickWebView::updateContentsSize(const QSizeF& size) d->updateContentsSize(size); } +qreal QQuickWebView::zoomFactor() const +{ + Q_D(const QQuickWebView); + return d->zoomFactor(); +} + +void QQuickWebView::setZoomFactor(qreal factor) +{ + + Q_D(QQuickWebView); + d->setZoomFactor(factor); +} + +struct JSCallbackClosure { + QPointer<QObject> receiver; + QByteArray method; +}; + +static void javaScriptCallback(WKSerializedScriptValueRef, WKErrorRef, void* context) +{ + JSCallbackClosure* closure = reinterpret_cast<JSCallbackClosure*>(context); + QMetaObject::invokeMethod(closure->receiver, closure->method); + delete closure; +} + +void QQuickWebView::runJavaScriptInMainFrame(const QString &script, QObject *receiver, const char *method) +{ + Q_D(QQuickWebView); + JSCallbackClosure* closure = new JSCallbackClosure; + closure->receiver = receiver; + closure->method = method; + d->webPageProxy.get()->runJavaScriptInMainFrame(script, ScriptValueCallback::create(closure, javaScriptCallback)); +} + #include "moc_qquickwebview_p.cpp" diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h index 5302916eb..916f2282d 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h @@ -23,8 +23,9 @@ #include "qquickurlschemedelegate_p.h" #include "qwebkitglobal.h" -#include <QtDeclarative/qdeclarativelist.h> +#include <QtQml/qqmllist.h> #include <QtQuick/qquickitem.h> +#include <private/qquickflickable_p.h> class QWebNavigationRequest; class QDeclarativeComponent; @@ -46,6 +47,10 @@ class PlatformWebView; namespace WebKit { class QtRefCountedNetworkRequestData; +class QtViewportInteractionEngine; +class QtWebPageLoadClient; +class QtWebPagePolicyClient; +class QtWebPageUIClient; } namespace WTF { @@ -59,13 +64,14 @@ typedef const struct OpaqueWKPage* WKPageRef; QT_BEGIN_NAMESPACE class QPainter; class QUrl; +class QQuickFlickable; QT_END_NAMESPACE // Instantiating the WebView in C++ is only possible by creating // a QDeclarativeComponent as the initialization depends on the // componentComplete method being called. -class QWEBKIT_EXPORT QQuickWebView : public QQuickItem { +class QWEBKIT_EXPORT QQuickWebView : public QQuickFlickable { Q_OBJECT Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) @@ -138,6 +144,11 @@ public: void updateContentsSize(const QSizeF&); QPointF pageItemPos(); + // Private C++-only API. + qreal zoomFactor() const; + void setZoomFactor(qreal); + void runJavaScriptInMainFrame(const QString& script, QObject* receiver, const char* method); + public Q_SLOTS: void loadHtml(const QString& html, const QUrl& baseUrl = QUrl()); @@ -182,16 +193,20 @@ protected: private: Q_DECLARE_PRIVATE(QQuickWebView) + void handleFlickableMousePress(const QPointF& position, qint64 eventTimestampMillis); + void handleFlickableMouseMove(const QPointF& position, qint64 eventTimestampMillis); + void handleFlickableMouseRelease(const QPointF& position, qint64 eventTimestampMillis); + + QPointF contentPos() const; + void setContentPos(const QPointF&); + QQuickWebView(WKContextRef, WKPageGroupRef, QQuickItem* parent = 0); WKPageRef pageRef() const; Q_PRIVATE_SLOT(d_func(), void _q_suspend()); Q_PRIVATE_SLOT(d_func(), void _q_resume()); - Q_PRIVATE_SLOT(d_func(), void _q_commitPositionChange(const QPointF&)); - Q_PRIVATE_SLOT(d_func(), void _q_commitScaleChange()); + Q_PRIVATE_SLOT(d_func(), void _q_contentViewportChanged(const QPointF&)); - 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()); Q_PRIVATE_SLOT(d_func(), void _q_onUrlChanged()); Q_PRIVATE_SLOT(d_func(), void _q_onReceivedResponseFromDownload(QWebDownloadItem*)); @@ -200,9 +215,10 @@ private: QScopedPointer<QQuickWebViewPrivate> d_ptr; QQuickWebViewExperimental* m_experimental; - friend class QtWebPageLoadClient; - friend class QtWebPagePolicyClient; - friend class QtWebPageUIClient; + friend class WebKit::QtViewportInteractionEngine; + friend class WebKit::QtWebPageLoadClient; + friend class WebKit::QtWebPagePolicyClient; + friend class WebKit::QtWebPageUIClient; friend class WTR::PlatformWebView; friend class QQuickWebViewExperimental; }; @@ -231,14 +247,9 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject { Q_OBJECT Q_PROPERTY(QQuickWebPage* page READ page CONSTANT FINAL) - // QML Flickable API. - Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged) - Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged) - Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged) - Q_PROPERTY(qreal contentY READ contentY WRITE setContentY NOTIFY contentYChanged) - Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT) - Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData) Q_PROPERTY(bool transparentBackground WRITE setTransparentBackground READ transparentBackground) + Q_PROPERTY(bool useDefaultContentItemSize WRITE setUseDefaultContentItemSize READ useDefaultContentItemSize) + Q_PROPERTY(int preferredMinimumContentsWidth WRITE setPreferredMinimumContentsWidth READ preferredMinimumContentsWidth) Q_PROPERTY(QWebNavigationHistory* navigationHistory READ navigationHistory CONSTANT FINAL) Q_PROPERTY(QDeclarativeComponent* alertDialog READ alertDialog WRITE setAlertDialog NOTIFY alertDialogChanged) @@ -248,9 +259,13 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject { Q_PROPERTY(QDeclarativeComponent* proxyAuthenticationDialog READ proxyAuthenticationDialog WRITE setProxyAuthenticationDialog NOTIFY proxyAuthenticationDialogChanged) Q_PROPERTY(QDeclarativeComponent* certificateVerificationDialog READ certificateVerificationDialog WRITE setCertificateVerificationDialog NOTIFY certificateVerificationDialogChanged) Q_PROPERTY(QDeclarativeComponent* itemSelector READ itemSelector WRITE setItemSelector NOTIFY itemSelectorChanged) + Q_PROPERTY(QDeclarativeComponent* filePicker READ filePicker WRITE setFilePicker NOTIFY filePickerChanged) + Q_PROPERTY(QDeclarativeComponent* databaseQuotaDialog READ databaseQuotaDialog WRITE setDatabaseQuotaDialog NOTIFY databaseQuotaDialogChanged) Q_PROPERTY(QWebPreferences* preferences READ preferences CONSTANT FINAL) Q_PROPERTY(QWebViewportInfo* viewportInfo READ viewportInfo CONSTANT FINAL) Q_PROPERTY(QDeclarativeListProperty<QQuickUrlSchemeDelegate> urlSchemeDelegates READ schemeDelegates) + Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent NOTIFY userAgentChanged) + Q_PROPERTY(double devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged) Q_ENUMS(NavigationRequestActionExperimental) public: @@ -275,6 +290,14 @@ public: void setItemSelector(QDeclarativeComponent*); QDeclarativeComponent* proxyAuthenticationDialog() const; void setProxyAuthenticationDialog(QDeclarativeComponent*); + QDeclarativeComponent* filePicker() const; + void setFilePicker(QDeclarativeComponent*); + QDeclarativeComponent* databaseQuotaDialog() const; + void setDatabaseQuotaDialog(QDeclarativeComponent*); + QString userAgent() const; + void setUserAgent(const QString& userAgent); + double devicePixelRatio() const; + void setDevicePixelRatio(double); QWebViewportInfo* viewportInfo(); @@ -287,22 +310,18 @@ public: static int schemeDelegates_Count(QDeclarativeListProperty<QQuickUrlSchemeDelegate>*); static void schemeDelegates_Clear(QDeclarativeListProperty<QQuickUrlSchemeDelegate>*); QDeclarativeListProperty<QQuickUrlSchemeDelegate> schemeDelegates(); - QDeclarativeListProperty<QObject> flickableData(); void invokeApplicationSchemeHandler(WTF::PassRefPtr<WebKit::QtRefCountedNetworkRequestData>); void sendApplicationSchemeReply(QQuickNetworkReply*); - QQuickItem* contentItem(); - qreal contentWidth() const; - void setContentWidth(qreal); - qreal contentHeight() const; - void setContentHeight(qreal); - qreal contentX() const; - void setContentX(qreal); - qreal contentY() const; - void setContentY(qreal); bool transparentBackground() const; void setTransparentBackground(bool); + bool useDefaultContentItemSize() const; + void setUseDefaultContentItemSize(bool enable); + + int preferredMinimumContentsWidth() const; + void setPreferredMinimumContentsWidth(int); + // C++ only bool renderToOffscreenBuffer() const; void setRenderToOffscreenBuffer(bool enable); @@ -315,20 +334,22 @@ public Q_SLOTS: void postMessage(const QString&); Q_SIGNALS: - void contentWidthChanged(); - void contentHeightChanged(); - void contentXChanged(); - void contentYChanged(); void alertDialogChanged(); void confirmDialogChanged(); void promptDialogChanged(); void authenticationDialogChanged(); void certificateVerificationDialogChanged(); void itemSelectorChanged(); + void filePickerChanged(); + void databaseQuotaDialogChanged(); void downloadRequested(QWebDownloadItem* downloadItem); void permissionRequested(QWebPermissionRequest* permission); void messageReceived(const QVariantMap& message); void proxyAuthenticationDialogChanged(); + void userAgentChanged(); + void devicePixelRatioChanged(); + void enterFullScreenRequested(); + void exitFullScreenRequested(); private: QQuickWebView* q_ptr; @@ -336,7 +357,7 @@ private: QObject* schemeParent; QWebViewportInfo* m_viewportInfo; - friend class QtWebPageUIClient; + friend class WebKit::QtWebPageUIClient; Q_DECLARE_PRIVATE(QQuickWebView) Q_DECLARE_PUBLIC(QQuickWebView) diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h index 39a14a7a6..417618d0a 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h @@ -21,36 +21,36 @@ #ifndef qquickwebview_p_p_h #define qquickwebview_p_p_h -#include "DrawingAreaProxy.h" -#include "QtDialogRunner.h" -#include "QtFlickProvider.h" #include "QtPageClient.h" -#include "QtViewportInteractionEngine.h" -#include "QtWebPageLoadClient.h" -#include "QtWebPagePolicyClient.h" #include "QtWebPageUIClient.h" #include "QtWebUndoController.h" -#include "WebPageProxy.h" #include "qquickwebview_p.h" #include "qquickwebpage_p.h" +#include <QtCore/QElapsedTimer> #include <QtCore/QObject> #include <QtCore/QScopedPointer> +#include <WebCore/ViewportArguments.h> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> namespace WebKit { class DownloadProxy; +class DrawingAreaProxy; +class QtDialogRunner; +class QtViewportInteractionEngine; class QtWebContext; +class QtWebPageLoadClient; +class QtWebPagePolicyClient; class WebPageProxy; } + class QWebNavigationHistory; class QWebViewportInfo; QT_BEGIN_NAMESPACE class QDeclarativeComponent; -class QFileDialog; QT_END_NAMESPACE class QQuickWebViewPrivate { @@ -67,8 +67,8 @@ public: virtual void initialize(WKContextRef contextRef = 0, WKPageGroupRef pageGroupRef = 0); - void enableMouseEvents(); - void disableMouseEvents(); + virtual void enableMouseEvents() { } + virtual void disableMouseEvents() { } virtual QPointF pageItemPos(); virtual void updateContentsSize(const QSizeF&) { } @@ -77,30 +77,29 @@ public: virtual void onComponentComplete(); virtual void loadDidCommit() { } virtual void didFinishFirstNonEmptyLayout() { } - virtual void didChangeViewportProperties(const WebCore::ViewportArguments& args) { } - void didChangeLoadingState(QWebLoadRequest* loadRequest); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes& attr) { } void didChangeBackForwardList(); void setNeedsDisplay(); - virtual QtViewportInteractionEngine* viewportInteractionEngine() { return 0; } + virtual WebKit::QtViewportInteractionEngine* viewportInteractionEngine() { return 0; } virtual void updateViewportSize() { } void updateTouchViewportSize(); virtual void _q_suspend() { } virtual void _q_resume() { } + virtual void _q_contentViewportChanged(const QPointF& trajectory) { }; - virtual void _q_commitScaleChange() { } - void _q_commitPositionChange(const QPointF&); + virtual qreal zoomFactor() const { return 1; } + virtual void setZoomFactor(qreal) { } - void _q_onOpenPanelFilesSelected(); - void _q_onOpenPanelFinished(int result); void _q_onVisibleChanged(); void _q_onUrlChanged(); void _q_onReceivedResponseFromDownload(QWebDownloadItem*); void _q_onIconChangedForPageURL(const QUrl& pageURL, const QUrl& iconURLString); - void chooseFiles(WKOpenPanelResultListenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType); + void chooseFiles(WKOpenPanelResultListenerRef, const QStringList& selectedFileNames, WebKit::QtWebPageUIClient::FileChooserType); + quint64 exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage); void runJavaScriptAlert(const QString&); bool runJavaScriptConfirm(const QString&); QString runJavaScriptPrompt(const QString&, const QString& defaultValue, bool& ok); @@ -109,7 +108,7 @@ public: bool handleCertificateVerificationRequest(const QString& hostname); void handleProxyAuthenticationRequiredRequest(const QString& hostname, uint16_t port, const QString& prefilledUsername, QString& username, QString& password); - void execDialogRunner(QtDialogRunner&); + void execDialogRunner(WebKit::QtDialogRunner&); void setRenderToOffscreenBuffer(bool enable) { m_renderToOffscreenBuffer = enable; } void setTransparentBackground(bool); @@ -121,8 +120,13 @@ public: bool transparentBackground() const; void setNavigatorQtObjectEnabled(bool); + QPointF contentPos() const; + void setContentPos(const QPointF&); + QRect visibleContentsRect() const; + void setDialogActive(bool active) { m_dialogActive = active; } + // PageClient. WebCore::IntSize viewSize() const; void didReceiveMessageFromNavigatorQtObject(const String& message); @@ -130,26 +134,46 @@ public: virtual void didChangeContentsSize(const QSize& newSize) { } void processDidCrash(); void didRelaunchProcess(); - PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy(); - void handleDownloadRequest(DownloadProxy*); + PassOwnPtr<WebKit::DrawingAreaProxy> createDrawingAreaProxy(); + void handleDownloadRequest(WebKit::DownloadProxy*); protected: + class FlickableAxisLocker { + QQuickFlickable::FlickableDirection m_allowedDirection; + + QElapsedTimer m_time; + QPointF m_initialScreenPosition; + QPointF m_lockReferencePosition; + int m_sampleCount; + + QVector2D touchVelocity(const QTouchEvent* event); + + public: + FlickableAxisLocker(); + + void update(const QTouchEvent* event); + void setReferencePosition(const QPointF&); + void reset(); + QPointF adjust(const QPointF&); + }; + QQuickWebViewPrivate(QQuickWebView* viewport); - RefPtr<QtWebContext> context; + RefPtr<WebKit::QtWebContext> context; RefPtr<WebKit::WebPageProxy> webPageProxy; - QtPageClient pageClient; - QtWebUndoController undoController; + WebKit::QtPageClient pageClient; + WebKit::QtWebUndoController undoController; OwnPtr<QWebNavigationHistory> navigationHistory; OwnPtr<QWebPreferences> preferences; - QScopedPointer<QtWebPageLoadClient> pageLoadClient; - QScopedPointer<QtWebPagePolicyClient> pagePolicyClient; - QScopedPointer<QtWebPageUIClient> pageUIClient; + QScopedPointer<WebKit::QtWebPageLoadClient> pageLoadClient; + QScopedPointer<WebKit::QtWebPagePolicyClient> pagePolicyClient; + QScopedPointer<WebKit::QtWebPageUIClient> pageUIClient; QScopedPointer<QQuickWebPage> pageView; QQuickWebView* q_ptr; - QtFlickProvider* flickProvider; + + FlickableAxisLocker axisLocker; QDeclarativeComponent* alertDialog; QDeclarativeComponent* confirmDialog; @@ -158,17 +182,15 @@ protected: QDeclarativeComponent* certificateVerificationDialog; QDeclarativeComponent* itemSelector; QDeclarativeComponent* proxyAuthenticationDialog; + QDeclarativeComponent* filePicker; + QDeclarativeComponent* databaseQuotaDialog; - WebCore::ViewportArguments viewportArguments; - QFileDialog* fileDialog; - WKOpenPanelResultListenerRef openPanelResultListener; + WebCore::ViewportAttributes attributes; - bool userDidOverrideContentWidth; - bool userDidOverrideContentHeight; + bool m_useDefaultContentItemSize; bool m_navigatorQtObjectEnabled; bool m_renderToOffscreenBuffer; - bool m_loadStartedSignalSent; - bool m_dialogRunnerActive; + bool m_dialogActive; QUrl m_iconURL; QUrl m_deferedUrlToLoad; }; @@ -180,6 +202,11 @@ public: virtual void initialize(WKContextRef contextRef = 0, WKPageGroupRef pageGroupRef = 0); virtual void updateViewportSize(); + virtual void enableMouseEvents(); + virtual void disableMouseEvents(); + + qreal zoomFactor() const; + void setZoomFactor(qreal); }; class QQuickWebViewFlickablePrivate : public QQuickWebViewPrivate { @@ -196,39 +223,19 @@ public: virtual void onComponentComplete(); virtual void loadDidCommit(); virtual void didFinishFirstNonEmptyLayout(); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments& args); - virtual QtViewportInteractionEngine* viewportInteractionEngine() { return interactionEngine.data(); } + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); + virtual WebKit::QtViewportInteractionEngine* viewportInteractionEngine() { return interactionEngine.data(); } virtual void updateViewportSize(); virtual void _q_suspend(); virtual void _q_resume(); - virtual void _q_commitScaleChange(); + virtual void _q_contentViewportChanged(const QPointF& trajectory); virtual void pageDidRequestScroll(const QPoint& pos); virtual void didChangeContentsSize(const QSize& newSize); - QtViewportInteractionEngine::Constraints computeViewportConstraints(); - private: - // This class is responsible for collecting and applying all properties - // on the viewport item, when transitioning from page A to page B is finished. - // See more at https://trac.webkit.org/wiki/QtWebKitLayoutInteraction - class PostTransitionState { - public: - PostTransitionState(QQuickWebViewFlickablePrivate* parent) - : p(parent) - { } - - void apply(); - - QQuickWebViewFlickablePrivate* p; - QSize contentsSize; - QPoint position; - }; - - QScopedPointer<QtViewportInteractionEngine> interactionEngine; - OwnPtr<PostTransitionState> postTransitionState; - bool isTransitioningToNewPage; + QScopedPointer<WebKit::QtViewportInteractionEngine> interactionEngine; bool pageIsSuspended; bool loadSuccessDispatchIsPending; }; diff --git a/Source/WebKit2/UIProcess/API/qt/qwebdownloaditem_p.h b/Source/WebKit2/UIProcess/API/qt/qwebdownloaditem_p.h index 79659753b..69bb3dfa1 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebdownloaditem_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebdownloaditem_p.h @@ -26,7 +26,6 @@ #include <QUrl> class QWebDownloadItemPrivate; -class QtWebError; QT_BEGIN_NAMESPACE class QString; @@ -34,6 +33,7 @@ QT_END_NAMESPACE namespace WebKit { class QtDownloadManager; +class QtWebError; } class QWEBKIT_EXPORT QWebDownloadItem : public QObject { diff --git a/Source/WebKit2/UIProcess/API/qt/qwebiconimageprovider_p.h b/Source/WebKit2/UIProcess/API/qt/qwebiconimageprovider_p.h index 8815d7b76..74f55995f 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebiconimageprovider_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebiconimageprovider_p.h @@ -21,7 +21,7 @@ #define qwebiconimageprovider_p_h #include "qwebkitglobal.h" -#include <QtDeclarative/QDeclarativeImageProvider> +#include <QtQuick/QQuickImageProvider> class QWEBKIT_EXPORT QWebIconImageProvider : public QDeclarativeImageProvider { public: diff --git a/Source/WebKit2/UIProcess/API/qt/qwebloadrequest.cpp b/Source/WebKit2/UIProcess/API/qt/qwebloadrequest.cpp index 0b249a61a..39f314c3b 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebloadrequest.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebloadrequest.cpp @@ -39,6 +39,17 @@ public: int errorCode; }; +/*! + \qmlclass WebLoadRequest QWebLoadRequest + \brief A utility class for the WebView::loadingChanged signal. + + This class contains information about a requested load of a web page, like the URL and + current loading status (started, finished, failed). + + \sa WebView::loadingChanged(WebLoadRequest) + + \inqmlmodule QtWebKit 3.0 +*/ QWebLoadRequest::QWebLoadRequest(const QUrl& url, QQuickWebView::LoadStatus status, const QString& errorString, QQuickWebView::ErrorDomain errorDomain, int errorCode, QObject* parent) : QObject(parent) , d(new QWebLoadRequestPrivate(url, status, errorString, errorDomain, errorCode)) @@ -49,16 +60,36 @@ QWebLoadRequest::~QWebLoadRequest() { } +/*! + \qmlproperty url WebLoadRequest::url + \brief The URL of the load request. + */ QUrl QWebLoadRequest::url() const { return d->url; } +/*! + \qmlproperty enumeration WebLoadRequest::status + + The load status of a web page load request. + + \list + \li WebView::LoadStartedStatus - the page is currently loading. + \li WebView::LoadSucceededStatus - the page has been loaded with success. + \li WebView::LoadFailedStatus - the page has failed loading. + \endlist + + \sa WebLoadRequest, WebView::loadingChanged(WebLoadRequest) +*/ QQuickWebView::LoadStatus QWebLoadRequest::status() const { return d->status; } +/*! + \qmlproperty string WebLoadRequest::errorString +*/ QString QWebLoadRequest::errorString() const { return d->errorString; @@ -69,6 +100,9 @@ QQuickWebView::ErrorDomain QWebLoadRequest::errorDomain() const return d->errorDomain; } +/*! + \qmlproperty int WebLoadRequest::errorCode +*/ int QWebLoadRequest::errorCode() const { return d->errorCode; diff --git a/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory.cpp b/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory.cpp index ff77dae6b..b057526e1 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory.cpp @@ -33,9 +33,9 @@ #include "WebBackForwardList.h" #include "qwebnavigationhistory_p_p.h" -#include <QDeclarativeEngine> #include <QString> #include <QUrl> +#include <QtQml/QQmlEngine> #include <WebKit2/WKArray.h> #include <WebKit2/WKBackForwardListItem.h> #include <WebKit2/WKBase.h> diff --git a/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory_p.h b/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory_p.h index 929114472..fa630754b 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebnavigationhistory_p.h @@ -31,7 +31,7 @@ #include <QObject> #include <QUrl> #include <QVariant> -#include <qdeclarative.h> +#include <QtQml/qqml.h> class QAbstractListModel; class QWebNavigationHistoryPrivate; diff --git a/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp b/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp index 835c698db..0b3f36d09 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebpreferences.cpp @@ -32,6 +32,7 @@ QWebPreferences* QWebPreferencesPrivate::createPreferences(QQuickWebViewPrivate* { QWebPreferences* prefs = new QWebPreferences; prefs->d->webViewPrivate = webViewPrivate; + prefs->d->initializeDefaultFontSettings(); return prefs; } @@ -40,6 +41,10 @@ bool QWebPreferencesPrivate::testAttribute(QWebPreferencesPrivate::WebAttribute switch (attr) { case AutoLoadImages: return WKPreferencesGetLoadsImagesAutomatically(preferencesRef()); +#if ENABLE(FULLSCREEN_API) + case FullScreenEnabled: + return WKPreferencesGetFullScreenEnabled(preferencesRef()); +#endif case JavascriptEnabled: return WKPreferencesGetJavaScriptEnabled(preferencesRef()); case PluginsEnabled: @@ -56,6 +61,8 @@ bool QWebPreferencesPrivate::testAttribute(QWebPreferencesPrivate::WebAttribute return WKPreferencesGetDNSPrefetchingEnabled(preferencesRef()); case FrameFlatteningEnabled: return WKPreferencesGetFrameFlatteningEnabled(preferencesRef()); + case DeveloperExtrasEnabled: + return WKPreferencesGetDeveloperExtrasEnabled(preferencesRef()); default: ASSERT_NOT_REACHED(); return false; @@ -68,6 +75,11 @@ void QWebPreferencesPrivate::setAttribute(QWebPreferencesPrivate::WebAttribute a case AutoLoadImages: WKPreferencesSetLoadsImagesAutomatically(preferencesRef(), enable); break; +#if ENABLE(FULLSCREEN_API) + case FullScreenEnabled: + WKPreferencesSetFullScreenEnabled(preferencesRef(), enable); + break; +#endif case JavascriptEnabled: WKPreferencesSetJavaScriptEnabled(preferencesRef(), enable); break; @@ -91,12 +103,38 @@ void QWebPreferencesPrivate::setAttribute(QWebPreferencesPrivate::WebAttribute a break; case FrameFlatteningEnabled: WKPreferencesSetFrameFlatteningEnabled(preferencesRef(), enable); + case DeveloperExtrasEnabled: + WKPreferencesSetDeveloperExtrasEnabled(preferencesRef(), enable); break; default: ASSERT_NOT_REACHED(); } } +void QWebPreferencesPrivate::initializeDefaultFontSettings() +{ + setFontSize(MinimumFontSize, 0); + setFontSize(DefaultFontSize, 16); + setFontSize(DefaultFixedFontSize, 13); + + QFont defaultFont; + defaultFont.setStyleHint(QFont::Serif); + setFontFamily(StandardFont, defaultFont.defaultFamily()); + setFontFamily(SerifFont, defaultFont.defaultFamily()); + + defaultFont.setStyleHint(QFont::Fantasy); + setFontFamily(FantasyFont, defaultFont.defaultFamily()); + + defaultFont.setStyleHint(QFont::Cursive); + setFontFamily(CursiveFont, defaultFont.defaultFamily()); + + defaultFont.setStyleHint(QFont::SansSerif); + setFontFamily(SansSerifFont, defaultFont.defaultFamily()); + + defaultFont.setStyleHint(QFont::Monospace); + setFontFamily(FixedFont, defaultFont.defaultFamily()); +} + void QWebPreferencesPrivate::setFontFamily(QWebPreferencesPrivate::FontFamily which, const QString& family) { switch (which) { @@ -208,6 +246,25 @@ void QWebPreferences::setAutoLoadImages(bool enable) emit autoLoadImagesChanged(); } +bool QWebPreferences::fullScreenEnabled() const +{ +#if ENABLE(FULLSCREEN_API) + return d->testAttribute(QWebPreferencesPrivate::FullScreenEnabled); +#else + return false; +#endif +} + +void QWebPreferences::setFullScreenEnabled(bool enable) +{ +#if ENABLE(FULLSCREEN_API) + d->setAttribute(QWebPreferencesPrivate::FullScreenEnabled, enable); + emit fullScreenEnabledChanged(); +#else + UNUSED_PARAM(enable); +#endif +} + bool QWebPreferences::javascriptEnabled() const { return d->testAttribute(QWebPreferencesPrivate::JavascriptEnabled); @@ -285,6 +342,17 @@ void QWebPreferences::setDnsPrefetchEnabled(bool enable) emit dnsPrefetchEnabledChanged(); } +bool QWebPreferences::developerExtrasEnabled() const +{ + return d->testAttribute(QWebPreferencesPrivate::DeveloperExtrasEnabled); +} + +void QWebPreferences::setDeveloperExtrasEnabled(bool enable) +{ + d->setAttribute(QWebPreferencesPrivate::DeveloperExtrasEnabled, enable); + emit developerExtrasEnabledChanged(); +} + bool QWebPreferences::navigatorQtObjectEnabled() const { return d->webViewPrivate->navigatorQtObjectEnabled(); diff --git a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h index 82b738fbf..24859bff2 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p.h @@ -32,6 +32,7 @@ public: ~QWebPreferences(); Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages NOTIFY autoLoadImagesChanged FINAL) + Q_PROPERTY(bool fullScreenEnabled READ fullScreenEnabled WRITE setFullScreenEnabled NOTIFY fullScreenEnabledChanged FINAL) Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled NOTIFY javascriptEnabledChanged FINAL) Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled NOTIFY pluginsEnabledChanged FINAL) Q_PROPERTY(bool offlineWebApplicationCacheEnabled READ offlineWebApplicationCacheEnabled WRITE setOfflineWebApplicationCacheEnabled NOTIFY offlineWebApplicationCacheEnabledChanged FINAL) @@ -41,6 +42,7 @@ public: Q_PROPERTY(bool dnsPrefetchEnabled READ dnsPrefetchEnabled WRITE setDnsPrefetchEnabled NOTIFY dnsPrefetchEnabledChanged FINAL) Q_PROPERTY(bool navigatorQtObjectEnabled READ navigatorQtObjectEnabled WRITE setNavigatorQtObjectEnabled NOTIFY navigatorQtObjectEnabledChanged FINAL) Q_PROPERTY(bool frameFlatteningEnabled READ frameFlatteningEnabled WRITE setFrameFlatteningEnabled NOTIFY frameFlatteningEnabledChanged FINAL) + Q_PROPERTY(bool developerExtrasEnabled READ developerExtrasEnabled WRITE setDeveloperExtrasEnabled NOTIFY developerExtrasEnabledChanged FINAL) Q_PROPERTY(QString standardFontFamily READ standardFontFamily WRITE setStandardFontFamily NOTIFY standardFontFamilyChanged FINAL) Q_PROPERTY(QString fixedFontFamily READ fixedFontFamily WRITE setFixedFontFamily NOTIFY fixedFontFamilyChanged FINAL) @@ -56,6 +58,9 @@ public: bool autoLoadImages() const; void setAutoLoadImages(bool enable); + bool fullScreenEnabled() const; + void setFullScreenEnabled(bool enable); + bool javascriptEnabled() const; void setJavascriptEnabled(bool enable); @@ -83,6 +88,9 @@ public: bool frameFlatteningEnabled() const; void setFrameFlatteningEnabled(bool enable); + bool developerExtrasEnabled() const; + void setDeveloperExtrasEnabled(bool enable); + QString standardFontFamily() const; void setStandardFontFamily(const QString& family); @@ -113,6 +121,7 @@ public: Q_SIGNALS: void autoLoadImagesChanged(); void pluginsEnabledChanged(); + void fullScreenEnabledChanged(); void javascriptEnabledChanged(); void offlineWebApplicationCacheEnabledChanged(); void localStorageEnabledChanged(); @@ -121,6 +130,7 @@ Q_SIGNALS: void dnsPrefetchEnabledChanged(); void navigatorQtObjectEnabledChanged(); void frameFlatteningEnabledChanged(); + void developerExtrasEnabledChanged(); void standardFontFamilyChanged(); void fixedFontFamilyChanged(); diff --git a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h index f4ef13c21..ae636c1c7 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebpreferences_p_p.h @@ -29,6 +29,7 @@ public: enum WebAttribute { AutoLoadImages, + FullScreenEnabled, JavascriptEnabled, PluginsEnabled, OfflineWebApplicationCacheEnabled, @@ -36,7 +37,8 @@ public: XSSAuditingEnabled, FrameFlatteningEnabled, PrivateBrowsingEnabled, - DnsPrefetchEnabled + DnsPrefetchEnabled, + DeveloperExtrasEnabled }; enum FontFamily { @@ -59,6 +61,7 @@ public: void setAttribute(WebAttribute attr, bool enable); bool testAttribute(WebAttribute attr) const; + void initializeDefaultFontSettings(); void setFontFamily(FontFamily which, const QString& family); QString fontFamily(FontFamily which) const; diff --git a/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo.cpp b/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo.cpp index 22863be29..170604d1d 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo.cpp @@ -19,21 +19,22 @@ */ #include "config.h" +#include "QtViewportInteractionEngine.h" #include "qwebviewportinfo_p.h" #include "qquickwebview_p.h" #include "qquickwebview_p_p.h" +using namespace WebKit; + QWebViewportInfo::QWebViewportInfo(QQuickWebViewPrivate* webViewPrivate, QObject* parent) : QObject(parent) , m_webViewPrivate(webViewPrivate) { - } QWebViewportInfo::~QWebViewportInfo() { - } QSize QWebViewportInfo::contentsSize() const @@ -46,55 +47,37 @@ QVariant QWebViewportInfo::currentScale() const if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) return interactionEngine->currentCSSScale(); - return QtViewportInteractionEngine::Constraints().initialScale; + return m_webViewPrivate->attributes.initialScale; } QVariant QWebViewportInfo::devicePixelRatio() const { - if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) - return interactionEngine->constraints().devicePixelRatio; - - return QtViewportInteractionEngine::Constraints().devicePixelRatio; + return m_webViewPrivate->attributes.devicePixelRatio; } QVariant QWebViewportInfo::initialScale() const { - if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) - return interactionEngine->constraints().initialScale; - - return QtViewportInteractionEngine::Constraints().initialScale; + return m_webViewPrivate->attributes.initialScale; } QVariant QWebViewportInfo::minimumScale() const { - if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) - return interactionEngine->constraints().minimumScale; - - return QtViewportInteractionEngine::Constraints().minimumScale; + return m_webViewPrivate->attributes.minimumScale; } QVariant QWebViewportInfo::maximumScale() const { - if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) - return interactionEngine->constraints().maximumScale; - - return QtViewportInteractionEngine::Constraints().maximumScale; + return m_webViewPrivate->attributes.maximumScale; } QVariant QWebViewportInfo::isScalable() const { - if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) - return interactionEngine->constraints().isUserScalable; - - return QtViewportInteractionEngine::Constraints().isUserScalable; + return !!m_webViewPrivate->attributes.userScalable; } QVariant QWebViewportInfo::layoutSize() const { - if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) - return interactionEngine->constraints().layoutSize; - - return QVariant(QSize()); + return QSizeF(m_webViewPrivate->attributes.layoutSize.width(), m_webViewPrivate->attributes.layoutSize.height()); } void QWebViewportInfo::didUpdateContentsSize() diff --git a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp index e0c2c256c..b81c07610 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.cpp @@ -31,6 +31,10 @@ ByteArrayTestData::ByteArrayTestData(QObject* parent) Q_ASSERT(m_latin1Data != m_utf8Data); } +ByteArrayTestData::~ByteArrayTestData() +{ +} + QVariant ByteArrayTestData::latin1Data() const { return QVariant(m_latin1Data); diff --git a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h index f7838f072..7f87e72dd 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h +++ b/Source/WebKit2/UIProcess/API/qt/tests/bytearraytestdata.h @@ -33,7 +33,7 @@ class QWEBKIT_EXPORT ByteArrayTestData : public QObject { public: ByteArrayTestData(QObject* parent = 0); - virtual ~ByteArrayTestData() { } + virtual ~ByteArrayTestData(); QVariant latin1Data() const; QVariant utf8Data() const; diff --git a/Source/WebKit2/UIProcess/API/qt/tests/html/basic_page.html b/Source/WebKit2/UIProcess/API/qt/tests/html/basic_page.html index b4eea41bd..53726e4a6 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/html/basic_page.html +++ b/Source/WebKit2/UIProcess/API/qt/tests/html/basic_page.html @@ -1 +1,6 @@ +<html> +<head> +<title> Basic Page </title> +</head> <h1>Basic page</h1> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/html/inputmethod.html b/Source/WebKit2/UIProcess/API/qt/tests/html/inputmethod.html new file mode 100644 index 000000000..f3ca937d2 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/html/inputmethod.html @@ -0,0 +1,9 @@ +<html> +<head> +<title>Basic Page For Input Method Testing</title> +</head> +<body> +<h1>Basic page</h1> +<input id="inputField" /> +</body> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/inspectorserver.pro b/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/inspectorserver.pro new file mode 100644 index 000000000..4a8d86f80 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/inspectorserver.pro @@ -0,0 +1,4 @@ +include(../tests.pri) +SOURCES += $${TARGET}.cpp +QT += webkit-private +DEFINES += IMPORT_DIR=\"\\\"$${ROOT_BUILD_DIR}$${QMAKE_DIR_SEP}imports\\\"\" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp b/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp new file mode 100644 index 000000000..0d0bb6902 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp @@ -0,0 +1,183 @@ +/* + 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 "../testwindow.h" +#include "../util.h" + +#include <QNetworkAccessManager> +#include <QNetworkReply> +#include <QNetworkRequest> +#include <QScopedPointer> +#include <QtQml/QQmlEngine> +#include <QtTest/QtTest> +#include <private/qquickwebview_p.h> +#include <private/qwebpreferences_p.h> + +#define INSPECTOR_SERVER_PORT "23654" +static const QUrl s_inspectorServerHttpBaseUrl("http://localhost:"INSPECTOR_SERVER_PORT); +static const QUrl s_inspectorServerWebSocketBaseUrl("ws://localhost:"INSPECTOR_SERVER_PORT); + +class tst_InspectorServer : public QObject { + Q_OBJECT +public: + tst_InspectorServer(); + +private slots: + void init(); + void cleanup(); + + void testPageList(); + void testRemoteDebuggingMessage(); + void openRemoteDebuggingSession(); +private: + void prepareWebViewComponent(); + inline QQuickWebView* newWebView(); + inline QQuickWebView* webView() const; + QJsonArray fetchPageList() const; + QScopedPointer<TestWindow> m_window; + QScopedPointer<QQmlComponent> m_component; +}; + +tst_InspectorServer::tst_InspectorServer() +{ + qputenv("QTWEBKIT_INSPECTOR_SERVER", INSPECTOR_SERVER_PORT); + addQtWebProcessToPath(); + prepareWebViewComponent(); +} + +void tst_InspectorServer::prepareWebViewComponent() +{ + static QQmlEngine* engine = new QQmlEngine(this); + engine->addImportPath(QString::fromUtf8(IMPORT_DIR)); + + m_component.reset(new QQmlComponent(engine, this)); + + m_component->setData(QByteArrayLiteral("import QtQuick 2.0\n" + "import QtWebKit 3.0\n" + "WebView {}") + , QUrl()); +} + +QQuickWebView* tst_InspectorServer::newWebView() +{ + QObject* viewInstance = m_component->create(); + + return qobject_cast<QQuickWebView*>(viewInstance); +} + +void tst_InspectorServer::init() +{ + m_window.reset(new TestWindow(newWebView())); + webView()->experimental()->preferences()->setDeveloperExtrasEnabled(true); +} + +void tst_InspectorServer::cleanup() +{ + m_window.reset(); +} + +inline QQuickWebView* tst_InspectorServer::webView() const +{ + return static_cast<QQuickWebView*>(m_window->webView.data()); +} + +QJsonArray tst_InspectorServer::fetchPageList() const +{ + QNetworkAccessManager qnam; + QScopedPointer<QNetworkReply> reply(qnam.get(QNetworkRequest(s_inspectorServerHttpBaseUrl.resolved(QUrl("pagelist.json"))))); + waitForSignal(reply.data(), SIGNAL(finished())); + return QJsonDocument::fromJson(reply->readAll()).array(); +} + +void tst_InspectorServer::testPageList() +{ + QUrl testPageUrl = QUrl::fromLocalFile(QLatin1String(TESTS_SOURCE_DIR "/html/basic_page.html")); + LoadStartedCatcher catcher(webView()); + webView()->setUrl(testPageUrl); + waitForSignal(&catcher, SIGNAL(finished())); + + // Our page has developerExtrasEnabled and should be the only one in the list. + QJsonArray pageList = fetchPageList(); + QCOMPARE(pageList.size(), 1); + QCOMPARE(testPageUrl.toString(), pageList.at(0).toObject().value("url").toString()); +} + +void tst_InspectorServer::testRemoteDebuggingMessage() +{ + QJsonArray pageList = fetchPageList(); + QCOMPARE(pageList.size(), 1); + + // Test sending a raw remote debugging message through our web socket server. + // For this specific message see: http://code.google.com/chrome/devtools/docs/protocol/tot/runtime.html#command-evaluate + QLatin1String jsExpression("2 + 2"); + QLatin1String jsExpressionResult("4"); + QScopedPointer<QQuickWebView> webSocketQueryWebView(newWebView()); + webSocketQueryWebView->loadHtml(QString( + "<script type=\"text/javascript\">\n" + "var socket = new WebSocket('%1/devtools/page/%2');\n" + "socket.onmessage = function(message) {\n" + "var response = JSON.parse(message.data);\n" + "if (response.id === 1)\n" + "document.title = response.result.result.value;\n" + "}\n" + "socket.onopen = function() {\n" + "socket.send('{\"id\": 1, \"method\": \"Runtime.evaluate\", \"params\": {\"expression\": \"%3\" } }');\n" + "}\n" + "</script>") + .arg(s_inspectorServerWebSocketBaseUrl.toString()) + .arg(pageList.at(0).toObject().value("id").toDouble()) + .arg(jsExpression)); + + for (int i = 0; i < 10; ++i) { + if (!webSocketQueryWebView->title().isEmpty()) + break; + waitForSignal(webSocketQueryWebView.data(), SIGNAL(titleChanged()), 500); + } + + QCOMPARE(webSocketQueryWebView->title(), jsExpressionResult); +} + +void tst_InspectorServer::openRemoteDebuggingSession() +{ + QJsonArray pageList = fetchPageList(); + QCOMPARE(pageList.size(), 1); + + QScopedPointer<QQuickWebView> inspectorWebView(newWebView()); + LoadStartedCatcher catcher2(inspectorWebView.data()); + inspectorWebView->setUrl(s_inspectorServerHttpBaseUrl.resolved(QUrl(pageList.at(0).toObject().value("inspectorUrl").toString()))); + waitForSignal(&catcher2, SIGNAL(finished())); + for (int i = 0; i < 10; ++i) { + if (!inspectorWebView->title().isEmpty()) + break; + waitForSignal(inspectorWebView.data(), SIGNAL(titleChanged()), 500); + } + + // To test the whole pipeline this exploits a behavior of the inspector front-end which won't provide any title unless the + // debugging session was established correctly through web socket. It should be something like "Web Inspector - <Page URL>". + // So this test case will fail if: + // - The page list didn't return a valid inspector URL + // - Or the front-end couldn't be loaded through the inspector HTTP server + // - Or the web socket connection couldn't be established between the front-end and the page through the inspector server + // Let's see if this test isn't raising too many false positives, in which case we should use a better predicate if available. + QVERIFY(!inspectorWebView->title().isEmpty()); +} + +QTEST_MAIN(tst_InspectorServer) + +#include "tst_inspectorserver.moc" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp index f5f976663..39e6b54cf 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp @@ -141,7 +141,11 @@ static void gatherAPI(const QString& prefix, const QMetaMethod& method, QStringL { if (method.access() != QMetaMethod::Private) { const char* methodTypeName = !!strlen(method.typeName()) ? method.typeName() : "void"; +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(QString::fromLatin1(method.methodSignature())).arg(QString::fromLatin1(methodTypeName)); +#else *output << QString::fromLatin1("%1%2 --> %3").arg(prefix).arg(method.signature()).arg(methodTypeName); +#endif checkKnownType(methodTypeName); foreach (QByteArray paramType, method.parameterTypes()) diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro index 9d16a7bdd..59a3ca5b4 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro @@ -19,4 +19,6 @@ OTHER_FILES += \ DesktopBehavior/tst_linkHovered.qml \ DesktopBehavior/tst_loadHtml.qml \ DesktopBehavior/tst_messaging.qml \ - DesktopBehavior/tst_navigationRequested.qml + DesktopBehavior/tst_navigationRequested.qml \ + DesktopBehavior/tst_singleFileupload.qml \ + DesktopBehavior/tst_multiFileupload.qml diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_multiFileUpload.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_multiFileUpload.qml new file mode 100644 index 000000000..f43f65672 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_multiFileUpload.qml @@ -0,0 +1,66 @@ +import QtQuick 2.0 +import QtTest 1.0 +import QtWebKit 3.0 +import QtWebKit.experimental 1.0 +import "../common" + +// FIXME: Added to Desktop tests because we want to have mouseClick() to open the <input> tag. We can move it back +// when TestCase starts supporting touch events, see https://bugreports.qt.nokia.com/browse/QTBUG-23083. +TestWebView { + id: webView + + width: 400 + height: 400 + + property bool selectFile + + experimental.filePicker: Item { + Timer { + running: true + interval: 1 + onTriggered: { + var selectedFiles = ["filename1", "filename2"] + if (selectFile) + model.accept(selectedFiles) + else + model.reject(); + } + } + } + + SignalSpy { + id: titleSpy + target: webView + signalName: "titleChanged" + } + + TestCase { + id: test + name: "WebViewMultiFilePicker" + when: windowShown + + function init() { + webView.url = Qt.resolvedUrl("../common/multifileupload.html") + verify(webView.waitForLoadSucceeded()) + titleSpy.clear() + } + + function openItemSelector() { + mouseClick(webView, 15, 15, Qt.LeftButton) + } + + function test_accept() { + webView.selectFile = true; + openItemSelector() + titleSpy.wait() + compare(webView.title, "filename1,filename2") + } + + function test_reject() { + var oldTitle = webView.title + webView.selectFile = false; + openItemSelector() + compare(webView.title, oldTitle) + } + } +} diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_singleFileUpload.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_singleFileUpload.qml new file mode 100644 index 000000000..7ca9efa38 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_singleFileUpload.qml @@ -0,0 +1,79 @@ +import QtQuick 2.0 +import QtTest 1.0 +import QtWebKit 3.0 +import QtWebKit.experimental 1.0 +import "../common" + +// FIXME: Added to Desktop tests because we want to have mouseClick() to open the <input> tag. We can move it back +// when TestCase starts supporting touch events, see https://bugreports.qt.nokia.com/browse/QTBUG-23083. +TestWebView { + id: webView + + width: 400 + height: 400 + + property bool selectFile + property bool acceptMultiple: false + + experimental.filePicker: Item { + Timer { + running: true + interval: 1 + onTriggered: { + var selectedFiles = ["filename1", "filename2"] + if (selectFile) { + if (acceptMultiple) + model.accept(selectedFiles) + else + model.accept("acceptedfilename"); + } + else + model.reject(); + } + } + } + + SignalSpy { + id: titleSpy + target: webView + signalName: "titleChanged" + } + + TestCase { + id: test + name: "WebViewSingleFilePicker" + when: windowShown + + function init() { + webView.url = Qt.resolvedUrl("../common/singlefileupload.html") + verify(webView.waitForLoadSucceeded()) + titleSpy.clear() + } + + function openItemSelector() { + mouseClick(webView, 15, 15, Qt.LeftButton) + } + + function test_accept() { + webView.selectFile = true; + openItemSelector() + titleSpy.wait() + compare(webView.title, "acceptedfilename") + } + + function test_multiple() { + webView.selectFile = true; + webView.acceptMultiple = true; + openItemSelector() + titleSpy.wait() + compare(webView.title, "filename1") + } + + function test_reject() { + var oldTitle = webView.title + webView.selectFile = false; + openItemSelector() + compare(webView.title, oldTitle) + } + } +} 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 875bcd060..4fe081298 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 @@ -3,8 +3,9 @@ import QtTest 1.0 import QtWebKit 3.0 import QtWebKit.experimental 1.0 import Test 1.0 +import "../common" -WebView { +TestWebView { id: webView width: 400 height: 300 @@ -61,12 +62,6 @@ WebView { ] } - SignalSpy { - id: spyTitle - target: webView - signalName: "titleChanged" - } - ByteArrayTestData { id: byteArrayHelper } @@ -75,58 +70,47 @@ WebView { name: "WebViewApplicationSchemes" function test_applicationScheme() { - spyTitle.clear() - compare(spyTitle.count, 0) var testUrl = "applicationScheme://something" webView.url = testUrl - spyTitle.wait() + verify(webView.waitForLoadSucceeded()) 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.url = testUrl - spyTitle.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Scheme2 Reply") testUrl = "scheme1://some-url-string" webView.url = testUrl - spyTitle.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Scheme1 Reply") - - compare(spyTitle.count, 2) } function test_multipleUrlsForScheme() { - spyTitle.clear() - compare(spyTitle.count, 0) var testUrl = "scheme3://url1" - webView.url = testUrl - spyTitle.wait() + webView.url = testUrl + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Scheme3 Reply1") testUrl = "scheme3://url2" - webView.url = testUrl - spyTitle.wait() + webView.url = testUrl + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Scheme3 Reply2") - compare(spyTitle.count, 2) } - function test_charsets() { - spyTitle.clear() - compare(spyTitle.count, 0) + function test_charsets() { var testUrl = "schemeCharset://latin1" webView.url = testUrl - spyTitle.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "title with copyright ©") testUrl = "schemeCharset://utf-8" webView.url = testUrl - spyTitle.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "title with copyright ©") } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_loadUrl.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_loadUrl.qml index 8fcbae54a..7ab69bd15 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_loadUrl.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_loadUrl.qml @@ -13,7 +13,7 @@ TestWebView { onLoadProgressChanged: { if (watchProgress && webView.loadProgress != 100) { watchProgress = false - load('') + url = '' } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_preferences.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_preferences.qml index 4f356e88b..16ff35c52 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_preferences.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_preferences.qml @@ -198,8 +198,10 @@ Item { function test_standardFontFamilyChanged() { var url = Qt.resolvedUrl("../common/font-preferences.html?standard#font-family") webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, defaultStandardFontFamily) @@ -207,8 +209,10 @@ Item { standardFontFamilySpy.wait() compare(standardFontFamilySpy.count, 1) webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, "foobar") } @@ -216,8 +220,10 @@ Item { function test_fontSizeChanged() { var url = Qt.resolvedUrl("../common/font-preferences.html?standard#font-size") webView.url = url - titleSpy.wait() - compare(webView.title, "Original Title") + verify(webView.waitForLoadSucceeded()) + compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, defaultFontSize.toString() + "px") @@ -225,8 +231,10 @@ Item { defaultFontSizeSpy.wait() compare(defaultFontSizeSpy.count, 1) webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, (defaultFontSize + 1).toString() + "px") } @@ -234,8 +242,10 @@ Item { function test_fixedFontSizeChanged() { var url = Qt.resolvedUrl("../common/font-preferences.html?fixed#font-size") webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, defaultFixedFontSize.toString() + "px") @@ -243,14 +253,18 @@ Item { defaultFixedFontSizeSpy.wait() compare(defaultFixedFontSizeSpy.count, 1) webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, (defaultFixedFontSize + 1).toString() + "px") webView.url = Qt.resolvedUrl("../common/font-preferences.html?standard#font-size") - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, defaultFontSize.toString() + "px") } @@ -259,8 +273,10 @@ Item { verify(defaultMinimumFontSize < defaultFontSize) var url = Qt.resolvedUrl("../common/font-preferences.html?minimum#font-size") webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() var smallerFontSize = webView.title smallerFontSize = smallerFontSize.substring(0, smallerFontSize.length - 2) @@ -271,8 +287,10 @@ Item { minimumFontSizeSpy.wait() compare(minimumFontSizeSpy.count, 1) webView.url = url - titleSpy.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Original Title") + titleSpy.clear() + titleSpy.wait() compare(webView.title, defaultFontSize.toString() + "px") } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_titleChanged.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_titleChanged.qml index 04f2c7e13..38e587d57 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_titleChanged.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_titleChanged.qml @@ -21,9 +21,10 @@ TestWebView { compare(spyTitle.count, 0) var testUrl = Qt.resolvedUrl("../common/test3.html") webView.url = testUrl - verify(webView.waitForLoadSucceeded()) - spyTitle.wait() + verify(webView.waitForLoadSucceeded()) compare(webView.title, "Test page 3") + spyTitle.clear() + spyTitle.wait() compare(webView.title, "New Title") } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/multifileupload.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/multifileupload.html new file mode 100644 index 000000000..7701ed4b5 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/multifileupload.html @@ -0,0 +1,11 @@ +<html> +<head> +<meta name="viewport" initial-scale=1"> +<title> Mutli-file Upload </title> +<script src = "./titleupdate.js"> +</script> + +<body> +<input type="file" name="file" id="upfile" onchange="updateTitle()" multiple/> +</body> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/singlefileupload.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/singlefileupload.html new file mode 100644 index 000000000..38e345f4b --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/singlefileupload.html @@ -0,0 +1,11 @@ +<html> +<head> +<meta name="viewport" initial-scale=1"> +<title> Single File Upload </title> +<script src = "./titleupdate.js"> +</script> + +<body> +<input type="file" name="file" id="upfile" onchange="updateTitle()"/> +</body> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/titleupdate.js b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/titleupdate.js new file mode 100644 index 000000000..2a5bac0ac --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/titleupdate.js @@ -0,0 +1,15 @@ +function updateTitle() +{ + var inp = document.getElementById("upfile"); + var allfiles = new String(""); + var name = new String(""); + for (var i = 0; i < inp.files.length; ++i) + { + name = inp.files.item(i).name; + if (allfiles.length == 0) + allfiles = name; + else + allfiles = allfiles + "," + name; + } + document.title = allfiles; +} 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 782b041ca..ab57556bd 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/tst_qmltests.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/tst_qmltests.cpp @@ -48,5 +48,5 @@ int main(int argc, char** argv) #ifdef DISABLE_FLICKABLE_VIEWPORT QQuickWebViewExperimental::setFlickableViewportEnabled(false); #endif - return quick_test_main(argc, argv, "qmltests", 0, QUICK_TEST_SOURCE_DIR); + return quick_test_main(argc, argv, "qmltests", QUICK_TEST_SOURCE_DIR); } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qquickwebview/tst_qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/tests/qquickwebview/tst_qquickwebview.cpp index a6b13990a..4d9ce7ba1 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qquickwebview/tst_qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/qquickwebview/tst_qquickwebview.cpp @@ -20,12 +20,11 @@ #include "../testwindow.h" #include "../util.h" -#include <QDeclarativeEngine> #include <QScopedPointer> +#include <QtQml/QQmlEngine> #include <QtTest/QtTest> #include <private/qquickwebpage_p.h> #include <private/qquickwebview_p.h> -#include <private/qwebloadrequest_p.h> class tst_QQuickWebView : public QObject { Q_OBJECT @@ -55,14 +54,18 @@ private slots: void removeFromCanvas(); void multipleWebViewWindows(); void multipleWebViews(); + void titleUpdate(); void transparentWebViews(); + void inputMethod(); + private: void prepareWebViewComponent(); inline QQuickWebView* newWebView(); inline QQuickWebView* webView() const; + void runJavaScript(const QString& script); QScopedPointer<TestWindow> m_window; - QScopedPointer<QDeclarativeComponent> m_component; + QScopedPointer<QQmlComponent> m_component; }; tst_QQuickWebView::tst_QQuickWebView() @@ -73,10 +76,10 @@ tst_QQuickWebView::tst_QQuickWebView() void tst_QQuickWebView::prepareWebViewComponent() { - static QDeclarativeEngine* engine = new QDeclarativeEngine(this); + static QQmlEngine* engine = new QQmlEngine(this); engine->addImportPath(QString::fromUtf8(IMPORT_DIR)); - m_component.reset(new QDeclarativeComponent(engine, this)); + m_component.reset(new QQmlComponent(engine, this)); m_component->setData(QByteArrayLiteral("import QtQuick 2.0\n" "import QtWebKit 3.0\n" @@ -87,8 +90,9 @@ void tst_QQuickWebView::prepareWebViewComponent() QQuickWebView* tst_QQuickWebView::newWebView() { QObject* viewInstance = m_component->create(); - - return qobject_cast<QQuickWebView*>(viewInstance); + QQuickWebView* webView = qobject_cast<QQuickWebView*>(viewInstance); + webView->experimental()->setDevicePixelRatio(1.5); + return webView; } void tst_QQuickWebView::init() @@ -106,6 +110,13 @@ inline QQuickWebView* tst_QQuickWebView::webView() const return static_cast<QQuickWebView*>(m_window->webView.data()); } +void tst_QQuickWebView::runJavaScript(const QString &script) +{ + QEventLoop loop; + webView()->runJavaScriptInMainFrame(script, &loop, "quit"); + loop.exec(); +} + void tst_QQuickWebView::accessPage() { QQuickWebPage* const pageDirectAccess = webView()->page(); @@ -124,32 +135,6 @@ void tst_QQuickWebView::navigationStatusAtStartup() QCOMPARE(webView()->loading(), false); } -class LoadStartedCatcher : public QObject { - Q_OBJECT -public: - LoadStartedCatcher(QQuickWebView* webView) - : m_webView(webView) - { - connect(m_webView, SIGNAL(loadingChanged(QWebLoadRequest*)), this, SLOT(onLoadingChanged(QWebLoadRequest*))); - } - -public slots: - void onLoadingChanged(QWebLoadRequest* loadRequest) - { - if (loadRequest->status() == QQuickWebView::LoadStartedStatus) { - QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); - - QCOMPARE(m_webView->loading(), true); - } - } - -signals: - void finished(); - -private: - QQuickWebView* m_webView; -}; - void tst_QQuickWebView::stopEnabledAfterLoadStarted() { QCOMPARE(webView()->loading(), false); @@ -344,6 +329,24 @@ void tst_QQuickWebView::multipleWebViews() QTest::qWait(200); } +void tst_QQuickWebView::titleUpdate() +{ + QSignalSpy titleSpy(webView(), SIGNAL(titleChanged())); + + // Load page with no title + webView()->setUrl(QUrl::fromLocalFile(QLatin1String(TESTS_SOURCE_DIR "/html/basic_page2.html"))); + QVERIFY(waitForLoadSucceeded(webView())); + QCOMPARE(titleSpy.size(), 1); + + titleSpy.clear(); + + // No titleChanged signal for failed load + webView()->setUrl(QUrl::fromLocalFile(QLatin1String(TESTS_SOURCE_DIR "/html/file_that_does_not_exist.html"))); + QVERIFY(waitForLoadFailed(webView())); + QCOMPARE(titleSpy.size(), 0); + +} + void tst_QQuickWebView::transparentWebViews() { showWebView(); @@ -371,6 +374,19 @@ void tst_QQuickWebView::transparentWebViews() // FIXME: test actual rendering results; https://bugs.webkit.org/show_bug.cgi?id=80609. } +void tst_QQuickWebView::inputMethod() +{ + QQuickWebView* view = webView(); + view->setUrl(QUrl::fromLocalFile(QLatin1String(TESTS_SOURCE_DIR "/html/inputmethod.html"))); + QVERIFY(waitForLoadSucceeded(view)); + + QVERIFY(!view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); + runJavaScript("document.getElementById('inputField').focus();"); + QVERIFY(view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); + runJavaScript("document.getElementById('inputField').blur();"); + QVERIFY(!view->flags().testFlag(QQuickItem::ItemAcceptsInputMethod)); +} + void tst_QQuickWebView::scrollRequest() { webView()->setSize(QSizeF(300, 400)); @@ -382,7 +398,7 @@ void tst_QQuickWebView::scrollRequest() // Use qRound as that is also used when calculating the position // in WebKit. int y = qRound(50 * webView()->page()->contentsScale()); - QVERIFY(webView()->experimental()->contentY() == y); + QVERIFY(webView()->contentY() == y); } QTEST_MAIN(tst_QQuickWebView) diff --git a/Source/WebKit2/UIProcess/API/qt/tests/tests.pri b/Source/WebKit2/UIProcess/API/qt/tests/tests.pri index aa8da8bc9..ded493f88 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/tests.pri +++ b/Source/WebKit2/UIProcess/API/qt/tests/tests.pri @@ -3,13 +3,14 @@ TEMPLATE = app VPATH += $$_PRO_FILE_PWD_ TARGET = tst_$$TARGET -HEADERS += ../bytearraytestdata.h +HEADERS += ../bytearraytestdata.h \ + ../util.h SOURCES += ../util.cpp \ ../bytearraytestdata.cpp INCLUDEPATH += $$PWD -QT += testlib declarative quick webkit +QT += testlib declarative quick quick-private webkit DEFINES += TESTS_SOURCE_DIR=\\\"$$PWD\\\" \ QWP_PATH=\\\"$${ROOT_BUILD_DIR}/bin\\\" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/util.cpp b/Source/WebKit2/UIProcess/API/qt/tests/util.cpp index 43a6696ef..2582848aa 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/util.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/util.cpp @@ -20,6 +20,7 @@ #include "util.h" #include "private/qquickwebview_p.h" #include "private/qwebloadrequest_p.h" +#include <QtTest/QtTest> #include <stdio.h> void addQtWebProcessToPath() @@ -120,4 +121,20 @@ void suppressDebugOutput() qputenv("QT_WEBKIT_SUPPRESS_WEB_PROCESS_OUTPUT", "1"); } + +LoadStartedCatcher::LoadStartedCatcher(QQuickWebView* webView) + : m_webView(webView) +{ + connect(m_webView, SIGNAL(loadingChanged(QWebLoadRequest*)), this, SLOT(onLoadingChanged(QWebLoadRequest*))); +} + +void LoadStartedCatcher::onLoadingChanged(QWebLoadRequest* loadRequest) +{ + if (loadRequest->status() == QQuickWebView::LoadStartedStatus) { + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + + QCOMPARE(m_webView->loading(), true); + } +} + #include "util.moc" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/util.h b/Source/WebKit2/UIProcess/API/qt/tests/util.h index f7be8b11e..9d076f1b4 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/util.h +++ b/Source/WebKit2/UIProcess/API/qt/tests/util.h @@ -23,6 +23,7 @@ #include <QTimer> class QQuickWebView; +class QWebLoadRequest; #if !defined(TESTS_SOURCE_DIR) #define TESTS_SOURCE_DIR "" @@ -33,3 +34,15 @@ bool waitForSignal(QObject*, const char* signal, int timeout = 10000); bool waitForLoadSucceeded(QQuickWebView* webView, int timeout = 10000); bool waitForLoadFailed(QQuickWebView* webView, int timeout = 10000); void suppressDebugOutput(); + +class LoadStartedCatcher : public QObject { + Q_OBJECT +public: + LoadStartedCatcher(QQuickWebView* webView); +public slots: + void onLoadingChanged(QWebLoadRequest* loadRequest); +signals: + void finished(); +private: + QQuickWebView* m_webView; +}; diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxy.h b/Source/WebKit2/UIProcess/DrawingAreaProxy.h index 8b8dc2b0d..e86ee8cf2 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxy.h +++ b/Source/WebKit2/UIProcess/DrawingAreaProxy.h @@ -29,6 +29,7 @@ #include "BackingStore.h" #include "DrawingAreaInfo.h" +#include <WebCore/FloatPoint.h> #include <WebCore/IntRect.h> #include <WebCore/IntSize.h> #include <stdint.h> @@ -47,7 +48,6 @@ namespace CoreIPC { } namespace WebCore { - class FloatPoint; class TransformationMatrix; } @@ -84,17 +84,15 @@ public: void setSize(const WebCore::IntSize&, const WebCore::IntSize& scrollOffset); virtual void pageCustomRepresentationChanged() { } + virtual void waitForPossibleGeometryUpdate() { } #if USE(UI_SIDE_COMPOSITING) virtual void updateViewport(); 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, const WebCore::FloatRect&) { } - virtual void paintLayerTree(BackingStore::PlatformGraphicsContext) { } LayerTreeHostProxy* layerTreeHostProxy() const { return m_layerTreeHostProxy.get(); } - virtual void setVisibleContentsRectForScaling(const WebCore::IntRect& visibleContentsRect, float scale) { } - virtual void setVisibleContentsRectForPanning(const WebCore::IntRect& visibleContentsRect, const WebCore::FloatPoint& trajectoryVector) { } + virtual void setVisibleContentsRect(const WebCore::IntRect& visibleContentsRect, float scale, const WebCore::FloatPoint& trajectoryVector, const WebCore::FloatPoint& accurateVisibleContentsPosition = WebCore::FloatPoint()) { } virtual void createTileForLayer(int layerID, int tileID, const WebKit::UpdateInfo&) { } virtual void updateTileForLayer(int layerID, int tileID, const WebKit::UpdateInfo&) { } virtual void removeTileForLayer(int layerID, int tileID) { } diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp index c0d044bf8..6519441b0 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp +++ b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp @@ -127,6 +127,11 @@ void DrawingAreaProxyImpl::deviceScaleFactorDidChange() backingStoreStateDidChange(RespondImmediately); } +void DrawingAreaProxyImpl::layerHostingModeDidChange() +{ + m_webPageProxy->process()->send(Messages::DrawingArea::SetLayerHostingMode(m_webPageProxy->layerHostingMode()), m_webPageProxy->pageID()); +} + void DrawingAreaProxyImpl::visibilityDidChange() { if (!m_webPageProxy->isViewVisible()) { @@ -348,29 +353,12 @@ void DrawingAreaProxyImpl::didReceiveLayerTreeHostProxyMessage(CoreIPC::Connecti m_layerTreeHostProxy->didReceiveLayerTreeHostProxyMessage(connection, messageID, arguments); } -void DrawingAreaProxyImpl::setVisibleContentsRectForScaling(const WebCore::IntRect& visibleContentsRect, float scale) -{ - if (m_layerTreeHostProxy) - m_layerTreeHostProxy->setVisibleContentsRectForScaling(visibleContentsRect, scale); -} - -void DrawingAreaProxyImpl::setVisibleContentsRectForPanning(const WebCore::IntRect& visibleContentsRect, const WebCore::FloatPoint& trajectoryVector) +void DrawingAreaProxyImpl::setVisibleContentsRect(const WebCore::IntRect& visibleContentsRect, float scale, const WebCore::FloatPoint& trajectoryVector, const WebCore::FloatPoint& accurateVisibleContentsPosition) { if (m_layerTreeHostProxy) - m_layerTreeHostProxy->setVisibleContentsRectForPanning(visibleContentsRect, trajectoryVector); + m_layerTreeHostProxy->setVisibleContentsRect(visibleContentsRect, scale, trajectoryVector, accurateVisibleContentsPosition); } -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, clipRect); -} #endif void DrawingAreaProxyImpl::exitAcceleratedCompositingMode() diff --git a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h index 613073bab..c67cd93da 100644 --- a/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h +++ b/Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h @@ -54,6 +54,8 @@ private: // DrawingAreaProxy virtual void sizeDidChange(); virtual void deviceScaleFactorDidChange(); + virtual void layerHostingModeDidChange() OVERRIDE; + virtual void visibilityDidChange(); virtual void setBackingStoreIsDiscardable(bool); virtual void waitForBackingStoreUpdateOnNextPaint(); @@ -78,10 +80,7 @@ private: bool isInAcceleratedCompositingMode() const { return !m_layerTreeContext.isEmpty(); } #if USE(UI_SIDE_COMPOSITING) - virtual void setVisibleContentsRectForScaling(const WebCore::IntRect& visibleContentsRect, float scale); - virtual void setVisibleContentsRectForPanning(const WebCore::IntRect& visibleContentsRect, const WebCore::FloatPoint&); - virtual void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity, const WebCore::FloatRect&); - virtual void paintLayerTree(BackingStore::PlatformGraphicsContext); + virtual void setVisibleContentsRect(const WebCore::IntRect& visibleContentsRect, float scale, const WebCore::FloatPoint& trajectory, const WebCore::FloatPoint& accurateVisibleContentsPosition = WebCore::FloatPoint()); void didReceiveLayerTreeHostProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); #endif #else diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp b/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp new file mode 100644 index 000000000..f335849ed --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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. + */ + +#include "config.h" + +#if ENABLE(INSPECTOR_SERVER) + +#include "WebInspectorServer.h" + +#include "WebInspectorProxy.h" +#include "WebSocketServerConnection.h" +#include <WebCore/HTTPRequest.h> + +using namespace WebCore; + +namespace WebKit { + +static unsigned pageIdFromRequestPath(const String& path) +{ + size_t start = path.reverseFind('/'); + String numberString = path.substring(start + 1, path.length() - start - 1); + + bool ok = false; + unsigned number = numberString.toUIntStrict(&ok); + if (!ok) + return 0; + return number; +} + +WebInspectorServer& WebInspectorServer::shared() +{ + static WebInspectorServer& server = *new WebInspectorServer; + return server; +} + +WebInspectorServer::WebInspectorServer() + : WebSocketServer(this) + , m_nextAvailablePageId(1) +{ +} + +WebInspectorServer::~WebInspectorServer() +{ + // Close any remaining open connections. + HashMap<unsigned, WebSocketServerConnection*>::iterator end = m_connectionMap.end(); + for (HashMap<unsigned, WebSocketServerConnection*>::iterator it = m_connectionMap.begin(); it != end; ++it) { + WebSocketServerConnection* connection = it->second; + WebInspectorProxy* client = m_clientMap.get(connection->identifier()); + closeConnection(client, connection); + } +} + +int WebInspectorServer::registerPage(WebInspectorProxy* client) +{ +#ifndef ASSERT_DISABLED + ClientMap::iterator end = m_clientMap.end(); + for (ClientMap::iterator it = m_clientMap.begin(); it != end; ++it) + ASSERT(it->second != client); +#endif + + int pageId = m_nextAvailablePageId++; + m_clientMap.set(pageId, client); + return pageId; +} + +void WebInspectorServer::unregisterPage(int pageId) +{ + m_clientMap.remove(pageId); + WebSocketServerConnection* connection = m_connectionMap.get(pageId); + if (connection) + closeConnection(0, connection); +} + +void WebInspectorServer::sendMessageOverConnection(unsigned pageIdForConnection, const String& message) +{ + WebSocketServerConnection* connection = m_connectionMap.get(pageIdForConnection); + if (connection) + connection->sendWebSocketMessage(message); +} + +void WebInspectorServer::didReceiveUnrecognizedHTTPRequest(WebSocketServerConnection* connection, PassRefPtr<HTTPRequest> request) +{ + // request->url() contains only the path extracted from the HTTP request line + // and KURL is poor at parsing incomplete URLs, so extract the interesting parts manually. + String path = request->url(); + size_t pathEnd = path.find('?'); + if (pathEnd == notFound) + pathEnd = path.find('#'); + if (pathEnd != notFound) + path.truncate(pathEnd); + + // Ask for the complete payload in memory for the sake of simplicity. A more efficient way would be + // to ask for header data and then let the platform abstraction write the payload straight on the connection. + Vector<char> body; + String contentType; + bool found = platformResourceForPath(path, body, contentType); + + HTTPHeaderMap headerFields; + headerFields.set("Connection", "close"); + headerFields.set("Content-Length", String::number(body.size())); + if (found) + headerFields.set("Content-Type", contentType); + + // Send when ready and close immediately afterwards. + connection->sendHTTPResponseHeader(found ? 200 : 404, found ? "OK" : "Not Found", headerFields); + connection->sendRawData(body.data(), body.size()); + connection->shutdownAfterSendOrNow(); +} + +bool WebInspectorServer::didReceiveWebSocketUpgradeHTTPRequest(WebSocketServerConnection*, PassRefPtr<HTTPRequest> request) +{ + String path = request->url(); + + // NOTE: Keep this in sync with WebCore/inspector/front-end/inspector.js. + DEFINE_STATIC_LOCAL(const String, inspectorWebSocketConnectionPathPrefix, ("/devtools/page/")); + + // Unknown path requested. + if (!path.startsWith(inspectorWebSocketConnectionPathPrefix)) + return false; + + int pageId = pageIdFromRequestPath(path); + // Invalid page id. + if (!pageId) + return false; + + // There is no client for that page id. + WebInspectorProxy* client = m_clientMap.get(pageId); + if (!client) + return false; + + return true; +} + +void WebInspectorServer::didEstablishWebSocketConnection(WebSocketServerConnection* connection, PassRefPtr<HTTPRequest> request) +{ + String path = request->url(); + unsigned pageId = pageIdFromRequestPath(path); + ASSERT(pageId); + + // Ignore connections to a page that already have a remote inspector connected. + if (m_connectionMap.contains(pageId)) { + LOG_ERROR("A remote inspector connection already exist for page ID %d. Ignoring.", pageId); + connection->shutdownNow(); + return; + } + + // Map the pageId to the connection in case we need to close the connection locally. + connection->setIdentifier(pageId); + m_connectionMap.set(pageId, connection); + + WebInspectorProxy* client = m_clientMap.get(pageId); + client->remoteFrontendConnected(); +} + +void WebInspectorServer::didReceiveWebSocketMessage(WebSocketServerConnection* connection, const String& message) +{ + // Dispatch incoming remote message locally. + unsigned pageId = connection->identifier(); + ASSERT(pageId); + WebInspectorProxy* client = m_clientMap.get(pageId); + client->dispatchMessageFromRemoteFrontend(message); +} + +void WebInspectorServer::didCloseWebSocketConnection(WebSocketServerConnection* connection) +{ + // Connection has already shut down. + unsigned pageId = connection->identifier(); + if (!pageId) + return; + + // The socket closing means the remote side has caused the close. + WebInspectorProxy* client = m_clientMap.get(pageId); + closeConnection(client, connection); +} + +void WebInspectorServer::closeConnection(WebInspectorProxy* client, WebSocketServerConnection* connection) +{ + // Local side cleanup. + if (client) + client->remoteFrontendDisconnected(); + + // Remote side cleanup. + m_connectionMap.remove(connection->identifier()); + connection->setIdentifier(0); + connection->shutdownNow(); +} + +} + +#endif // ENABLE(INSPECTOR_SERVER) diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.h b/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.h new file mode 100644 index 000000000..f0bbc213c --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebInspectorServer.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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 WebInspectorServer_h +#define WebInspectorServer_h + +#if ENABLE(INSPECTOR_SERVER) + +#include "WebSocketServer.h" +#include "WebSocketServerClient.h" +#include <wtf/HashMap.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +class WebInspectorProxy; + +class WebInspectorServer : public WebSocketServer, public WebSocketServerClient { +public: + typedef HashMap<unsigned, WebInspectorProxy*> ClientMap; + static WebInspectorServer& shared(); + + // Page registry to manage known pages. + int registerPage(WebInspectorProxy* client); + void unregisterPage(int pageId); + void sendMessageOverConnection(unsigned pageIdForConnection, const String& message); + +private: + WebInspectorServer(); + ~WebInspectorServer(); + + // WebSocketServerClient implementation. Events coming from remote connections. + virtual void didReceiveUnrecognizedHTTPRequest(WebSocketServerConnection*, PassRefPtr<WebCore::HTTPRequest>); + virtual bool didReceiveWebSocketUpgradeHTTPRequest(WebSocketServerConnection*, PassRefPtr<WebCore::HTTPRequest>); + virtual void didEstablishWebSocketConnection(WebSocketServerConnection*, PassRefPtr<WebCore::HTTPRequest>); + virtual void didReceiveWebSocketMessage(WebSocketServerConnection*, const String& message); + virtual void didCloseWebSocketConnection(WebSocketServerConnection*); + + bool platformResourceForPath(const String& path, Vector<char>& data, String& contentType); +#if PLATFORM(QT) + void buildPageList(Vector<char>& data, String& contentType); +#endif + + void closeConnection(WebInspectorProxy*, WebSocketServerConnection*); + + unsigned m_nextAvailablePageId; + ClientMap m_clientMap; + HashMap<unsigned, WebSocketServerConnection*> m_connectionMap; +}; + +} + +#endif // ENABLE(INSPECTOR_SERVER) + +#endif // WebInspectorServer_h diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServer.cpp b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServer.cpp new file mode 100644 index 000000000..1ccdbc8e6 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServer.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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. + */ + +#include "config.h" + +#if ENABLE(INSPECTOR_SERVER) + +#include "WebSocketServer.h" + +#include "WebSocketServerConnection.h" +#include <WebCore/SocketStreamHandle.h> +#include <wtf/PassOwnPtr.h> + +#if PLATFORM(QT) +#include "WebSocketServerQt.h" +#endif + +using namespace WebCore; + +namespace WebKit { + +WebSocketServer::WebSocketServer(WebSocketServerClient* client) + : m_state(Closed) + , m_client(client) +{ + platformInitialize(); +} + +WebSocketServer::~WebSocketServer() +{ + close(); +} + +bool WebSocketServer::listen(const String& bindAddress, unsigned short port) +{ + ASSERT(port); + + if (m_state == Listening) + return false; + + bool isNowListening = platformListen(bindAddress, port); + m_state = isNowListening ? Listening : Closed; + return isNowListening; +} + +void WebSocketServer::close() +{ + if (m_state == Closed) + return; + + platformClose(); +} + +void WebSocketServer::didAcceptConnection(PassRefPtr<SocketStreamHandle> socketHandle) +{ + m_connections.append(adoptPtr(new WebSocketServerConnection(socketHandle, m_client, this))); +} + +void WebSocketServer::didCloseWebSocketServerConnection(WebSocketServerConnection* connection) +{ + Deque<OwnPtr<WebSocketServerConnection> >::iterator end = m_connections.end(); + for (Deque<OwnPtr<WebSocketServerConnection> >::iterator it = m_connections.begin(); it != end; ++it) { + if (it->get() == connection) { + m_connections.remove(it); + return; + } + } + ASSERT_NOT_REACHED(); +} + +} + +#endif // ENABLE(INSPECTOR_SERVER) diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServer.h b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServer.h new file mode 100644 index 000000000..d60820e43 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServer.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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 WebSocketServer_h +#define WebSocketServer_h + +#if ENABLE(INSPECTOR_SERVER) + +#include <wtf/Deque.h> +#include <wtf/OwnPtr.h> +#include <wtf/text/WTFString.h> + +#if PLATFORM(QT) +namespace WebKit { +class QtTcpServerHandler; +} +#endif + +namespace WebCore { +class SocketStreamHandle; +} + +namespace WebKit { + +class WebSocketServerClient; +class WebSocketServerConnection; + +class WebSocketServer { +public: + enum ServerState { Closed, Listening }; + WebSocketServer(WebSocketServerClient*); + virtual ~WebSocketServer(); + + // Server operations. + bool listen(const String& bindAddress, unsigned short port); + void close(); + + void didAcceptConnection(PassRefPtr<WebCore::SocketStreamHandle>); + +private: + void didCloseWebSocketServerConnection(WebSocketServerConnection*); + + void platformInitialize(); + bool platformListen(const String& bindAddress, unsigned short port); + void platformClose(); + + ServerState m_state; + Deque<OwnPtr<WebSocketServerConnection> > m_connections; + WebSocketServerClient* m_client; +#if PLATFORM(QT) + OwnPtr<QtTcpServerHandler> m_tcpServerHandler; +#endif + friend class WebSocketServerConnection; +}; + +} + +#endif // ENABLE(INSPECTOR_SERVER) + +#endif // WebSocketServer_h diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h new file mode 100644 index 000000000..e7be3abb7 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerClient.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * + * 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. ``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 + * 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 WebSocketServerClient_h +#define WebSocketServerClient_h + +#if ENABLE(INSPECTOR_SERVER) + +#include <wtf/PassRefPtr.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { +class HTTPRequest; +} + +namespace WebKit { + +class WebSocketServerConnection; + +class WebSocketServerClient { +public: + virtual ~WebSocketServerClient() { } + + // Received an HTTP request but didn't know what to do with it. + virtual void didReceiveUnrecognizedHTTPRequest(WebSocketServerConnection*, PassRefPtr<WebCore::HTTPRequest>) { } + + // Received a WebSocket Upgrade HTTP request. Ask if we should handle it and upgrade. + virtual bool didReceiveWebSocketUpgradeHTTPRequest(WebSocketServerConnection*, PassRefPtr<WebCore::HTTPRequest>) { return true; } + + // Established a WebSocket Connection. + virtual void didEstablishWebSocketConnection(WebSocketServerConnection*, PassRefPtr<WebCore::HTTPRequest>) { } + + // Received a WebSocket message. + virtual void didReceiveWebSocketMessage(WebSocketServerConnection*, const String&) { } + + // WebSocket Connection closed. + virtual void didCloseWebSocketConnection(WebSocketServerConnection*) { } +}; + +} + +#endif // ENABLE(INSPECTOR_SERVER) + +#endif // WebSocketServerClient_h diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerConnection.cpp b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerConnection.cpp new file mode 100644 index 000000000..9ffbbbe36 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerConnection.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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. + */ + +#include "config.h" + +#if ENABLE(INSPECTOR_SERVER) + +#include "WebSocketServerConnection.h" + +#include "WebSocketServer.h" +#include "WebSocketServerClient.h" +#include <WebCore/HTTPRequest.h> +#include <WebCore/NotImplemented.h> +#include <WebCore/SocketStreamError.h> +#include <WebCore/SocketStreamHandle.h> +#include <WebCore/WebSocketChannel.h> +#include <WebCore/WebSocketHandshake.h> +#include <wtf/text/CString.h> +#include <wtf/text/StringBuilder.h> + +using namespace WebCore; + +namespace WebKit { + +WebSocketServerConnection::WebSocketServerConnection(PassRefPtr<SocketStreamHandle> socket, WebSocketServerClient* client, WebSocketServer* server) + : m_identifier(0) + , m_mode(HTTP) + , m_socket(socket) + , m_server(server) + , m_client(client) +{ + m_socket->setClient(this); +} + +WebSocketServerConnection::~WebSocketServerConnection() +{ + shutdownNow(); +} + +void WebSocketServerConnection::shutdownNow() +{ + if (!m_socket) + return; + RefPtr<SocketStreamHandle> socket = m_socket.release(); + socket->close(); +} + +void WebSocketServerConnection::shutdownAfterSendOrNow() +{ + // If this ASSERT happens on any platform then their SocketStreamHandle::send + // followed by a SocketStreamHandle::close is not guarenteed to have sent all + // data. If this happens, we need to slightly change the design to include a + // SocketStreamHandleClient::didSend, handle it here, and add an m_shutdownAfterSend + // state on this WebSocketServerConnection. + ASSERT(!m_socket->bufferedAmount()); + + shutdownNow(); +} + +void WebSocketServerConnection::sendWebSocketMessage(const String& message) +{ + CString payload = message.utf8(); + const bool final = true, compress = false, masked = false; + WebSocketFrame frame(WebSocketFrame::OpCodeText, final, compress, masked, payload.data(), payload.length()); + + Vector<char> frameData; + frame.makeFrameData(frameData); + + m_socket->send(frameData.data(), frameData.size()); +} + +void WebSocketServerConnection::sendHTTPResponseHeader(int statusCode, const String& statusText, const HTTPHeaderMap& headerFields) +{ + StringBuilder builder; + builder.append("HTTP/1.1 "); + builder.append(String::number(statusCode)); + builder.append(" "); + builder.append(statusText); + builder.append("\r\n"); + HTTPHeaderMap::const_iterator end = headerFields.end(); + for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) { + builder.append(it->first); + builder.append(": "); + builder.append(it->second + "\r\n"); + } + builder.append("\r\n"); + + CString header = builder.toString().latin1(); + m_socket->send(header.data(), header.length()); +} + +void WebSocketServerConnection::sendRawData(const char* data, size_t length) +{ + m_socket->send(data, length); +} + +void WebSocketServerConnection::didCloseSocketStream(SocketStreamHandle*) +{ + // Web Socket Mode. + if (m_mode == WebSocket) + m_client->didCloseWebSocketConnection(this); + + // Tell the server to get rid of this. + m_server->didCloseWebSocketServerConnection(this); +} + +void WebSocketServerConnection::didReceiveSocketStreamData(SocketStreamHandle*, const char* data, int length) +{ + // Each didReceiveData call adds more data to our buffer. + // We clear the buffer when we have handled data from it. + m_bufferedData.append(data, length); + + switch (m_mode) { + case HTTP: + readHTTPMessage(); + break; + case WebSocket: + readWebSocketFrames(); + break; + default: + // For any new modes added in the future. + ASSERT_NOT_REACHED(); + } +} + +void WebSocketServerConnection::didFailSocketStream(SocketStreamHandle*, const SocketStreamError&) +{ + // Possible read or write error. +} + +void WebSocketServerConnection::readHTTPMessage() +{ + String failureReason; + RefPtr<HTTPRequest> request = HTTPRequest::parseHTTPRequestFromBuffer(m_bufferedData.data(), m_bufferedData.size(), failureReason); + if (!request) + return; + + // Assume all the input has been read if we are reading an HTTP Request. + m_bufferedData.clear(); + + // If this is a WebSocket request, perform the WebSocket Handshake. + const HTTPHeaderMap& headers = request->headerFields(); + String upgradeHeaderValue = headers.get("Upgrade"); + if (upgradeHeaderValue == "websocket") { + upgradeToWebSocketServerConnection(request); + return; + } + if (upgradeHeaderValue == "WebSocket") { + LOG_ERROR("WebSocket protocol version < Hybi-10 not supported. Upgrade your client."); + return; + } + + // Otherwise, this is an HTTP Request we don't know how to deal with. + m_client->didReceiveUnrecognizedHTTPRequest(this, request); +} + +void WebSocketServerConnection::upgradeToWebSocketServerConnection(PassRefPtr<HTTPRequest> request) +{ + ASSERT(request); + ASSERT(m_mode == HTTP); + m_mode = WebSocket; + RefPtr<HTTPRequest> protectedRequest(request); + + // Ask the client if we should upgrade for this or not. + if (!m_client->didReceiveWebSocketUpgradeHTTPRequest(this, protectedRequest)) { + shutdownNow(); + return; + } + + // Build and send the WebSocket handshake response. + const HTTPHeaderMap& requestHeaders = protectedRequest->headerFields(); + String accept = WebSocketHandshake::getExpectedWebSocketAccept(requestHeaders.get("Sec-WebSocket-Key")); + HTTPHeaderMap responseHeaders; + responseHeaders.add("Upgrade", requestHeaders.get("Upgrade")); + responseHeaders.add("Connection", requestHeaders.get("Connection")); + responseHeaders.add("Sec-WebSocket-Accept", accept); + + sendHTTPResponseHeader(101, "WebSocket Protocol Handshake", responseHeaders); + + m_client->didEstablishWebSocketConnection(this, protectedRequest); +} + +void WebSocketServerConnection::readWebSocketFrames() +{ + while (true) { + bool didReadOneFrame = readWebSocketFrame(); + if (!didReadOneFrame) + break; + if (m_bufferedData.isEmpty()) + break; + } +} + +bool WebSocketServerConnection::readWebSocketFrame() +{ + WebSocketFrame frame; + const char* frameEnd; + String errorString; + WebSocketFrame::ParseFrameResult result = WebSocketFrame::parseFrame(m_bufferedData.data(), m_bufferedData.size(), frame, frameEnd, errorString); + + // Incomplete frame. Wait to receive more data. + if (result == WebSocketFrame::FrameIncomplete) + return false; + + if (result == WebSocketFrame::FrameError) { + shutdownNow(); + } else if (frame.opCode == WebSocketFrame::OpCodeText) { + // Delegate Text frames to our client. + String msg = String::fromUTF8(frame.payload, frame.payloadLength); + m_client->didReceiveWebSocketMessage(this, msg); + } else + notImplemented(); + + // Remove the frame from our buffer. + m_bufferedData.remove(0, frameEnd - m_bufferedData.data()); + + return true; +} + +} + +#endif // ENABLE(INSPECTOR_SERVER) diff --git a/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerConnection.h b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerConnection.h new file mode 100644 index 000000000..6cc770137 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/WebSocketServerConnection.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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 WebSocketServerConnection_h +#define WebSocketServerConnection_h + +#if ENABLE(INSPECTOR_SERVER) + +#include <WebCore/SocketStreamHandleClient.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { +class HTTPHeaderMap; +class HTTPRequest; +class SocketStreamHandle; +} + +namespace WebKit { + +class WebSocketServer; +class WebSocketServerClient; + +class WebSocketServerConnection : public WebCore::SocketStreamHandleClient { +public: + enum WebSocketServerMode { HTTP, WebSocket }; + WebSocketServerConnection(PassRefPtr<WebCore::SocketStreamHandle>, WebSocketServerClient*, WebSocketServer*); + virtual ~WebSocketServerConnection(); + + unsigned identifier() const { return m_identifier; } + void setIdentifier(unsigned id) { m_identifier = id; } + + // Sending data over the connection. + void sendWebSocketMessage(const String& message); + void sendHTTPResponseHeader(int statusCode, const String& statusText, const WebCore::HTTPHeaderMap& headerFields); + void sendRawData(const char* data, size_t length); + + // Terminating the connection. + void shutdownNow(); + void shutdownAfterSendOrNow(); + + // SocketStreamHandleClient implementation. + virtual void didCloseSocketStream(WebCore::SocketStreamHandle*); + virtual void didReceiveSocketStreamData(WebCore::SocketStreamHandle*, const char* data, int length); + virtual void didFailSocketStream(WebCore::SocketStreamHandle*, const WebCore::SocketStreamError&); + +private: + // HTTP Mode. + void readHTTPMessage(); + + // WebSocket Mode. + void upgradeToWebSocketServerConnection(PassRefPtr<WebCore::HTTPRequest>); + void readWebSocketFrames(); + bool readWebSocketFrame(); + +protected: + unsigned m_identifier; + Vector<char> m_bufferedData; + WebSocketServerMode m_mode; + RefPtr<WebCore::SocketStreamHandle> m_socket; + WebSocketServer* m_server; + WebSocketServerClient* m_client; +}; + +} + +#endif // ENABLE(INSPECTOR_SERVER) + +#endif // WebSocketServerConnection_h diff --git a/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp b/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp new file mode 100644 index 000000000..9f84a656b --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/qt/WebInspectorServerQt.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 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 "config.h" + +#include "WebInspectorServer.h" + +#include "WebInspectorProxy.h" +#include "WebPageProxy.h" +#include <WebCore/MIMETypeRegistry.h> +#include <wtf/text/CString.h> +#include <wtf/text/StringBuilder.h> + +namespace WebKit { + +bool WebInspectorServer::platformResourceForPath(const String& path, Vector<char>& data, String& contentType) +{ + // The page list contains an unformated list of pages that can be inspected with a link to open a session. + if (path == "/pagelist.json") { + buildPageList(data, contentType); + return true; + } + + // Point the default path to a formatted page that queries the page list and display them. + String localPath = (path == "/") ? "/webkit/resources/inspectorPageIndex.html" : path; + // All other paths are mapped directly to a resource, if possible. + QFile file(QString::fromLatin1(":%1").arg(localPath)); + if (file.exists()) { + file.open(QIODevice::ReadOnly); + data.grow(file.size()); + file.read(data.data(), data.size()); + + size_t extStart = localPath.reverseFind('.'); + String ext = localPath.substring(extStart != notFound ? extStart + 1 : 0); + contentType = WebCore::MIMETypeRegistry::getMIMETypeForExtension(ext); + return true; + } + return false; +} + +void WebInspectorServer::buildPageList(Vector<char>& data, String& contentType) +{ + StringBuilder builder; + builder.append("[ "); + ClientMap::iterator end = m_clientMap.end(); + for (ClientMap::iterator it = m_clientMap.begin(); it != end; ++it) { + WebPageProxy* webPage = it->second->page(); + if (it != m_clientMap.begin()) + builder.append(", "); + builder.append("{ \"id\": " + String::number(it->first)); + builder.append(", \"title\": \""); + builder.append(webPage->pageTitle()); + builder.append("\", \"url\": \""); + builder.append(webPage->activeURL()); + builder.append("\", \"inspectorUrl\": \""); + builder.append("/webkit/inspector/inspector.html?page=" + String::number(it->first)); + builder.append("\" }"); + } + builder.append(" ]"); + CString cstr = builder.toString().utf8(); + data.append(cstr.data(), cstr.length()); + contentType = "application/json; charset=utf-8"; +} + +} diff --git a/Source/WebKit2/UIProcess/InspectorServer/qt/WebSocketServerQt.cpp b/Source/WebKit2/UIProcess/InspectorServer/qt/WebSocketServerQt.cpp new file mode 100644 index 000000000..6a9c5b393 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/qt/WebSocketServerQt.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 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 "config.h" +#include "WebSocketServerQt.h" + +#include "WebSocketServer.h" +#include <WebCore/SocketStreamHandle.h> +#include <wtf/PassOwnPtr.h> + +using namespace WebCore; + +namespace WebKit { + +void WebSocketServer::platformInitialize() +{ + m_tcpServerHandler = adoptPtr(new QtTcpServerHandler(this)); +} + +bool WebSocketServer::platformListen(const String& bindAddress, unsigned short port) +{ + return m_tcpServerHandler->listen(bindAddress, port); +} + +void WebSocketServer::platformClose() +{ + m_tcpServerHandler->close(); +} + +QtTcpServerHandler::QtTcpServerHandler(WebSocketServer* webSocketServer) +: m_webSocketServer(webSocketServer) +{ + connect(&m_serverSocket, SIGNAL(newConnection()), SLOT(handleNewConnection())); +} + +void QtTcpServerHandler::handleNewConnection() +{ + QTcpSocket* socket = m_serverSocket.nextPendingConnection(); + ASSERT(socket); + m_webSocketServer->didAcceptConnection(SocketStreamHandle::create(socket, 0)); +} + +bool QtTcpServerHandler::listen(const String& bindAddress, unsigned short port) +{ + ASSERT(!bindAddress.isEmpty()); + ASSERT(port); + bool success = m_serverSocket.listen(QHostAddress(bindAddress), port); + if (!success) + LOG_ERROR("Can't open server socket on %s:%d [%s]", qPrintable(bindAddress), port, qPrintable(m_serverSocket.errorString())); + return success; +} + +void QtTcpServerHandler::close() +{ + m_serverSocket.close(); +} + +} + +#include "moc_WebSocketServerQt.cpp" diff --git a/Source/WebKit2/UIProcess/InspectorServer/qt/WebSocketServerQt.h b/Source/WebKit2/UIProcess/InspectorServer/qt/WebSocketServerQt.h new file mode 100644 index 000000000..d565977d9 --- /dev/null +++ b/Source/WebKit2/UIProcess/InspectorServer/qt/WebSocketServerQt.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. ``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 + * 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 WebSocketServerQt_h +#define WebSocketServerQt_h + +#include <QTcpServer> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +class WebSocketServer; + +class QtTcpServerHandler : public QObject { + Q_OBJECT +public: + QtTcpServerHandler(WebSocketServer*); + bool listen(const String& bindAddress, unsigned short port); + void close(); + +private slots: + void handleNewConnection(); + +private: + QTcpServer m_serverSocket; + WebSocketServer* m_webSocketServer; +}; + +} + +#endif // WebSocketServerQt_h diff --git a/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h index 09c5589f3..bc1f867f3 100644 --- a/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h +++ b/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h @@ -68,7 +68,6 @@ public: void invalidate(); static bool getProcessTypeFromString(const char*, ProcessType&); - private: ProcessLauncher(Client*, const LaunchOptions& launchOptions); diff --git a/Source/WebKit2/UIProcess/Launcher/efl/ProcessLauncherEfl.cpp b/Source/WebKit2/UIProcess/Launcher/efl/ProcessLauncherEfl.cpp new file mode 100644 index 000000000..14111a2d7 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/efl/ProcessLauncherEfl.cpp @@ -0,0 +1,97 @@ +/* + 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. + */ + +#include "config.h" +#include "ProcessLauncher.h" + +#include "Connection.h" +#include <WebCore/FileSystem.h> +#include <WebCore/ResourceHandle.h> +#include <WebCore/RunLoop.h> +#include <libgen.h> +#include <unistd.h> +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +using namespace WebCore; + +namespace WebKit { + +void ProcessLauncher::launchProcess() +{ + int sockets[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { + ASSERT_NOT_REACHED(); + return; + } + + pid_t pid = fork(); + if (!pid) { // child process + close(sockets[1]); + String socket = String::format("%d", sockets[0]); + String processName; + switch (m_launchOptions.processType) { + case WebProcess: + processName = "WebProcess"; + break; + case PluginProcess: + processName = "PluginProcess"; + break; + default: + ASSERT_NOT_REACHED(); + return; + } + + String executablePath; + char readLinkBuffer[PATH_MAX]; + memset(readLinkBuffer, 0, PATH_MAX); + ssize_t result = readlink("/proc/self/exe", readLinkBuffer, PATH_MAX); + + if (result == -1) + executablePath = String("/usr/bin"); + else { + char* executablePathPtr = dirname(readLinkBuffer); + executablePath = String(executablePathPtr); + } + String fullPath = executablePath + "/" + processName; + execl(fullPath.utf8().data(), processName.utf8().data(), socket.utf8().data(), static_cast<char*>(0)); + } else if (pid > 0) { // parent process; + close(sockets[0]); + m_processIdentifier = pid; + // We've finished launching the process, message back to the main run loop. + RunLoop::main()->dispatch(bind(&ProcessLauncher::didFinishLaunchingProcess, this, pid, sockets[1])); + } else { + ASSERT_NOT_REACHED(); + return; + } + +} + +void ProcessLauncher::terminateProcess() +{ + if (!m_processIdentifier) + return; + kill(m_processIdentifier, SIGKILL); +} + +void ProcessLauncher::platformInvalidate() +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/efl/ThreadLauncherEfl.cpp b/Source/WebKit2/UIProcess/Launcher/efl/ThreadLauncherEfl.cpp new file mode 100644 index 000000000..47e1fd685 --- /dev/null +++ b/Source/WebKit2/UIProcess/Launcher/efl/ThreadLauncherEfl.cpp @@ -0,0 +1,33 @@ +/* + 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. +*/ + +#include "config.h" +#include "ThreadLauncher.h" + +#include <WebCore/NotImplemented.h> + +namespace WebKit { + +CoreIPC::Connection::Identifier ThreadLauncher::createWebThread() +{ + notImplemented(); + return -1; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp index 94cad5fc4..8fb619ecd 100644 --- a/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp +++ b/Source/WebKit2/UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp @@ -28,6 +28,7 @@ #include "ProcessLauncher.h" #include "Connection.h" +#include "ProcessExecutablePath.h" #include <WebCore/FileSystem.h> #include <WebCore/ResourceHandle.h> #include <WebCore/RunLoop.h> @@ -52,9 +53,6 @@ using namespace WebCore; namespace WebKit { -const char* gWebKitWebProcessName = "WebKitWebProcess"; -const char* gWebKitPluginProcessName = "WebKitPluginProcess"; - static void childSetupFunction(gpointer userData) { int socket = GPOINTER_TO_INT(userData); @@ -77,34 +75,6 @@ static void childFinishedFunction(GPid, gint status, gpointer userData) close(GPOINTER_TO_INT(userData)); } -static CString findWebKitProcess(const char* processName) -{ - const char* execDirectory = g_getenv("WEBKIT_EXEC_PATH"); - if (execDirectory) { - String processPath = pathByAppendingComponent(filenameToString(execDirectory), processName); - if (fileExists(processPath)) - return fileSystemRepresentation(processPath); - } - - static bool gotExecutablePath = false; - static String executablePath; - if (!gotExecutablePath) { - gotExecutablePath = true; - - CString executableFile = getCurrentExecutablePath(); - if (!executableFile.isNull()) - executablePath = directoryName(filenameToString(executableFile.data())); - } - - if (!executablePath.isNull()) { - String processPath = pathByAppendingComponent(executablePath, processName); - if (fileExists(processPath)) - return fileSystemRepresentation(processPath); - } - - return fileSystemRepresentation(pathByAppendingComponent(filenameToString(LIBEXECDIR), processName)); -} - void ProcessLauncher::launchProcess() { GPid pid = 0; @@ -116,7 +86,9 @@ void ProcessLauncher::launchProcess() return; } - CString binaryPath = findWebKitProcess(m_launchOptions.processType == ProcessLauncher::WebProcess ? gWebKitWebProcessName : gWebKitPluginProcessName); + String executablePath = m_launchOptions.processType == WebProcess ? + executablePathOfWebProcess() : executablePathOfPluginProcess(); + CString binaryPath = fileSystemRepresentation(executablePath); GOwnPtr<gchar> socket(g_strdup_printf("%d", sockets[0])); char* argv[3]; argv[0] = const_cast<char*>(binaryPath.data()); diff --git a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp index 8e8262063..c5c3f7145 100644 --- a/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp +++ b/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp @@ -28,10 +28,9 @@ #include "ProcessLauncher.h" #include "Connection.h" +#include "ProcessExecutablePath.h" #include "WebProcess.h" -#include <QCoreApplication> #include <QDebug> -#include <QFile> #include <QLocalServer> #include <QMetaType> #include <QProcess> @@ -102,13 +101,9 @@ void QtWebProcess::setupChildProcess() void ProcessLauncher::launchProcess() { - QString applicationPath = QLatin1String("%1 %2"); - - if (QFile::exists(QCoreApplication::applicationDirPath() + QLatin1String("/QtWebProcess"))) { - applicationPath = applicationPath.arg(QCoreApplication::applicationDirPath() + QLatin1String("/QtWebProcess")); - } else { - applicationPath = applicationPath.arg(QLatin1String("QtWebProcess")); - } + QString commandLine = QLatin1String("%1 %2"); + commandLine = commandLine.arg(m_launchOptions.processType == WebProcess ? + executablePathOfWebProcess() : executablePathOfPluginProcess()); #if OS(DARWIN) // Create the listening port. @@ -124,7 +119,7 @@ void ProcessLauncher::launchProcess() kern_return_t kr = bootstrap_register2(bootstrap_port, const_cast<char*>(serviceName.toUtf8().data()), connector, 0); ASSERT_UNUSED(kr, kr == KERN_SUCCESS); - QString program(applicationPath.arg(serviceName)); + commandLine = commandLine.arg(serviceName); #else int sockets[2]; if (socketpair(AF_UNIX, SOCKET_TYPE, 0, sockets) == -1) { @@ -144,12 +139,12 @@ void ProcessLauncher::launchProcess() } int connector = sockets[1]; - QString program(applicationPath.arg(sockets[0])); + commandLine = commandLine.arg(sockets[0]); #endif QProcess* webProcess = new QtWebProcess(); webProcess->setProcessChannelMode(QProcess::ForwardedChannels); - webProcess->start(program); + webProcess->start(commandLine); #if !OS(DARWIN) // Don't expose the web socket to possible future web processes @@ -163,7 +158,7 @@ void ProcessLauncher::launchProcess() #endif if (!webProcess->waitForStarted()) { - qDebug() << "Failed to start" << program; + qDebug() << "Failed to start" << commandLine; ASSERT_NOT_REACHED(); #if OS(DARWIN) mach_port_deallocate(mach_task_self(), connector); diff --git a/Source/WebKit2/UIProcess/LayerTreeHostProxy.cpp b/Source/WebKit2/UIProcess/LayerTreeHostProxy.cpp index e760a7dae..03a5eacad 100644 --- a/Source/WebKit2/UIProcess/LayerTreeHostProxy.cpp +++ b/Source/WebKit2/UIProcess/LayerTreeHostProxy.cpp @@ -45,17 +45,6 @@ LayerTreeHostProxy::~LayerTreeHostProxy() m_renderer->detach(); } -void LayerTreeHostProxy::paintToCurrentGLContext(const WebCore::TransformationMatrix& matrix, float opacity, const WebCore::FloatRect& rect) -{ - m_renderer->syncRemoteContent(); - m_renderer->paintToCurrentGLContext(matrix, opacity, rect); -} - -void LayerTreeHostProxy::paintToGraphicsContext(BackingStore::PlatformGraphicsContext context) -{ - m_renderer->paintToGraphicsContext(context); -} - void LayerTreeHostProxy::updateViewport() { m_drawingAreaProxy->updateViewport(); @@ -64,22 +53,29 @@ void LayerTreeHostProxy::updateViewport() void LayerTreeHostProxy::dispatchUpdate(const Function<void()>& function) { m_renderer->appendUpdate(function); - updateViewport(); } -void LayerTreeHostProxy::createTileForLayer(int layerID, int tileID, const WebKit::UpdateInfo& updateInfo) +void LayerTreeHostProxy::createTileForLayer(int layerID, int tileID, const IntRect& targetRect, const WebKit::SurfaceUpdateInfo& updateInfo) { - dispatchUpdate(bind(&WebLayerTreeRenderer::createTile, m_renderer.get(), layerID, tileID, updateInfo.updateScaleFactor)); - updateTileForLayer(layerID, tileID, updateInfo); + dispatchUpdate(bind(&WebLayerTreeRenderer::createTile, m_renderer.get(), layerID, tileID, updateInfo.scaleFactor)); + updateTileForLayer(layerID, tileID, targetRect, updateInfo); } -void LayerTreeHostProxy::updateTileForLayer(int layerID, int tileID, const WebKit::UpdateInfo& updateInfo) +void LayerTreeHostProxy::updateTileForLayer(int layerID, int tileID, const IntRect& targetRect, const WebKit::SurfaceUpdateInfo& updateInfo) { - ASSERT(updateInfo.updateRects.size() == 1); - IntRect sourceRect = updateInfo.updateRects.first(); - IntRect targetRect = updateInfo.updateRectBounds; - RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(updateInfo.bitmapHandle); - dispatchUpdate(bind(&WebLayerTreeRenderer::updateTile, m_renderer.get(), layerID, tileID, sourceRect, targetRect, bitmap)); + RefPtr<ShareableSurface> surface; +#if USE(GRAPHICS_SURFACE) + uint32_t token = updateInfo.surfaceHandle.graphicsSurfaceToken(); + HashMap<uint32_t, RefPtr<ShareableSurface> >::iterator it = m_surfaces.find(token); + if (it == m_surfaces.end()) { + surface = ShareableSurface::create(updateInfo.surfaceHandle); + m_surfaces.add(token, surface); + } else + surface = it->second; +#else + surface = ShareableSurface::create(updateInfo.surfaceHandle); +#endif + dispatchUpdate(bind(&WebLayerTreeRenderer::updateTile, m_renderer.get(), layerID, tileID, WebLayerTreeRenderer::TileUpdate(updateInfo.updateRect, targetRect, surface, updateInfo.surfaceOffset))); } void LayerTreeHostProxy::removeTileForLayer(int layerID, int tileID) @@ -90,21 +86,36 @@ void LayerTreeHostProxy::removeTileForLayer(int layerID, int tileID) void LayerTreeHostProxy::deleteCompositingLayer(WebLayerID id) { dispatchUpdate(bind(&WebLayerTreeRenderer::deleteLayer, m_renderer.get(), id)); + updateViewport(); } void LayerTreeHostProxy::setRootCompositingLayer(WebLayerID id) { dispatchUpdate(bind(&WebLayerTreeRenderer::setRootLayerID, m_renderer.get(), id)); + updateViewport(); } -void LayerTreeHostProxy::syncCompositingLayerState(const WebLayerInfo& info) +void LayerTreeHostProxy::setCompositingLayerState(WebLayerID id, const WebLayerInfo& info) { - dispatchUpdate(bind(&WebLayerTreeRenderer::syncLayerParameters, m_renderer.get(), info)); + dispatchUpdate(bind(&WebLayerTreeRenderer::setLayerState, m_renderer.get(), id, info)); } +void LayerTreeHostProxy::setCompositingLayerChildren(WebLayerID id, const Vector<WebLayerID>& children) +{ + dispatchUpdate(bind(&WebLayerTreeRenderer::setLayerChildren, m_renderer.get(), id, children)); +} + +#if ENABLE(CSS_FILTERS) +void LayerTreeHostProxy::setCompositingLayerFilters(WebLayerID id, const FilterOperations& filters) +{ + dispatchUpdate(bind(&WebLayerTreeRenderer::setLayerFilters, m_renderer.get(), id, filters)); +} +#endif + void LayerTreeHostProxy::didRenderFrame() { dispatchUpdate(bind(&WebLayerTreeRenderer::flushLayerChanges, m_renderer.get())); + updateViewport(); } void LayerTreeHostProxy::createDirectlyCompositedImage(int64_t key, const WebKit::ShareableBitmap::Handle& handle) @@ -118,15 +129,15 @@ void LayerTreeHostProxy::destroyDirectlyCompositedImage(int64_t key) dispatchUpdate(bind(&WebLayerTreeRenderer::destroyImage, m_renderer.get(), key)); } -void LayerTreeHostProxy::setVisibleContentsRectForPanning(const IntRect& rect, const FloatPoint& trajectoryVector) +void LayerTreeHostProxy::setContentsSize(const FloatSize& contentsSize) { - m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::SetVisibleContentsRectForPanning(rect, trajectoryVector), m_drawingAreaProxy->page()->pageID()); + m_renderer->setContentsSize(contentsSize); } -void LayerTreeHostProxy::setVisibleContentsRectForScaling(const IntRect& rect, float scale) +void LayerTreeHostProxy::setVisibleContentsRect(const IntRect& rect, float scale, const FloatPoint& trajectoryVector, const WebCore::FloatPoint& accurateVisibleContentsPosition) { - m_renderer->setVisibleContentsRectForScaling(rect, scale); - m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::SetVisibleContentsRectForScaling(rect, scale), m_drawingAreaProxy->page()->pageID()); + dispatchUpdate(bind(&WebLayerTreeRenderer::setVisibleContentsRect, m_renderer.get(), rect, scale, accurateVisibleContentsPosition)); + m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::SetVisibleContentsRect(rect, scale, trajectoryVector), m_drawingAreaProxy->page()->pageID()); } void LayerTreeHostProxy::renderNextFrame() @@ -134,8 +145,14 @@ void LayerTreeHostProxy::renderNextFrame() m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::RenderNextFrame(), m_drawingAreaProxy->page()->pageID()); } +void LayerTreeHostProxy::didChangeScrollPosition(const IntPoint& position) +{ + dispatchUpdate(bind(&WebLayerTreeRenderer::didChangeScrollPosition, m_renderer.get(), position)); +} + void LayerTreeHostProxy::purgeBackingStores() { + m_renderer->setActive(false); m_drawingAreaProxy->page()->process()->send(Messages::LayerTreeHost::PurgeBackingStores(), m_drawingAreaProxy->page()->pageID()); } diff --git a/Source/WebKit2/UIProcess/LayerTreeHostProxy.h b/Source/WebKit2/UIProcess/LayerTreeHostProxy.h index f6c31d1bc..ac3d3d2b3 100644 --- a/Source/WebKit2/UIProcess/LayerTreeHostProxy.h +++ b/Source/WebKit2/UIProcess/LayerTreeHostProxy.h @@ -25,6 +25,7 @@ #include "BackingStore.h" #include "DrawingAreaProxy.h" #include "Region.h" +#include "SurfaceUpdateInfo.h" #include "WebLayerTreeInfo.h" #include <WebCore/GraphicsContext.h> #include <WebCore/GraphicsLayer.h> @@ -47,24 +48,27 @@ class LayerTreeHostProxy { public: LayerTreeHostProxy(DrawingAreaProxy*); virtual ~LayerTreeHostProxy(); - void syncCompositingLayerState(const WebLayerInfo&); + void setCompositingLayerState(WebLayerID, const WebLayerInfo&); + void setCompositingLayerChildren(WebLayerID, const Vector<WebLayerID>&); +#if ENABLE(CSS_FILTERS) + void setCompositingLayerFilters(WebLayerID, const WebCore::FilterOperations&); +#endif void deleteCompositingLayer(WebLayerID); void setRootCompositingLayer(WebLayerID); void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); - void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float opacity, const WebCore::FloatRect& clip); - void paintToGraphicsContext(BackingStore::PlatformGraphicsContext); void purgeGLResources(); - void setVisibleContentsRectForScaling(const WebCore::IntRect&, float); - void setVisibleContentsRectForPanning(const WebCore::IntRect&, const WebCore::FloatPoint&); + void setContentsSize(const WebCore::FloatSize&); + void setVisibleContentsRect(const WebCore::IntRect&, float scale, const WebCore::FloatPoint& trajectory, const WebCore::FloatPoint& accurateVisibleContentsPosition); void didRenderFrame(); - void createTileForLayer(int layerID, int tileID, const WebKit::UpdateInfo&); - void updateTileForLayer(int layerID, int tileID, const WebKit::UpdateInfo&); + void createTileForLayer(int layerID, int tileID, const WebCore::IntRect&, const SurfaceUpdateInfo&); + void updateTileForLayer(int layerID, int tileID, const WebCore::IntRect&, const SurfaceUpdateInfo&); void removeTileForLayer(int layerID, int tileID); void createDirectlyCompositedImage(int64_t, const WebKit::ShareableBitmap::Handle&); void destroyDirectlyCompositedImage(int64_t); void didReceiveLayerTreeHostProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); void updateViewport(); void renderNextFrame(); + void didChangeScrollPosition(const WebCore::IntPoint& position); void purgeBackingStores(); WebLayerTreeRenderer* layerTreeRenderer() const { return m_renderer.get(); } @@ -73,6 +77,9 @@ protected: DrawingAreaProxy* m_drawingAreaProxy; RefPtr<WebLayerTreeRenderer> m_renderer; +#if USE(GRAPHICS_SURFACE) + HashMap<uint32_t, RefPtr<ShareableSurface> > m_surfaces; +#endif }; } diff --git a/Source/WebKit2/UIProcess/LayerTreeHostProxy.messages.in b/Source/WebKit2/UIProcess/LayerTreeHostProxy.messages.in index 70465b350..1cdae0d33 100644 --- a/Source/WebKit2/UIProcess/LayerTreeHostProxy.messages.in +++ b/Source/WebKit2/UIProcess/LayerTreeHostProxy.messages.in @@ -19,14 +19,19 @@ #if USE(ACCELERATED_COMPOSITING) && USE(TILED_BACKING_STORE) messages -> LayerTreeHostProxy { - SyncCompositingLayerState(WebKit::WebLayerInfo layerInfo) + SetCompositingLayerState(uint32_t id, WebKit::WebLayerInfo layerInfo) + SetCompositingLayerChildren(uint32_t id, Vector<uint32_t> children) +#if ENABLE(CSS_FILTERS) + SetCompositingLayerFilters(uint32_t id, WebCore::FilterOperations filters) +#endif SetRootCompositingLayer(uint32_t id) DeleteCompositingLayer(uint32_t id) - CreateTileForLayer(uint32_t layerID, int tileID, WebKit::UpdateInfo updateInfo) - UpdateTileForLayer(uint32_t layerID, int tileID, WebKit::UpdateInfo updateInfo) + CreateTileForLayer(uint32_t layerID, int tileID, WebCore::IntRect targetRect, WebKit::SurfaceUpdateInfo updateInfo) + UpdateTileForLayer(uint32_t layerID, int tileID, WebCore::IntRect targetRect, WebKit::SurfaceUpdateInfo updateInfo) RemoveTileForLayer(uint32_t layerID, int tileID) CreateDirectlyCompositedImage(int64_t key, WebKit::ShareableBitmap::Handle handle) DestroyDirectlyCompositedImage(int64_t key) DidRenderFrame() + DidChangeScrollPosition(WebCore::IntPoint position) } #endif diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp b/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp index 99ba0ede1..fb8ddb0a6 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp +++ b/Source/WebKit2/UIProcess/Notifications/WebNotification.cpp @@ -33,11 +33,11 @@ namespace WebKit { -WebNotification::WebNotification(const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID) +WebNotification::WebNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID) : m_title(title) , m_body(body) , m_iconURL(iconURL) - , m_replaceID(replaceID) + , m_tag(tag) , 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 19bda4050..3355aab7e 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotification.h +++ b/Source/WebKit2/UIProcess/Notifications/WebNotification.h @@ -45,28 +45,28 @@ class WebNotification : public APIObject { public: static const Type APIType = TypeNotification; - static PassRefPtr<WebNotification> create(const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID) + static PassRefPtr<WebNotification> create(const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID) { - return adoptRef(new WebNotification(title, body, iconURL, replaceID, originString, notificationID)); + return adoptRef(new WebNotification(title, body, iconURL, tag, originString, notificationID)); } const String& title() const { return m_title; } const String& body() const { return m_body; } const String& iconURL() const { return m_iconURL; } - const String& replaceID() const { return m_replaceID; } + const String& tag() const { return m_tag; } WebSecurityOrigin* origin() const { return m_origin.get(); } uint64_t notificationID() const { return m_notificationID; } private: - WebNotification(const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID); + WebNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID); virtual Type type() const { return APIType; } String m_title; String m_body; String m_iconURL; - String m_replaceID; + String m_tag; RefPtr<WebSecurityOrigin> m_origin; uint64_t m_notificationID; }; diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp index 27a889e26..c1246068a 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.cpp @@ -33,7 +33,6 @@ #include "WebNotificationManagerMessages.h" #include "WebPageProxy.h" #include "WebSecurityOrigin.h" -#include <WebCore/NotificationContents.h> using namespace WTF; using namespace WebCore; @@ -77,12 +76,12 @@ void WebNotificationManagerProxy::didReceiveMessage(CoreIPC::Connection* connect didReceiveWebNotificationManagerProxyMessage(connection, messageID, arguments); } -void WebNotificationManagerProxy::show(WebPageProxy* page, const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID) +void WebNotificationManagerProxy::show(WebPageProxy* page, const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID) { if (!isNotificationIDValid(notificationID)) return; - RefPtr<WebNotification> notification = WebNotification::create(title, body, iconURL, replaceID, originString, notificationID); + RefPtr<WebNotification> notification = WebNotification::create(title, body, iconURL, tag, originString, notificationID); m_notifications.set(notificationID, notification); m_provider.show(page, notification.get()); } diff --git a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h index edfccc179..e028d6b93 100644 --- a/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h +++ b/Source/WebKit2/UIProcess/Notifications/WebNotificationManagerProxy.h @@ -60,7 +60,7 @@ public: void initializeProvider(const WKNotificationProvider*); void populateCopyOfNotificationPermissions(HashMap<String, bool>&); - void show(WebPageProxy*, const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID); + void show(WebPageProxy*, const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID); void providerDidShowNotification(uint64_t notificationID); void providerDidClickNotification(uint64_t notificationID); diff --git a/Source/WebKit2/UIProcess/PageClient.h b/Source/WebKit2/UIProcess/PageClient.h index f06d8271f..7c815101d 100644 --- a/Source/WebKit2/UIProcess/PageClient.h +++ b/Source/WebKit2/UIProcess/PageClient.h @@ -29,8 +29,8 @@ #include "ShareableBitmap.h" #include "WebPageProxy.h" #include "WebPopupMenuProxy.h" +#include <WebCore/AlternativeTextClient.h> #include <WebCore/EditorClient.h> -#include <WebCore/SpellingCorrectionController.h> #include <wtf/Forward.h> #if PLATFORM(MAC) @@ -41,7 +41,7 @@ OBJC_CLASS WKView; namespace WebCore { class Cursor; - struct ViewportArguments; + struct ViewportAttributes; } namespace WebKit { @@ -123,7 +123,7 @@ public: virtual void setCursor(const WebCore::Cursor&) = 0; virtual void setCursorHiddenUntilMouseMoves(bool) = 0; - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&) = 0; + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&) = 0; virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo) = 0; virtual void clearAllEditCommands() = 0; @@ -137,6 +137,8 @@ public: virtual void updateTextInputState(bool updateSecureInputState) = 0; virtual void resetTextInputState() = 0; virtual void makeFirstResponder() = 0; + virtual void setPromisedData(const String& pasteboardName, PassRefPtr<WebCore::SharedBuffer> imageBuffer, const String& filename, const String& extension, const String& title, + const String& url, const String& visibleUrl, PassRefPtr<WebCore::SharedBuffer> archiveBuffer) = 0; #endif #if PLATFORM(WIN) virtual void compositionSelectionChanged(bool) = 0; @@ -183,10 +185,10 @@ public: virtual CGContextRef containingWindowGraphicsContext() = 0; virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&) = 0; virtual void dismissDictionaryLookupPanel() = 0; - virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) = 0; - virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel) = 0; - virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel) = 0; - virtual void recordAutocorrectionResponse(WebCore::EditorClient::AutocorrectionResponseType, const String& replacedString, const String& replacementString) = 0; + virtual void showCorrectionPanel(WebCore::AlternativeTextType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) = 0; + virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingAlternativeText) = 0; + virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText) = 0; + virtual void recordAutocorrectionResponse(WebCore::AutocorrectionResponseType, const String& replacedString, const String& replacementString) = 0; virtual void recommendedScrollbarStyleDidChange(int32_t newStyle) = 0; virtual WKView* wkView() const = 0; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp index f37099f2c..cef14dcf0 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp @@ -164,7 +164,7 @@ static inline String pathExtension(const KURL& url) { String extension; String filename = url.lastPathComponent(); - if (!filename.endsWith("/")) { + if (!filename.endsWith('/')) { int extensionPos = filename.reverseFind('.'); if (extensionPos != -1) extension = filename.substring(extensionPos + 1); diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp index 35da365d7..cebf4f7b2 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.cpp @@ -87,8 +87,9 @@ PluginProcessProxy* PluginProcessManager::pluginProcessWithPath(const String& pl { for (size_t i = 0; i < m_pluginProcesses.size(); ++i) { if (m_pluginProcesses[i]->pluginInfo().path == pluginPath) - return m_pluginProcesses[i]; + return m_pluginProcesses[i].get(); } + return 0; } @@ -97,10 +98,12 @@ PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(const PluginM if (PluginProcessProxy* pluginProcess = pluginProcessWithPath(plugin.path)) return pluginProcess; - PluginProcessProxy* pluginProcess = PluginProcessProxy::create(this, plugin).leakPtr(); - m_pluginProcesses.append(pluginProcess); + RefPtr<PluginProcessProxy> pluginProcess = PluginProcessProxy::create(this, plugin); + PluginProcessProxy* pluginProcessPtr = pluginProcess.get(); + + m_pluginProcesses.append(pluginProcess.release()); - return pluginProcess; + return pluginProcessPtr; } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h index 935967bdd..19aafe860 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessManager.h @@ -64,7 +64,7 @@ private: PluginProcessProxy* getOrCreatePluginProcess(const PluginModuleInfo&); PluginProcessProxy* pluginProcessWithPath(const String& pluginPath); - Vector<PluginProcessProxy*> m_pluginProcesses; + Vector<RefPtr<PluginProcessProxy> > m_pluginProcesses; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp index 893f84732..43fa2f4cb 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp @@ -47,9 +47,9 @@ using namespace WebCore; namespace WebKit { -PassOwnPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo) +PassRefPtr<PluginProcessProxy> PluginProcessProxy::create(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo) { - return adoptPtr(new PluginProcessProxy(PluginProcessManager, pluginInfo)); + return adoptRef(new PluginProcessProxy(PluginProcessManager, pluginInfo)); } PluginProcessProxy::PluginProcessProxy(PluginProcessManager* PluginProcessManager, const PluginModuleInfo& pluginInfo) @@ -151,9 +151,8 @@ void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch() while (!m_pendingClearSiteDataReplies.isEmpty()) didClearSiteData(m_pendingClearSiteDataReplies.begin()->first); - // Tell the plug-in process manager to forget about this plug-in process proxy. + // Tell the plug-in process manager to forget about this plug-in process proxy. This may cause us to be deleted. m_pluginProcessManager->removePluginProcessProxy(this); - delete this; } void PluginProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) diff --git a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h index a75d5b138..0a51d9b27 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.h @@ -52,9 +52,17 @@ class WebPluginSiteDataManager; class WebProcessProxy; struct PluginProcessCreationParameters; -class PluginProcessProxy : CoreIPC::Connection::Client, ProcessLauncher::Client { +#if PLUGIN_ARCHITECTURE(X11) +struct RawPluginMetaData { + String name; + String description; + String mimeDescription; +}; +#endif + +class PluginProcessProxy : public RefCounted<PluginProcessProxy>, CoreIPC::Connection::Client, ProcessLauncher::Client { public: - static PassOwnPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginModuleInfo&); + static PassRefPtr<PluginProcessProxy> create(PluginProcessManager*, const PluginModuleInfo&); ~PluginProcessProxy(); const PluginModuleInfo& pluginInfo() const { return m_pluginInfo; } @@ -80,6 +88,10 @@ public: static bool createPropertyListFile(const PluginModuleInfo&); #endif +#if PLUGIN_ARCHITECTURE(X11) + static bool scanPlugin(const String& pluginPath, RawPluginMetaData& result); +#endif + private: PluginProcessProxy(PluginProcessManager*, const PluginModuleInfo&); diff --git a/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp b/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp index 4c85772a2..653c72965 100644 --- a/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp @@ -29,13 +29,51 @@ #if ENABLE(PLUGIN_PROCESS) #include "PluginProcessCreationParameters.h" -#include <WebCore/NotImplemented.h> +#include "ProcessExecutablePath.h" +#include <WebCore/FileSystem.h> +#include <glib.h> +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +using namespace WebCore; namespace WebKit { -void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters) +void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters&) +{ +} + +bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result) { - notImplemented(); + CString binaryPath = fileSystemRepresentation(executablePathOfPluginProcess()); + CString pluginPathCString = fileSystemRepresentation(pluginPath); + char* argv[4]; + argv[0] = const_cast<char*>(binaryPath.data()); + argv[1] = const_cast<char*>("-scanPlugin"); + argv[2] = const_cast<char*>(pluginPathCString.data()); + argv[3] = 0; + + gint status; + gchar* stdOut; + if (!g_spawn_sync(0, argv, 0, G_SPAWN_STDERR_TO_DEV_NULL, 0, 0, &stdOut, 0, &status, 0)) + return false; + if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) + return false; + + const unsigned kNumLinesExpected = 3; + String lines[kNumLinesExpected]; + unsigned lineIndex = 0; + const UChar* current = reinterpret_cast<const UChar*>(stdOut); + while (lineIndex < kNumLinesExpected) { + const UChar* start = current; + while (*current++ != UChar('\n')) { } + lines[lineIndex++] = String(start, current - start - 1); + } + + result.name.swap(lines[0]); + result.description.swap(lines[1]); + result.mimeDescription.swap(lines[2]); + return !result.mimeDescription.isEmpty(); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm index 4e539beaa..290451a4b 100644 --- a/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginProcessProxyMac.mm @@ -202,7 +202,7 @@ void PluginProcessProxy::exitFullscreen() void PluginProcessProxy::setModalWindowIsShowing(bool modalWindowIsShowing) { - if (modalWindowIsShowing == m_modalWindowIsShowing) + if (modalWindowIsShowing == m_modalWindowIsShowing) return; m_modalWindowIsShowing = modalWindowIsShowing; @@ -223,7 +223,11 @@ void PluginProcessProxy::beginModal() m_activationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationWillBecomeActiveNotification object:NSApp queue:nil usingBlock:^(NSNotification *){ applicationDidBecomeActive(); }]; - + + // The call to -[NSApp runModalForWindow:] below will run a nested run loop, and if the plug-in process + // crashes the PluginProcessProxy object can be destroyed. Protect against this here. + RefPtr<PluginProcessProxy> protect(this); + [NSApp runModalForWindow:m_placeholderWindow.get()]; [m_placeholderWindow.get() orderOut:nil]; diff --git a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp index cc521e0af..9b7f2b2dd 100644 --- a/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp +++ b/Source/WebKit2/UIProcess/Plugins/qt/PluginProcessProxyQt.cpp @@ -28,14 +28,51 @@ #if ENABLE(PLUGIN_PROCESS) -#include "PluginProcessCreationParameters.h" -#include <WebCore/NotImplemented.h> +#include "ProcessExecutablePath.h" +#include <QByteArray> +#include <QCoreApplication> +#include <QDir> +#include <QEventLoop> +#include <QProcess> +#include <QString> namespace WebKit { -void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters& parameters) +class PluginProcessCreationParameters; + +void PluginProcessProxy::platformInitializePluginProcess(PluginProcessCreationParameters&) { - notImplemented(); +} + +bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& result) +{ + QString commandLine = QLatin1String("%1 %2 %3"); + commandLine = commandLine.arg(executablePathOfPluginProcess()); + commandLine = commandLine.arg(QStringLiteral("-scanPlugin")).arg(static_cast<QString>(pluginPath)); + + QProcess process; + process.setReadChannel(QProcess::StandardOutput); + process.start(commandLine); + + if (!process.waitForFinished() + || process.exitStatus() != QProcess::NormalExit + || process.exitCode() != EXIT_SUCCESS) { + process.kill(); + return false; + } + + QByteArray outputBytes = process.readAll(); + ASSERT(!(outputBytes.size() % sizeof(UChar))); + + String output(reinterpret_cast<const UChar*>(outputBytes.constData()), outputBytes.size() / sizeof(UChar)); + Vector<String> lines; + output.split(UChar('\n'), lines); + ASSERT(lines.size() == 3); + + result.name.swap(lines[0]); + result.description.swap(lines[1]); + result.mimeDescription.swap(lines[2]); + return !result.mimeDescription.isEmpty(); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp b/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp index 87838ca26..766ae0e20 100644 --- a/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp +++ b/Source/WebKit2/UIProcess/ResponsivenessTimer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ using namespace WebCore; namespace WebKit { -static const double kResponsivenessTimeout = 3; +static const double responsivenessTimeout = 3; ResponsivenessTimer::ResponsivenessTimer(ResponsivenessTimer::Client* client) : m_client(client) @@ -51,13 +51,13 @@ void ResponsivenessTimer::invalidate() void ResponsivenessTimer::timerFired() { - // We'll never schedule the timer unless we're responsive. - ASSERT(m_isResponsive); - - m_isResponsive = false; - m_client->didBecomeUnresponsive(this); - - m_timer.stop(); + if (m_isResponsive) { + m_isResponsive = false; + m_client->didBecomeUnresponsive(this); + } else { + // The timer fired while unresponsive. + m_client->interactionOccurredWhileUnresponsive(this); + } } void ResponsivenessTimer::start() @@ -65,10 +65,7 @@ void ResponsivenessTimer::start() if (m_timer.isActive()) return; - if (!m_isResponsive) - return; - - m_timer.startOneShot(kResponsivenessTimeout); + m_timer.startOneShot(responsivenessTimeout); } void ResponsivenessTimer::stop() diff --git a/Source/WebKit2/UIProcess/ResponsivenessTimer.h b/Source/WebKit2/UIProcess/ResponsivenessTimer.h index 36733151f..307b3b169 100644 --- a/Source/WebKit2/UIProcess/ResponsivenessTimer.h +++ b/Source/WebKit2/UIProcess/ResponsivenessTimer.h @@ -36,6 +36,7 @@ public: public: virtual ~Client() { } virtual void didBecomeUnresponsive(ResponsivenessTimer*) = 0; + virtual void interactionOccurredWhileUnresponsive(ResponsivenessTimer*) = 0; virtual void didBecomeResponsive(ResponsivenessTimer*) = 0; }; diff --git a/Source/WebKit2/UIProcess/WebContext.cpp b/Source/WebKit2/UIProcess/WebContext.cpp index 23ca56be6..f1a0f0fb7 100644 --- a/Source/WebKit2/UIProcess/WebContext.cpp +++ b/Source/WebKit2/UIProcess/WebContext.cpp @@ -66,6 +66,10 @@ #include "BuiltInPDFView.h" #endif +#if USE(SOUP) +#include "WebSoupRequestManagerProxy.h" +#endif + #ifndef NDEBUG #include <wtf/RefCountedLeakCounter.h> #endif @@ -135,6 +139,9 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa , m_notificationManagerProxy(WebNotificationManagerProxy::create(this)) , m_pluginSiteDataManager(WebPluginSiteDataManager::create(this)) , m_resourceCacheManagerProxy(WebResourceCacheManagerProxy::create(this)) +#if USE(SOUP) + , m_soupRequestManagerProxy(WebSoupRequestManagerProxy::create(this)) +#endif #if PLATFORM(WIN) , m_shouldPaintNativeControls(true) , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyAlways) @@ -192,7 +199,12 @@ WebContext::~WebContext() m_resourceCacheManagerProxy->invalidate(); m_resourceCacheManagerProxy->clearContext(); - + +#if USE(SOUP) + m_soupRequestManagerProxy->invalidate(); + m_soupRequestManagerProxy->clearContext(); +#endif + invalidateCallbackMap(m_dictionaryCallbacks); platformInvalidateContext(); @@ -259,10 +271,8 @@ void WebContext::ensureWebProcess() parameters.applicationCacheDirectory = applicationCacheDirectory(); parameters.databaseDirectory = databaseDirectory(); parameters.localStorageDirectory = localStorageDirectory(); - parameters.webInspectorLocalizedStringsPath = m_overrideWebInspectorLocalizedStringsPath; #if PLATFORM(MAC) - parameters.webInspectorBaseDirectory = m_overrideWebInspectorBaseDirectory; parameters.presenterApplicationPid = getpid(); #endif @@ -281,7 +291,7 @@ void WebContext::ensureWebProcess() parameters.defaultRequestTimeoutInterval = WebURLRequest::defaultTimeoutInterval(); -#if ENABLE(NOTIFICATIONS) +#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) m_notificationManagerProxy->populateCopyOfNotificationPermissions(parameters.notificationPermissions); #endif @@ -382,6 +392,9 @@ void WebContext::disconnectProcess(WebProcessProxy* process) m_mediaCacheManagerProxy->invalidate(); m_notificationManagerProxy->invalidate(); m_resourceCacheManagerProxy->invalidate(); +#if USE(SOUP) + m_soupRequestManagerProxy->invalidate(); +#endif // When out of process plug-ins are enabled, we don't want to invalidate the plug-in site data // manager just because the web process crashes since it's not involved. @@ -718,6 +731,13 @@ void WebContext::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::Mes return; } +#if USE(SOUP) + if (messageID.is<CoreIPC::MessageClassWebSoupRequestManagerProxy>()) { + m_soupRequestManagerProxy->didReceiveMessage(connection, messageID, arguments); + return; + } +#endif + switch (messageID.get<WebContextLegacyMessage::Kind>()) { case WebContextLegacyMessage::PostMessage: { String messageName; diff --git a/Source/WebKit2/UIProcess/WebContext.h b/Source/WebKit2/UIProcess/WebContext.h index c378725dc..ddf3d7932 100644 --- a/Source/WebKit2/UIProcess/WebContext.h +++ b/Source/WebKit2/UIProcess/WebContext.h @@ -58,6 +58,9 @@ class WebNotificationManagerProxy; class WebPageGroup; class WebPageProxy; class WebResourceCacheManagerProxy; +#if USE(SOUP) +class WebSoupRequestManagerProxy; +#endif struct StatisticsData; struct WebProcessCreationParameters; @@ -161,6 +164,9 @@ public: WebNotificationManagerProxy* notificationManagerProxy() const { return m_notificationManagerProxy.get(); } WebPluginSiteDataManager* pluginSiteDataManager() const { return m_pluginSiteDataManager.get(); } WebResourceCacheManagerProxy* resourceCacheManagerProxy() const { return m_resourceCacheManagerProxy.get(); } +#if USE(SOUP) + WebSoupRequestManagerProxy* soupRequestManagerProxy() const { return m_soupRequestManagerProxy.get(); } +#endif struct Statistics { unsigned wkViewCount; @@ -174,14 +180,6 @@ public: String iconDatabasePath() const; void setLocalStorageDirectory(const String& dir) { m_overrideLocalStorageDirectory = dir; } - String overrideWebInspectorBaseDirectory() const { return m_overrideWebInspectorBaseDirectory; } - void setOverrideWebInspectorBaseDirectory(const String& path) { m_overrideWebInspectorBaseDirectory = path; } - - String overrideWebInspectorPagePath() const { return m_overrideWebInspectorPagePath; } - void setOverrideWebInspectorPagePath(const String& path) { m_overrideWebInspectorPagePath = path; } - - void setOverrideWebInspectorLocalizedStringsPath(const String& path) { m_overrideWebInspectorLocalizedStringsPath = path; } - void ensureWebProcess(); void warmInitialProcess(); @@ -234,6 +232,8 @@ private: void getPasteboardChangeCount(const String& pasteboardName, uint64_t& changeCount); void getPasteboardUniqueName(String& pasteboardName); void getPasteboardColor(const String& pasteboardName, WebCore::Color&); + void getPasteboardURL(const String& pasteboardName, WTF::String&); + void addPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes); void setPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes); void setPasteboardPathnamesForType(const String& pasteboardName, const String& pasteboardType, const Vector<String>& pathnames); void setPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, const String&); @@ -302,6 +302,9 @@ private: RefPtr<WebNotificationManagerProxy> m_notificationManagerProxy; RefPtr<WebPluginSiteDataManager> m_pluginSiteDataManager; RefPtr<WebResourceCacheManagerProxy> m_resourceCacheManagerProxy; +#if USE(SOUP) + RefPtr<WebSoupRequestManagerProxy> m_soupRequestManagerProxy; +#endif #if PLATFORM(WIN) bool m_shouldPaintNativeControls; @@ -315,9 +318,6 @@ private: String m_overrideDatabaseDirectory; String m_overrideIconDatabasePath; String m_overrideLocalStorageDirectory; - String m_overrideWebInspectorBaseDirectory; - String m_overrideWebInspectorPagePath; - String m_overrideWebInspectorLocalizedStringsPath; bool m_processTerminationEnabled; diff --git a/Source/WebKit2/UIProcess/WebContext.messages.in b/Source/WebKit2/UIProcess/WebContext.messages.in index 4bc3ec7d4..85ea7a2b7 100644 --- a/Source/WebKit2/UIProcess/WebContext.messages.in +++ b/Source/WebKit2/UIProcess/WebContext.messages.in @@ -53,6 +53,8 @@ messages -> WebContext { GetPasteboardChangeCount(WTF::String pasteboardName) -> (uint64_t changeCount) GetPasteboardUniqueName() -> (WTF::String pasteboardName) GetPasteboardColor(WTF::String pasteboardName) -> (WebCore::Color color) + GetPasteboardURL(WTF::String pasteboardName) -> (WTF::String urlString) + AddPasteboardTypes(WTF::String pasteboardName, Vector<WTF::String> pasteboardTypes) SetPasteboardTypes(WTF::String pasteboardName, Vector<WTF::String> pasteboardTypes) SetPasteboardPathnamesForType(WTF::String pasteboardName, WTF::String pasteboardType, Vector<WTF::String> pathnames) SetPasteboardStringForType(WTF::String pasteboardName, WTF::String pasteboardType, WTF::String string) diff --git a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp index 17c070b6d..bb1bd6011 100644 --- a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.cpp @@ -89,12 +89,14 @@ void WebFullScreenManagerProxy::setAnimatingFullScreen(bool animating) m_page->process()->send(Messages::WebFullScreenManager::SetAnimatingFullScreen(animating), m_page->pageID()); } +void WebFullScreenManagerProxy::requestExitFullScreen() +{ + m_page->process()->send(Messages::WebFullScreenManager::RequestExitFullScreen(), m_page->pageID()); +} + void WebFullScreenManagerProxy::supportsFullScreen(bool withKeyboard, bool& supports) { - if (withKeyboard) - supports = false; - else - supports = true; + supports = true; } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.h b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.h index c947f1652..61435d647 100644 --- a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.h +++ b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.h @@ -44,6 +44,10 @@ class IntRect; #if PLATFORM(MAC) OBJC_CLASS WKView; +#elif PLATFORM(GTK) +typedef struct _WebKitWebViewBase WebKitWebViewBase; +#elif PLATFORM(QT) +class QQuickWebView; #endif namespace WebKit { @@ -54,11 +58,11 @@ typedef WKView PlatformWebView; class WebView; typedef WebView PlatformWebView; #elif PLATFORM(QT) -// FIXME: We need to investigate how to abstract QDesktopWebView/QTouchWebView here. -typedef QObject PlatformWebView; +typedef QQuickWebView PlatformWebView; #elif PLATFORM(GTK) -class WebView; -typedef WebView PlatformWebView; +typedef WebKitWebViewBase PlatformWebView; +#elif PLATFORM(EFL) +typedef Evas_Object PlatformWebView; #endif class WebPageProxy; @@ -72,6 +76,8 @@ public: void invalidate(); void setWebView(PlatformWebView*); + bool isFullScreen(); + void close(); void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply); @@ -81,6 +87,7 @@ public: void willExitFullScreen(); void didExitFullScreen(); void setAnimatingFullScreen(bool); + void requestExitFullScreen(); private: WebFullScreenManagerProxy(WebPageProxy*); diff --git a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.messages.in b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.messages.in index c52cea92e..97e46130f 100644 --- a/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebFullScreenManagerProxy.messages.in @@ -27,5 +27,6 @@ messages -> WebFullScreenManagerProxy { ExitFullScreen() BeganEnterFullScreen(WebCore::IntRect initialRect, WebCore::IntRect finalRect) BeganExitFullScreen(WebCore::IntRect initialRect, WebCore::IntRect finalRect) + Close() } #endif diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp index 6bf7a6bd9..ab19d5d14 100644 --- a/Source/WebKit2/UIProcess/WebInspectorProxy.cpp +++ b/Source/WebKit2/UIProcess/WebInspectorProxy.cpp @@ -29,6 +29,7 @@ #if ENABLE(INSPECTOR) +#include "WebFramePolicyListenerProxy.h" #include "WebFrameProxy.h" #include "WebInspectorMessages.h" #include "WebPageCreationParameters.h" @@ -36,7 +37,11 @@ #include "WebPageProxy.h" #include "WebPreferences.h" #include "WebProcessProxy.h" +#include "WebURLRequest.h" +#if ENABLE(INSPECTOR_SERVER) +#include "WebInspectorServer.h" +#endif #if PLATFORM(WIN) #include "WebView.h" #endif @@ -79,6 +84,9 @@ WebInspectorProxy::WebInspectorProxy(WebPageProxy* page) , m_inspectorView(0) , m_inspectorWindow(0) #endif +#if ENABLE(INSPECTOR_SERVER) + , m_remoteInspectionPageId(0) +#endif { } @@ -88,6 +96,11 @@ WebInspectorProxy::~WebInspectorProxy() void WebInspectorProxy::invalidate() { +#if ENABLE(INSPECTOR_SERVER) + if (m_remoteInspectionPageId) + WebInspectorServer::shared().unregisterPage(m_remoteInspectionPageId); +#endif + m_page->close(); didClose(); @@ -224,6 +237,59 @@ bool WebInspectorProxy::isInspectorPage(WebPageProxy* page) return page->pageGroup() == inspectorPageGroup(); } +static void decidePolicyForNavigationAction(WKPageRef, WKFrameRef frameRef, WKFrameNavigationType, WKEventModifiers, WKEventMouseButton, WKURLRequestRef requestRef, WKFramePolicyListenerRef listenerRef, WKTypeRef, const void* clientInfo) +{ + // Allow non-main frames to navigate anywhere. + if (!toImpl(frameRef)->isMainFrame()) { + toImpl(listenerRef)->use(); + return; + } + + const WebInspectorProxy* webInspectorProxy = static_cast<const WebInspectorProxy*>(clientInfo); + ASSERT(webInspectorProxy); + + // Use KURL so we can compare just the fileSystemPaths. + KURL inspectorURL(KURL(), webInspectorProxy->inspectorPageURL()); + KURL requestURL(KURL(), toImpl(requestRef)->url()); + + ASSERT(inspectorURL.isLocalFile()); + + // Allow loading of the main inspector file. + if (requestURL.isLocalFile() && requestURL.fileSystemPath() == inspectorURL.fileSystemPath()) { + toImpl(listenerRef)->use(); + return; + } + + // Prevent everything else from loading in the inspector's page. + toImpl(listenerRef)->ignore(); + + // And instead load it in the inspected page. + webInspectorProxy->page()->loadURLRequest(toImpl(requestRef)); +} + +#if ENABLE(INSPECTOR_SERVER) +void WebInspectorProxy::enableRemoteInspection() +{ + if (!m_remoteInspectionPageId) + m_remoteInspectionPageId = WebInspectorServer::shared().registerPage(this); +} + +void WebInspectorProxy::remoteFrontendConnected() +{ + m_page->process()->send(Messages::WebInspector::RemoteFrontendConnected(), m_page->pageID()); +} + +void WebInspectorProxy::remoteFrontendDisconnected() +{ + m_page->process()->send(Messages::WebInspector::RemoteFrontendDisconnected(), m_page->pageID()); +} + +void WebInspectorProxy::dispatchMessageFromRemoteFrontend(const String& message) +{ + m_page->process()->send(Messages::WebInspector::DispatchMessageFromRemoteFrontend(message), m_page->pageID()); +} +#endif + // Called by WebInspectorProxy messages void WebInspectorProxy::createInspectorPage(uint64_t& inspectorPageID, WebPageCreationParameters& inspectorPageParameters) { @@ -242,10 +308,23 @@ void WebInspectorProxy::createInspectorPage(uint64_t& inspectorPageID, WebPageCr inspectorPageID = inspectorPage->pageID(); inspectorPageParameters = inspectorPage->creationParameters(); + WKPagePolicyClient policyClient = { + kWKPagePolicyClientCurrentVersion, + this, /* clientInfo */ + decidePolicyForNavigationAction, + 0, /* decidePolicyForNewWindowAction */ + 0, /* decidePolicyForResponse */ + 0 /* unableToImplementPolicy */ + }; + + inspectorPage->initializePolicyClient(&policyClient); + String url = inspectorPageURL(); if (m_isAttached) url += "?docked=true"; + m_page->process()->assumeReadAccessToBaseURL(inspectorBaseURL()); + inspectorPage->loadURL(url); } @@ -303,6 +382,14 @@ bool WebInspectorProxy::shouldOpenAttached() return inspectorPageGroup()->preferences()->inspectorStartsAttached() && canAttach(); } +#if ENABLE(INSPECTOR_SERVER) +void WebInspectorProxy::sendMessageToRemoteFrontend(const String& message) +{ + ASSERT(m_remoteInspectionPageId); + WebInspectorServer::shared().sendMessageOverConnection(m_remoteInspectionPageId, message); +} +#endif + } // namespace WebKit #endif // ENABLE(INSPECTOR) diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.h b/Source/WebKit2/UIProcess/WebInspectorProxy.h index 884b66621..961467284 100644 --- a/Source/WebKit2/UIProcess/WebInspectorProxy.h +++ b/Source/WebKit2/UIProcess/WebInspectorProxy.h @@ -119,6 +119,17 @@ public: static bool isInspectorPage(WebPageProxy*); + // Implemented the platform WebInspectorProxy file + String inspectorPageURL() const; + String inspectorBaseURL() const; + +#if ENABLE(INSPECTOR_SERVER) + void enableRemoteInspection(); + void remoteFrontendConnected(); + void remoteFrontendDisconnected(); + void dispatchMessageFromRemoteFrontend(const String& message); +#endif + private: WebInspectorProxy(WebPageProxy* page); @@ -135,10 +146,6 @@ private: void platformDetach(); void platformSetAttachedWindowHeight(unsigned); - // Implemented the platform WebInspectorProxy file - String inspectorPageURL() const; - String inspectorBaseURL() const; - // Called by WebInspectorProxy messages void createInspectorPage(uint64_t& inspectorPageID, WebPageCreationParameters&); void didLoadInspectorPage(); @@ -146,6 +153,10 @@ private: void bringToFront(); void inspectedURLChanged(const String&); +#if ENABLE(INSPECTOR_SERVER) + void sendMessageToRemoteFrontend(const String& message); +#endif + bool canAttach(); bool shouldOpenAttached(); @@ -194,6 +205,9 @@ private: GtkWidget* m_inspectorView; GtkWidget* m_inspectorWindow; #endif +#if ENABLE(INSPECTOR_SERVER) + int m_remoteInspectionPageId; +#endif }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.messages.in b/Source/WebKit2/UIProcess/WebInspectorProxy.messages.in index a1949858e..2b6663369 100644 --- a/Source/WebKit2/UIProcess/WebInspectorProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebInspectorProxy.messages.in @@ -32,6 +32,10 @@ messages -> WebInspectorProxy { Attach() Detach() SetAttachedWindowHeight(unsigned height) + +#if ENABLE(INSPECTOR_SERVER) + SendMessageToRemoteFrontend(WTF::String message) +#endif } #endif diff --git a/Source/WebKit2/UIProcess/WebLayerTreeRenderer.cpp b/Source/WebKit2/UIProcess/WebLayerTreeRenderer.cpp index f2c049592..fa301a2aa 100644 --- a/Source/WebKit2/UIProcess/WebLayerTreeRenderer.cpp +++ b/Source/WebKit2/UIProcess/WebLayerTreeRenderer.cpp @@ -26,7 +26,6 @@ #include "GraphicsLayerTextureMapper.h" #include "LayerBackingStore.h" #include "LayerTreeHostProxy.h" -#include "MainThread.h" #include "MessageID.h" #include "ShareableBitmap.h" #include "TextureMapper.h" @@ -35,6 +34,7 @@ #include "UpdateInfo.h" #include <OpenGLShims.h> #include <wtf/Atomics.h> +#include <wtf/MainThread.h> namespace WebKit { @@ -73,9 +73,21 @@ void WebLayerTreeRenderer::callOnMainTread(const Function<void()>& function) MainThreadGuardedInvoker<WebLayerTreeRenderer>::call(this, function); } +static IntPoint boundedScrollPosition(const IntPoint& scrollPosition, const IntRect& visibleContentRect, const FloatSize& contentSize) +{ + IntSize size(contentSize.width(), contentSize.height()); + int scrollPositionX = std::max(scrollPosition.x(), 0); + scrollPositionX = std::min(scrollPositionX, size.width() - visibleContentRect.width()); + + int scrollPositionY = std::max(scrollPosition.y(), 0); + scrollPositionY = std::min(scrollPositionY, size.height() - visibleContentRect.height()); + return IntPoint(scrollPositionX, scrollPositionY); +} + WebLayerTreeRenderer::WebLayerTreeRenderer(LayerTreeHostProxy* layerTreeHostProxy) : m_layerTreeHostProxy(layerTreeHostProxy) - , m_rootLayerID(0) + , m_rootLayerID(InvalidWebLayerID) + , m_isActive(false) { } @@ -91,13 +103,19 @@ PassOwnPtr<GraphicsLayer> WebLayerTreeRenderer::createLayer(WebLayerID layerID) return adoptPtr(newLayer); } -void WebLayerTreeRenderer::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect) +void WebLayerTreeRenderer::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, TextureMapper::PaintFlags PaintFlags) { if (!m_textureMapper) m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode); ASSERT(m_textureMapper->accelerationMode() == TextureMapper::OpenGLMode); - syncRemoteContent(); + // We need to compensate for the rounding error that happens due to m_visibleContentsRect being + // int and not float. We do that by moving the TransformationMatrix by the delta between the + // position of m_visibleContentsRect and the position it would have if it wasn't rounded. + + TransformationMatrix newMatrix = matrix; + newMatrix.translate(m_accurateVisibleContentsPosition.x() / m_contentsScale - m_visibleContentsRect.x(), m_accurateVisibleContentsPosition.y() / m_contentsScale - m_visibleContentsRect.y()); + adjustPositionForFixedLayers(); GraphicsLayer* currentRootLayer = rootLayer(); if (!currentRootLayer) return; @@ -108,31 +126,18 @@ void WebLayerTreeRenderer::paintToCurrentGLContext(const TransformationMatrix& m return; layer->setTextureMapper(m_textureMapper.get()); - m_textureMapper->beginPainting(); - m_textureMapper->bindSurface(0); + m_textureMapper->beginPainting(PaintFlags); m_textureMapper->beginClip(TransformationMatrix(), clipRect); - if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) { + if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != newMatrix) { currentRootLayer->setOpacity(opacity); - currentRootLayer->setTransform(matrix); + currentRootLayer->setTransform(newMatrix); currentRootLayer->syncCompositingStateForThisLayerOnly(); } layer->paint(); m_textureMapper->endClip(); m_textureMapper->endPainting(); - - syncAnimations(); -} - -void WebLayerTreeRenderer::syncAnimations() -{ - TextureMapperLayer* layer = toTextureMapperLayer(rootLayer()); - ASSERT(layer); - - layer->syncAnimationsRecursively(); - if (layer->descendantsOrSelfHaveRunningAnimations()) - callOnMainThread(bind(&WebLayerTreeRenderer::updateViewport, this)); } void WebLayerTreeRenderer::paintToGraphicsContext(QPainter* painter) @@ -149,16 +154,21 @@ void WebLayerTreeRenderer::paintToGraphicsContext(QPainter* painter) GraphicsContext graphicsContext(painter); m_textureMapper->setGraphicsContext(&graphicsContext); m_textureMapper->beginPainting(); - m_textureMapper->bindSurface(0); layer->paint(); m_textureMapper->endPainting(); m_textureMapper->setGraphicsContext(0); } -void WebLayerTreeRenderer::setVisibleContentsRectForScaling(const IntRect& rect, float scale) +void WebLayerTreeRenderer::setContentsSize(const WebCore::FloatSize& contentsSize) +{ + m_contentsSize = contentsSize; +} + +void WebLayerTreeRenderer::setVisibleContentsRect(const IntRect& rect, float scale, const WebCore::FloatPoint& accurateVisibleContentsPosition) { m_visibleContentsRect = rect; m_contentsScale = scale; + m_accurateVisibleContentsPosition = accurateVisibleContentsPosition; } void WebLayerTreeRenderer::updateViewport() @@ -167,15 +177,61 @@ void WebLayerTreeRenderer::updateViewport() m_layerTreeHostProxy->updateViewport(); } -void WebLayerTreeRenderer::syncLayerParameters(const WebLayerInfo& layerInfo) +void WebLayerTreeRenderer::adjustPositionForFixedLayers() +{ + if (m_fixedLayers.isEmpty()) + return; + + IntPoint scrollPosition = boundedScrollPosition(m_visibleContentsRect.location(), m_visibleContentsRect, m_contentsSize); + + LayerMap::iterator end = m_fixedLayers.end(); + for (LayerMap::iterator it = m_fixedLayers.begin(); it != end; ++it) + toTextureMapperLayer(it->second)->setScrollPositionDeltaIfNeeded(IntPoint(scrollPosition.x() - m_renderedContentsScrollPosition.x(), scrollPosition.y() - m_renderedContentsScrollPosition.y())); +} + +void WebLayerTreeRenderer::didChangeScrollPosition(const IntPoint& position) +{ + m_pendingRenderedContentsScrollPosition = boundedScrollPosition(position, m_visibleContentsRect, m_contentsSize); +} + +void WebLayerTreeRenderer::setLayerChildren(WebLayerID id, const Vector<WebLayerID>& childIDs) { - WebLayerID id = layerInfo.id; ensureLayer(id); LayerMap::iterator it = m_layers.find(id); GraphicsLayer* layer = it->second; - bool needsToUpdateImageTiles = layerInfo.imageIsUpdated || (layerInfo.contentsRect != layer->contentsRect() && layerInfo.imageBackingStoreID); + Vector<GraphicsLayer*> children; - layer->setName(layerInfo.name); + for (size_t i = 0; i < childIDs.size(); ++i) { + WebLayerID childID = childIDs[i]; + GraphicsLayer* child = layerByID(childID); + if (!child) { + child = createLayer(childID).leakPtr(); + m_layers.add(childID, child); + } + children.append(child); + } + layer->setChildren(children); +} + +#if ENABLE(CSS_FILTERS) +void WebLayerTreeRenderer::setLayerFilters(WebLayerID id, const FilterOperations& filters) +{ + ensureLayer(id); + LayerMap::iterator it = m_layers.find(id); + ASSERT(it != m_layers.end()); + + GraphicsLayer* layer = it->second; + layer->setFilters(filters); +} +#endif + +void WebLayerTreeRenderer::setLayerState(WebLayerID id, const WebLayerInfo& layerInfo) +{ + ensureLayer(id); + LayerMap::iterator it = m_layers.find(id); + ASSERT(it != m_layers.end()); + + GraphicsLayer* layer = it->second; layer->setReplicatedByLayer(layerByID(layerInfo.replica)); layer->setMaskLayer(layerByID(layerInfo.mask)); @@ -189,46 +245,19 @@ void WebLayerTreeRenderer::syncLayerParameters(const WebLayerInfo& layerInfo) layer->setContentsOpaque(layerInfo.contentsOpaque); layer->setContentsRect(layerInfo.contentsRect); layer->setDrawsContent(layerInfo.drawsContent); + toGraphicsLayerTextureMapper(layer)->setFixedToViewport(layerInfo.fixedToViewport); - if (needsToUpdateImageTiles) - assignImageToLayer(layer, layerInfo.imageBackingStoreID); + if (layerInfo.fixedToViewport) + m_fixedLayers.add(id, layer); + else + m_fixedLayers.remove(id); + + assignImageToLayer(layer, layerInfo.imageBackingStoreID); // Never make the root layer clip. layer->setMasksToBounds(layerInfo.isRootLayer ? false : layerInfo.masksToBounds); layer->setOpacity(layerInfo.opacity); layer->setPreserves3D(layerInfo.preserves3D); - Vector<GraphicsLayer*> children; - - for (size_t i = 0; i < layerInfo.children.size(); ++i) { - WebLayerID childID = layerInfo.children[i]; - GraphicsLayer* child = layerByID(childID); - if (!child) { - child = createLayer(childID).leakPtr(); - m_layers.add(childID, child); - } - children.append(child); - } - layer->setChildren(children); - - for (size_t i = 0; i < layerInfo.animations.size(); ++i) { - const WebKit::WebLayerAnimation anim = layerInfo.animations[i]; - - switch (anim.operation) { - case WebKit::WebLayerAnimation::AddAnimation: { - const IntSize boxSize = anim.boxSize; - layer->addAnimation(anim.keyframeList, boxSize, anim.animation.get(), anim.name, anim.startTime); - break; - } - case WebKit::WebLayerAnimation::RemoveAnimation: - layer->removeAnimation(anim.name); - break; - case WebKit::WebLayerAnimation::PauseAnimation: - double offset = WTF::currentTime() - anim.startTime; - layer->pauseAnimation(anim.name, offset); - break; - } - } - if (layerInfo.isRootLayer && m_rootLayerID != id) setRootLayerID(id); } @@ -241,6 +270,7 @@ void WebLayerTreeRenderer::deleteLayer(WebLayerID layerID) layer->removeFromParent(); m_layers.remove(layerID); + m_fixedLayers.remove(layerID); delete layer; } @@ -274,8 +304,8 @@ void WebLayerTreeRenderer::setRootLayerID(WebLayerID layerID) PassRefPtr<LayerBackingStore> WebLayerTreeRenderer::getBackingStore(WebLayerID id) { - ensureLayer(id); TextureMapperLayer* layer = toTextureMapperLayer(layerByID(id)); + ASSERT(layer); RefPtr<LayerBackingStore> backingStore = static_cast<LayerBackingStore*>(layer->backingStore().get()); if (!backingStore) { backingStore = LayerBackingStore::create(); @@ -295,11 +325,10 @@ void WebLayerTreeRenderer::removeTile(WebLayerID layerID, int tileID) getBackingStore(layerID)->removeTile(tileID); } -void WebLayerTreeRenderer::updateTile(WebLayerID layerID, int tileID, const IntRect& sourceRect, const IntRect& targetRect, PassRefPtr<ShareableBitmap> weakBitmap) +void WebLayerTreeRenderer::updateTile(WebLayerID layerID, int tileID, const TileUpdate& update) { - RefPtr<ShareableBitmap> bitmap = weakBitmap; RefPtr<LayerBackingStore> backingStore = getBackingStore(layerID); - backingStore->updateTile(tileID, sourceRect, targetRect, bitmap.get()); + backingStore->updateTile(tileID, update.sourceRect, update.targetRect, update.surface, update.offset); m_backingStoresWithPendingBuffers.add(backingStore); } @@ -307,8 +336,8 @@ void WebLayerTreeRenderer::createImage(int64_t imageID, PassRefPtr<ShareableBitm { RefPtr<ShareableBitmap> bitmap = weakBitmap; RefPtr<TextureMapperTiledBackingStore> backingStore = TextureMapperTiledBackingStore::create(); - backingStore->updateContents(m_textureMapper.get(), bitmap->createImage().get(), BitmapTexture::BGRAFormat); m_directlyCompositedImages.set(imageID, backingStore); + backingStore->updateContents(m_textureMapper.get(), bitmap->createImage().get()); } void WebLayerTreeRenderer::destroyImage(int64_t imageID) @@ -318,24 +347,31 @@ void WebLayerTreeRenderer::destroyImage(int64_t imageID) void WebLayerTreeRenderer::assignImageToLayer(GraphicsLayer* layer, int64_t imageID) { + if (!imageID) { + layer->setContentsToMedia(0); + return; + } + HashMap<int64_t, RefPtr<TextureMapperBackingStore> >::iterator it = m_directlyCompositedImages.find(imageID); ASSERT(it != m_directlyCompositedImages.end()); layer->setContentsToMedia(it->second.get()); } -void WebLayerTreeRenderer::swapBuffers() +void WebLayerTreeRenderer::commitTileOperations() { HashSet<RefPtr<LayerBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end(); for (HashSet<RefPtr<LayerBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it) - (*it)->swapBuffers(m_textureMapper.get()); + (*it)->commitTileOperations(m_textureMapper.get()); m_backingStoresWithPendingBuffers.clear(); } void WebLayerTreeRenderer::flushLayerChanges() { + m_renderedContentsScrollPosition = m_pendingRenderedContentsScrollPosition; + m_rootLayer->syncCompositingState(FloatRect()); - swapBuffers(); + commitTileOperations(); // The pending tiles state is on its way for the screen, tell the web process to render the next one. callOnMainThread(bind(&WebLayerTreeRenderer::renderNextFrame, this)); @@ -383,6 +419,12 @@ void WebLayerTreeRenderer::purgeGLResources() layer->clearBackingStoresRecursive(); m_directlyCompositedImages.clear(); + + m_rootLayer->removeAllChildren(); + m_rootLayer.clear(); + m_rootLayerID = InvalidWebLayerID; + m_layers.clear(); + m_fixedLayers.clear(); m_textureMapper.clear(); m_backingStoresWithPendingBuffers.clear(); @@ -402,9 +444,24 @@ void WebLayerTreeRenderer::detach() void WebLayerTreeRenderer::appendUpdate(const Function<void()>& function) { + if (!m_isActive) + return; + m_renderQueue.append(function); } +void WebLayerTreeRenderer::setActive(bool active) +{ + if (m_isActive == active) + return; + + // Have to clear render queue in both cases. + // If there are some updates in queue during activation then those updates are from previous instance of paint node + // and cannot be applied to the newly created instance. + m_renderQueue.clear(); + m_isActive = active; +} + } // namespace WebKit #endif // USE(UI_SIDE_COMPOSITING) diff --git a/Source/WebKit2/UIProcess/WebLayerTreeRenderer.h b/Source/WebKit2/UIProcess/WebLayerTreeRenderer.h index 6c788652a..042c52d06 100644 --- a/Source/WebKit2/UIProcess/WebLayerTreeRenderer.h +++ b/Source/WebKit2/UIProcess/WebLayerTreeRenderer.h @@ -21,8 +21,8 @@ #define WebLayerTreeRenderer_h #if USE(UI_SIDE_COMPOSITING) - #include "BackingStore.h" +#include "ShareableSurface.h" #include "TextureMapper.h" #include "TextureMapperBackingStore.h" #include "WebLayerTreeInfo.h" @@ -45,24 +45,45 @@ class WebLayerUpdateInfo; class WebLayerTreeRenderer : public ThreadSafeRefCounted<WebLayerTreeRenderer>, public WebCore::GraphicsLayerClient { public: + struct TileUpdate { + WebCore::IntRect sourceRect; + WebCore::IntRect targetRect; + RefPtr<ShareableSurface> surface; + WebCore::IntPoint offset; + TileUpdate(const WebCore::IntRect& source, const WebCore::IntRect& target, PassRefPtr<ShareableSurface> newSurface, const WebCore::IntPoint& newOffset) + : sourceRect(source) + , targetRect(target) + , surface(newSurface) + , offset(newOffset) + { + } + }; WebLayerTreeRenderer(LayerTreeHostProxy*); virtual ~WebLayerTreeRenderer(); void purgeGLResources(); - void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&); + void paintToCurrentGLContext(const WebCore::TransformationMatrix&, float, const WebCore::FloatRect&, WebCore::TextureMapper::PaintFlags = 0); void paintToGraphicsContext(BackingStore::PlatformGraphicsContext); void syncRemoteContent(); - void setVisibleContentsRectForScaling(const WebCore::IntRect&, float); + void setContentsSize(const WebCore::FloatSize&); + void setVisibleContentsRect(const WebCore::IntRect&, float scale, const WebCore::FloatPoint& accurateVisibleContentsPosition); + void didChangeScrollPosition(const WebCore::IntPoint& position); void detach(); void appendUpdate(const Function<void()>&); void updateViewport(); + void setActive(bool); void deleteLayer(WebLayerID); void setRootLayerID(WebLayerID); - void syncLayerParameters(const WebLayerInfo&); + void setLayerChildren(WebLayerID, const Vector<WebLayerID>&); + void setLayerState(WebLayerID, const WebLayerInfo&); +#if ENABLE(CSS_FILTERS) + void setLayerFilters(WebLayerID, const WebCore::FilterOperations&); +#endif + void createTile(WebLayerID, int, float scale); void removeTile(WebLayerID, int); - void updateTile(WebLayerID, int, const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<ShareableBitmap>); + void updateTile(WebLayerID, int, const TileUpdate&); void flushLayerChanges(); void createImage(int64_t, PassRefPtr<ShareableBitmap>); void destroyImage(int64_t); @@ -80,9 +101,12 @@ private: virtual bool showRepaintCounter(const WebCore::GraphicsLayer*) const { return false; } void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect&) { } void callOnMainTread(const Function<void()>&); + void adjustPositionForFixedLayers(); typedef HashMap<WebLayerID, WebCore::GraphicsLayer*> LayerMap; + WebCore::FloatSize m_contentsSize; WebCore::IntRect m_visibleContentsRect; + WebCore::FloatPoint m_accurateVisibleContentsPosition; float m_contentsScale; // Render queue can be accessed ony from main thread or updatePaintNode call stack! @@ -100,7 +124,7 @@ private: void assignImageToLayer(WebCore::GraphicsLayer*, int64_t imageID); void ensureRootLayer(); void ensureLayer(WebLayerID); - void swapBuffers(); + void commitTileOperations(); void syncAnimations(); void renderNextFrame(); void purgeBackingStores(); @@ -110,7 +134,11 @@ private: Vector<WebLayerID> m_layersToDelete; LayerMap m_layers; + LayerMap m_fixedLayers; WebLayerID m_rootLayerID; + WebCore::IntPoint m_renderedContentsScrollPosition; + WebCore::IntPoint m_pendingRenderedContentsScrollPosition; + bool m_isActive; }; }; diff --git a/Source/WebKit2/UIProcess/WebLoaderClient.cpp b/Source/WebKit2/UIProcess/WebLoaderClient.cpp index 2aae01617..ca9d7f6f1 100644 --- a/Source/WebKit2/UIProcess/WebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/WebLoaderClient.cpp @@ -211,6 +211,14 @@ void WebLoaderClient::processDidBecomeUnresponsive(WebPageProxy* page) m_client.processDidBecomeUnresponsive(toAPI(page), m_client.clientInfo); } +void WebLoaderClient::interactionOccurredWhileProcessUnresponsive(WebPageProxy* page) +{ + if (!m_client.interactionOccurredWhileProcessUnresponsive) + return; + + m_client.interactionOccurredWhileProcessUnresponsive(toAPI(page), m_client.clientInfo); +} + void WebLoaderClient::processDidBecomeResponsive(WebPageProxy* page) { if (!m_client.processDidBecomeResponsive) @@ -243,17 +251,17 @@ bool WebLoaderClient::shouldGoToBackForwardListItem(WebPageProxy* page, WebBackF { // We should only even considering sending the shouldGoToBackForwardListItem() client callback // for version 0 clients. Later versioned clients should get willGoToBackForwardListItem() instead, - // but do to XPC race conditions this one might have been called instead. + // but due to XPC race conditions this one might have been called instead. if (m_client.version > 0 || !m_client.shouldGoToBackForwardListItem) return true; return m_client.shouldGoToBackForwardListItem(toAPI(page), toAPI(item), m_client.clientInfo); } -void WebLoaderClient::willGoToBackForwardListItem(WebPageProxy* page, WebBackForwardListItem* item) +void WebLoaderClient::willGoToBackForwardListItem(WebPageProxy* page, WebBackForwardListItem* item, APIObject* userData) { if (m_client.willGoToBackForwardListItem) - m_client.willGoToBackForwardListItem(toAPI(page), toAPI(item), m_client.clientInfo); + m_client.willGoToBackForwardListItem(toAPI(page), toAPI(item), toAPI(userData), m_client.clientInfo); } void WebLoaderClient::didFailToInitializePlugin(WebPageProxy* page, const String& mimeType) diff --git a/Source/WebKit2/UIProcess/WebLoaderClient.h b/Source/WebKit2/UIProcess/WebLoaderClient.h index 55cc6aace..3981e2f0d 100644 --- a/Source/WebKit2/UIProcess/WebLoaderClient.h +++ b/Source/WebKit2/UIProcess/WebLoaderClient.h @@ -78,12 +78,13 @@ public: // FIXME: These three functions should not be part of this client. void processDidBecomeUnresponsive(WebPageProxy*); + void interactionOccurredWhileProcessUnresponsive(WebPageProxy*); void processDidBecomeResponsive(WebPageProxy*); void processDidCrash(WebPageProxy*); void didChangeBackForwardList(WebPageProxy*, WebBackForwardListItem* addedItem, Vector<RefPtr<APIObject> >* removedItems); bool shouldGoToBackForwardListItem(WebPageProxy*, WebBackForwardListItem*); - void willGoToBackForwardListItem(WebPageProxy*, WebBackForwardListItem*); + void willGoToBackForwardListItem(WebPageProxy*, WebBackForwardListItem*, APIObject*); void didFailToInitializePlugin(WebPageProxy*, const String& mimeType); }; diff --git a/Source/WebKit2/UIProcess/WebPageContextMenuClient.cpp b/Source/WebKit2/UIProcess/WebPageContextMenuClient.cpp index 3f7d0289f..8a11ebb89 100644 --- a/Source/WebKit2/UIProcess/WebPageContextMenuClient.cpp +++ b/Source/WebKit2/UIProcess/WebPageContextMenuClient.cpp @@ -24,6 +24,9 @@ */ #include "config.h" + +#if ENABLE(CONTEXT_MENUS) + #include "WebPageContextMenuClient.h" #include "Logging.h" @@ -91,3 +94,4 @@ void WebPageContextMenuClient::contextMenuDismissed(WebPageProxy* page) } } // namespace WebKit +#endif // ENABLE(CONTEXT_MENUS) diff --git a/Source/WebKit2/UIProcess/WebPageContextMenuClient.h b/Source/WebKit2/UIProcess/WebPageContextMenuClient.h index 9e738bba4..dff9019c1 100644 --- a/Source/WebKit2/UIProcess/WebPageContextMenuClient.h +++ b/Source/WebKit2/UIProcess/WebPageContextMenuClient.h @@ -26,6 +26,8 @@ #ifndef WebPageContextMenuClient_h #define WebPageContextMenuClient_h +#if ENABLE(CONTEXT_MENUS) + #include "APIClient.h" #include "WebHitTestResult.h" #include "WKPage.h" @@ -46,4 +48,5 @@ public: } // namespace WebKit +#endif // ENABLE(CONTEXT_MENUS) #endif // WebPageContextMenuClient_h diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index 40973449a..043cdb690 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -204,6 +204,9 @@ WebPageProxy::WebPageProxy(PageClient* pageClient, PassRefPtr<WebProcessProxy> p , m_renderTreeSize(0) , m_shouldSendEventsSynchronously(false) , m_mediaVolume(1) +#if ENABLE(PAGE_VISIBILITY_API) + , m_visibilityState(PageVisibilityStateVisible) +#endif { #ifndef NDEBUG webPageProxyCounter.increment(); @@ -294,10 +297,12 @@ void WebPageProxy::initializeFindClient(const WKPageFindClient* client) m_findClient.initialize(client); } +#if ENABLE(CONTEXT_MENUS) void WebPageProxy::initializeContextMenuClient(const WKPageContextMenuClient* client) { m_contextMenuClient.initialize(client); } +#endif void WebPageProxy::reattachToWebProcess() { @@ -339,7 +344,16 @@ void WebPageProxy::initializeWebPage() m_drawingArea = m_pageClient->createDrawingAreaProxy(); ASSERT(m_drawingArea); +#if ENABLE(INSPECTOR_SERVER) + if (m_pageGroup->preferences()->developerExtrasEnabled()) + inspector()->enableRemoteInspection(); +#endif + process()->send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0); + +#if ENABLE(PAGE_VISIBILITY_API) + process()->send(Messages::WebPage::SetVisibilityState(m_visibilityState, /* isInitialState */ true), m_pageID); +#endif } void WebPageProxy::close() @@ -396,6 +410,9 @@ void WebPageProxy::close() m_loadDependentStringCallbackIDs.clear(); invalidateCallbackMap(m_scriptValueCallbacks); invalidateCallbackMap(m_computedPagesCallbacks); +#if PLATFORM(GTK) + invalidateCallbackMap(m_printFinishedCallbacks); +#endif Vector<WebEditCommandProxy*> editCommandVector; copyToVector(m_editCommandSet, editCommandVector); @@ -504,6 +521,15 @@ void WebPageProxy::loadPlainTextString(const String& string) process()->responsivenessTimer()->start(); } +void WebPageProxy::loadWebArchiveData(const WebData* webArchiveData) +{ + if (!isValid()) + reattachToWebProcess(); + + process()->send(Messages::WebPage::LoadWebArchiveData(webArchiveData->dataReference()), m_pageID); + process()->responsivenessTimer()->start(); +} + void WebPageProxy::stopLoading() { if (!isValid()) @@ -618,10 +644,15 @@ void WebPageProxy::shouldGoToBackForwardListItem(uint64_t itemID, bool& shouldGo shouldGoToBackForwardItem = item && m_loaderClient.shouldGoToBackForwardListItem(this, item); } -void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID) +void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID, CoreIPC::ArgumentDecoder* arguments) { + RefPtr<APIObject> userData; + WebContextUserMessageDecoder messageDecoder(userData, m_process->context()); + if (!arguments->decode(messageDecoder)) + return; + if (WebBackForwardListItem* item = process()->webBackForwardItem(itemID)) - m_loaderClient.willGoToBackForwardListItem(this, item); + m_loaderClient.willGoToBackForwardListItem(this, item, userData.get()); } String WebPageProxy::activeURL() const @@ -633,7 +664,8 @@ String WebPageProxy::activeURL() const if (!m_pendingAPIRequestURL.isNull()) return m_pendingAPIRequestURL; - // FIXME: What do we do in the case of the unreachable URL? + if (!m_mainFrame->unreachableURL().isEmpty()) + return m_mainFrame->unreachableURL(); switch (m_mainFrame->loadState()) { case WebFrameProxy::LoadStateProvisional: @@ -765,13 +797,27 @@ void WebPageProxy::viewStateDidChange(ViewStateFlags flags) process()->send(Messages::WebPage::SetIsInWindow(isInWindow), m_pageID); } - LayerHostingMode layerHostingMode = m_pageClient->viewLayerHostingMode(); - if (m_layerHostingMode != layerHostingMode) { - m_layerHostingMode = layerHostingMode; - m_drawingArea->layerHostingModeDidChange(); + if (isInWindow) { + LayerHostingMode layerHostingMode = m_pageClient->viewLayerHostingMode(); + if (m_layerHostingMode != layerHostingMode) { + m_layerHostingMode = layerHostingMode; + m_drawingArea->layerHostingModeDidChange(); + } } } +#if ENABLE(PAGE_VISIBILITY_API) + PageVisibilityState visibilityState = PageVisibilityStateHidden; + + if (m_pageClient->isViewVisible()) + visibilityState = PageVisibilityStateVisible; + + if (visibilityState != m_visibilityState) { + m_visibilityState = visibilityState; + process()->send(Messages::WebPage::SetVisibilityState(visibilityState, false), m_pageID); + } +#endif + updateBackingStoreDiscardableState(); } @@ -831,14 +877,6 @@ void WebPageProxy::executeEditCommand(const String& commandName) } #if USE(TILED_BACKING_STORE) -void WebPageProxy::setFixedVisibleContentRect(const IntRect& rect) -{ - if (!isValid()) - return; - - process()->send(Messages::WebPage::SetFixedVisibleContentRect(rect), m_pageID); -} - void WebPageProxy::setViewportSize(const IntSize& size) { if (!isValid()) @@ -851,27 +889,30 @@ void WebPageProxy::setViewportSize(const IntSize& size) void WebPageProxy::dragEntered(DragData* dragData, const String& dragStorageName) { SandboxExtension::Handle sandboxExtensionHandle; - performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle); + SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray; + performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray); } void WebPageProxy::dragUpdated(DragData* dragData, const String& dragStorageName) { SandboxExtension::Handle sandboxExtensionHandle; - performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle); + SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray; + performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray); } void WebPageProxy::dragExited(DragData* dragData, const String& dragStorageName) { SandboxExtension::Handle sandboxExtensionHandle; - performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle); + SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray; + performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray); } -void WebPageProxy::performDrag(DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle) +void WebPageProxy::performDrag(DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload) { - performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle); + performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionsForUpload); } -void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle) +void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload) { if (!isValid()) return; @@ -882,7 +923,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag #elif PLATFORM(QT) || PLATFORM(GTK) process()->send(Messages::WebPage::PerformDragControllerAction(action, *dragData), m_pageID); #else - process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags(), sandboxExtensionHandle), m_pageID); + process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags(), sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID); #endif } @@ -999,9 +1040,9 @@ void WebPageProxy::handleGestureEvent(const WebGestureEvent& event) #if ENABLE(TOUCH_EVENTS) #if PLATFORM(QT) -void WebPageProxy::handlePotentialActivation(const IntPoint& layoutPoint) +void WebPageProxy::handlePotentialActivation(const IntPoint& touchPoint, const IntSize& touchArea) { - process()->send(Messages::WebPage::HighlightPotentialActivation(layoutPoint), m_pageID); + process()->send(Messages::WebPage::HighlightPotentialActivation(touchPoint, touchArea), m_pageID); } #endif @@ -1276,14 +1317,13 @@ void WebPageProxy::scalePage(double scale, const IntPoint& origin) void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor) { - if (!isValid()) - return; - if (m_intrinsicDeviceScaleFactor == scaleFactor) return; m_intrinsicDeviceScaleFactor = scaleFactor; - m_drawingArea->deviceScaleFactorDidChange(); + + if (m_drawingArea) + m_drawingArea->deviceScaleFactorDidChange(); } void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID) @@ -1561,6 +1601,11 @@ void WebPageProxy::preferencesDidChange() if (!isValid()) return; +#if ENABLE(INSPECTOR_SERVER) + if (m_pageGroup->preferences()->developerExtrasEnabled()) + inspector()->enableRemoteInspection(); +#endif + // FIXME: It probably makes more sense to send individual preference changes. // However, WebKitTestRunner depends on getting a preference change notification // even if nothing changed in UI process, so that overrides get removed. @@ -1802,7 +1847,7 @@ void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeTyp m_pageClient->resetTextInputState(); #if !defined(BUILDING_ON_SNOW_LEOPARD) // FIXME: Should this be moved inside resetTextInputState()? - dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored); + dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored); m_pageClient->dismissDictionaryLookupPanel(); #endif #endif @@ -1813,6 +1858,13 @@ void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, const String& mimeTyp if (frame->isMainFrame()) { m_mainFrameHasCustomRepresentation = frameHasCustomRepresentation; + + if (m_mainFrameHasCustomRepresentation) { + // Always assume that the main frame is pinned here, since the custom representation view will handle + // any wheel events and dispatch them to the WKView when necessary. + m_mainFrameIsPinnedToLeftSide = true; + m_mainFrameIsPinnedToRightSide = true; + } m_pageClient->didCommitLoadForMainFrame(frameHasCustomRepresentation); } @@ -2343,16 +2395,16 @@ void WebPageProxy::pageDidRequestScroll(const IntPoint& point) } #endif -void WebPageProxy::didChangeViewportProperties(const ViewportArguments& args) +void WebPageProxy::didChangeViewportProperties(const ViewportAttributes& attr) { - m_pageClient->didChangeViewportProperties(args); + m_pageClient->didChangeViewportProperties(attr); } void WebPageProxy::pageDidScroll() { m_uiClient.pageDidScroll(this); #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) - dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored); + dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored); #endif } @@ -2386,6 +2438,7 @@ void WebPageProxy::printFrame(uint64_t frameID) m_uiClient.printFrame(this, frame); + endPrinting(); // Send a message synchronously while m_isPerformingDOMPrintOperation is still true. m_isPerformingDOMPrintOperation = false; } @@ -2418,12 +2471,12 @@ void WebPageProxy::didFindZoomableArea(const IntPoint& target, const IntRect& ar m_pageClient->didFindZoomableArea(target, area); } -void WebPageProxy::findZoomableAreaForPoint(const IntPoint& point) +void WebPageProxy::findZoomableAreaForPoint(const IntPoint& point, const IntSize& area) { if (!isValid()) return; - process()->send(Messages::WebPage::FindZoomableAreaForPoint(point), m_pageID); + process()->send(Messages::WebPage::FindZoomableAreaForPoint(point, area), m_pageID); } void WebPageProxy::didReceiveMessageFromNavigatorQtObject(const String& contents) @@ -2638,6 +2691,7 @@ void WebPageProxy::hidePopupMenu() m_activePopupMenu = 0; } +#if ENABLE(CONTEXT_MENUS) void WebPageProxy::showContextMenu(const IntPoint& menuLocation, const WebHitTestResult::Data& hitTestResultData, const Vector<WebContextMenuItemData>& proposedItems, CoreIPC::ArgumentDecoder* arguments) { internalShowContextMenu(menuLocation, hitTestResultData, proposedItems, arguments); @@ -2747,6 +2801,7 @@ void WebPageProxy::contextMenuItemSelected(const WebContextMenuItemData& item) process()->send(Messages::WebPage::DidSelectItemFromActiveContextMenu(item), m_pageID); } +#endif // ENABLE(CONTEXT_MENUS) void WebPageProxy::didChooseFilesForOpenPanel(const Vector<String>& fileURLs) { @@ -3174,6 +3229,20 @@ void WebPageProxy::validateCommandCallback(const String& commandName, bool isEna callback->performCallbackWithReturnValue(commandName.impl(), isEnabled, state); } +#if PLATFORM(GTK) +void WebPageProxy::printFinishedCallback(const ResourceError& printError, uint64_t callbackID) +{ + RefPtr<PrintFinishedCallback> callback = m_printFinishedCallbacks.take(callbackID); + if (!callback) { + // FIXME: Log error or assert. + return; + } + + RefPtr<WebError> error = WebError::create(printError); + callback->performCallbackWithReturnValue(error.get()); +} +#endif + void WebPageProxy::focusedFrameChanged(uint64_t frameID) { if (!frameID) { @@ -3210,6 +3279,14 @@ void WebPageProxy::processDidBecomeUnresponsive() m_loaderClient.processDidBecomeUnresponsive(this); } +void WebPageProxy::interactionOccurredWhileProcessUnresponsive() +{ + if (!isValid()) + return; + + m_loaderClient.interactionOccurredWhileProcessUnresponsive(this); +} + void WebPageProxy::processDidBecomeResponsive() { if (!isValid()) @@ -3277,6 +3354,9 @@ void WebPageProxy::processDidCrash() invalidateCallbackMap(m_scriptValueCallbacks); invalidateCallbackMap(m_computedPagesCallbacks); invalidateCallbackMap(m_validateCommandCallbacks); +#if PLATFORM(GTK) + invalidateCallbackMap(m_printFinishedCallbacks); +#endif Vector<WebEditCommandProxy*> editCommandVector; copyToVector(m_editCommandSet, editCommandVector); @@ -3319,7 +3399,7 @@ void WebPageProxy::processDidCrash() #endif #if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) - dismissCorrectionPanel(ReasonForDismissingCorrectionPanelIgnored); + dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored); m_pageClient->dismissDictionaryLookupPanel(); #endif } @@ -3440,9 +3520,9 @@ void WebPageProxy::requestNotificationPermission(uint64_t requestID, const Strin request->deny(); } -void WebPageProxy::showNotification(const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID) +void WebPageProxy::showNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID) { - m_process->context()->notificationManagerProxy()->show(this, title, body, iconURL, replaceID, originString, notificationID); + m_process->context()->notificationManagerProxy()->show(this, title, body, iconURL, tag, originString, notificationID); } float WebPageProxy::headerHeight(WebFrameProxy* frame) @@ -3591,16 +3671,16 @@ void WebPageProxy::drawPagesToPDF(WebFrameProxy* frame, const PrintInfo& printIn 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) +void WebPageProxy::drawPagesForPrinting(WebFrameProxy* frame, const PrintInfo& printInfo, PassRefPtr<PrintFinishedCallback> didPrintCallback) { - RefPtr<VoidCallback> callback = didPrintCallback; + RefPtr<PrintFinishedCallback> callback = didPrintCallback; if (!isValid()) { callback->invalidate(); return; } uint64_t callbackID = callback->callbackID(); - m_voidCallbacks.set(callbackID, callback.get()); + m_printFinishedCallbacks.set(callbackID, callback.get()); m_isInPrintingMode = true; process()->send(Messages::WebPage::DrawPagesForPrinting(frame->frameID(), printInfo, callbackID), m_pageID, m_isPerformingDOMPrintOperation ? CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply : 0); } @@ -3655,30 +3735,30 @@ void WebPageProxy::substitutionsPanelIsShowing(bool& isShowing) #if !defined(BUILDING_ON_SNOW_LEOPARD) void WebPageProxy::showCorrectionPanel(int32_t panelType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) { - m_pageClient->showCorrectionPanel((CorrectionPanelInfo::PanelType)panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings); + m_pageClient->showCorrectionPanel((AlternativeTextType)panelType, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings); } void WebPageProxy::dismissCorrectionPanel(int32_t reason) { - m_pageClient->dismissCorrectionPanel((ReasonForDismissingCorrectionPanel)reason); + m_pageClient->dismissCorrectionPanel((ReasonForDismissingAlternativeText)reason); } void WebPageProxy::dismissCorrectionPanelSoon(int32_t reason, String& result) { - result = m_pageClient->dismissCorrectionPanelSoon((ReasonForDismissingCorrectionPanel)reason); + result = m_pageClient->dismissCorrectionPanelSoon((ReasonForDismissingAlternativeText)reason); } void WebPageProxy::recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString) { - m_pageClient->recordAutocorrectionResponse((EditorClient::AutocorrectionResponseType)responseType, replacedString, replacementString); + m_pageClient->recordAutocorrectionResponse((AutocorrectionResponseType)responseType, replacedString, replacementString); } #endif // !defined(BUILDING_ON_SNOW_LEOPARD) -void WebPageProxy::handleCorrectionPanelResult(const String& result) +void WebPageProxy::handleAlternativeTextUIResult(const String& result) { #if !defined(BUILDING_ON_SNOW_LEOPARD) if (!isClosed()) - process()->send(Messages::WebPage::HandleCorrectionPanelResult(result), m_pageID, 0); + process()->send(Messages::WebPage::HandleAlternativeTextUIResult(result), m_pageID, 0); #endif } #endif // PLATFORM(MAC) diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index 5049228e2..a3e9bb8f7 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -92,7 +92,7 @@ namespace WebCore { class ProtectionSpace; struct FileChooserSettings; struct TextCheckingResult; - struct ViewportArguments; + struct ViewportAttributes; struct WindowFeatures; } @@ -154,6 +154,10 @@ class WebGestureEvent; typedef GenericCallback<WKStringRef, StringImpl*> StringCallback; typedef GenericCallback<WKSerializedScriptValueRef, WebSerializedScriptValue*> ScriptValueCallback; +#if PLATFORM(GTK) +typedef GenericCallback<WKErrorRef> PrintFinishedCallback; +#endif + #if ENABLE(TOUCH_EVENTS) struct QueuedTouchEvents { QueuedTouchEvents(const NativeWebTouchEvent& event) @@ -235,7 +239,9 @@ public: WebFullScreenManagerProxy* fullScreenManager(); #endif +#if ENABLE(CONTEXT_MENUS) void initializeContextMenuClient(const WKPageContextMenuClient*); +#endif void initializeFindClient(const WKPageFindClient*); void initializeFormClient(const WKPageFormClient*); void initializeLoaderClient(const WKPageLoaderClient*); @@ -254,6 +260,7 @@ public: void loadHTMLString(const String& htmlString, const String& baseURL); void loadAlternateHTMLString(const String& htmlString, const String& baseURL, const String& unreachableURL); void loadPlainTextString(const String& string); + void loadWebArchiveData(const WebData*); void stopLoading(); void reload(bool reloadFromOrigin); @@ -267,7 +274,7 @@ public: void tryRestoreScrollPosition(); void didChangeBackForwardList(WebBackForwardListItem* addedItem, Vector<RefPtr<APIObject> >* removedItems); void shouldGoToBackForwardListItem(uint64_t itemID, bool& shouldGoToBackForwardListItem); - void willGoToBackForwardListItem(uint64_t itemID); + void willGoToBackForwardListItem(uint64_t itemID, CoreIPC::ArgumentDecoder* arguments); String activeURL() const; String provisionalURL() const; @@ -373,7 +380,6 @@ public: PlatformWidget viewWidget(); #endif #if USE(TILED_BACKING_STORE) - void setFixedVisibleContentRect(const WebCore::IntRect&); void setViewportSize(const WebCore::IntSize&); #endif @@ -386,7 +392,7 @@ public: #if ENABLE(TOUCH_EVENTS) void handleTouchEvent(const NativeWebTouchEvent&); #if PLATFORM(QT) - void handlePotentialActivation(const WebCore::IntPoint&); + void handlePotentialActivation(const WebCore::IntPoint& touchPoint, const WebCore::IntSize& touchArea); #endif #endif @@ -462,8 +468,9 @@ public: void registerWebProcessAccessibilityToken(const CoreIPC::DataReference&); // Called by the UI process when it is ready to send its tokens to the web process. void registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elemenToken, const CoreIPC::DataReference& windowToken); - bool writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes); bool readSelectionFromPasteboard(const String& pasteboardName); + String stringSelectionForPasteboard(); + PassRefPtr<WebCore::SharedBuffer> dataSelectionForPasteboard(const String& pasteboardType); void makeFirstResponder(); #endif @@ -511,12 +518,14 @@ public: void dragEntered(WebCore::DragData*, const String& dragStorageName = String()); void dragUpdated(WebCore::DragData*, const String& dragStorageName = String()); void dragExited(WebCore::DragData*, const String& dragStorageName = String()); - void performDrag(WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&); + void performDrag(WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&, const SandboxExtension::HandleArray&); void didPerformDragControllerAction(WebCore::DragSession); void dragEnded(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t operation); #if PLATFORM(MAC) void setDragImage(const WebCore::IntPoint& clientPosition, const ShareableBitmap::Handle& dragImageHandle, bool isLinkDrag); + void setPromisedData(const String& pasteboardName, const SharedMemory::Handle& imageHandle, uint64_t imageSize, const String& filename, const String& extension, + const String& title, const String& url, const String& visibleURL, const SharedMemory::Handle& archiveHandle, uint64_t archiveSize); #endif #if PLATFORM(WIN) void startDragDrop(const WebCore::IntPoint& imagePoint, const WebCore::IntPoint& dragPoint, uint64_t okEffect, const HashMap<UINT, Vector<String> >& dataMap, uint64_t fileSize, const String& pathname, const SharedMemory::Handle& fileContentHandle, const WebCore::IntSize& dragImageSize, const SharedMemory::Handle& dragImageHandle, bool isLinkDrag); @@ -528,6 +537,7 @@ public: void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&); void processDidBecomeUnresponsive(); + void interactionOccurredWhileProcessUnresponsive(); void processDidBecomeResponsive(); void processDidCrash(); @@ -545,6 +555,11 @@ public: bool isValidEditCommand(WebEditCommandProxy*); void registerEditCommand(PassRefPtr<WebEditCommandProxy>, UndoOrRedo); +#if PLATFORM(MAC) + void registerKeypressCommandName(const String& name) { m_knownKeypressCommandNames.add(name); } + bool isValidKeypressCommandName(const String& name) const { return m_knownKeypressCommandNames.contains(name); } +#endif + WebProcessProxy* process() const; PlatformProcessIdentifier processIdentifier() const; @@ -560,8 +575,10 @@ public: void preferencesDidChange(); +#if ENABLE(CONTEXT_MENUS) // Called by the WebContextMenuProxy. void contextMenuItemSelected(const WebContextMenuItemData&); +#endif // Called by the WebOpenPanelResultListenerProxy. void didChooseFilesForOpenPanel(const Vector<String>&); @@ -570,7 +587,7 @@ public: WebPageCreationParameters creationParameters() const; #if PLATFORM(QT) - void findZoomableAreaForPoint(const WebCore::IntPoint&); + void findZoomableAreaForPoint(const WebCore::IntPoint&, const WebCore::IntSize&); void didReceiveMessageFromNavigatorQtObject(const String&); void handleDownloadRequest(DownloadProxy*); #endif @@ -597,7 +614,7 @@ public: 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>); + void drawPagesForPrinting(WebFrameProxy*, const PrintInfo&, PassRefPtr<PrintFinishedCallback>); #endif const String& pendingAPIRequestURL() const { return m_pendingAPIRequestURL; } @@ -605,7 +622,7 @@ public: void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects); #if PLATFORM(MAC) - void handleCorrectionPanelResult(const String& result); + void handleAlternativeTextUIResult(const String& result); #endif static void setDebugPaintFlags(WKPageDebugPaintFlags flags) { s_debugPaintFlags = flags; } @@ -715,7 +732,7 @@ private: void screenToWindow(const WebCore::IntPoint& screenPoint, WebCore::IntPoint& windowPoint); void windowToScreen(const WebCore::IntRect& viewRect, WebCore::IntRect& result); void runBeforeUnloadConfirmPanel(const String& message, uint64_t frameID, bool& shouldClose); - void didChangeViewportProperties(const WebCore::ViewportArguments&); + void didChangeViewportProperties(const WebCore::ViewportAttributes&); void pageDidScroll(); void runOpenPanel(uint64_t frameID, const WebCore::FileChooserSettings&); void printFrame(uint64_t frameID); @@ -734,7 +751,7 @@ private: void reattachToWebProcessWithItem(WebBackForwardListItem*); void requestNotificationPermission(uint64_t notificationID, const String& originString); - void showNotification(const String& title, const String& body, const String& iconURL, const String& replaceID, const String& originString, uint64_t notificationID); + void showNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& originString, uint64_t notificationID); #if USE(TILED_BACKING_STORE) void pageDidRequestScroll(const WebCore::IntPoint&); @@ -785,9 +802,11 @@ private: void setPopupMenuSelectedIndex(int32_t); #endif +#if ENABLE(CONTEXT_MENUS) // Context Menu. void showContextMenu(const WebCore::IntPoint& menuLocation, const WebHitTestResult::Data&, const Vector<WebContextMenuItemData>&, CoreIPC::ArgumentDecoder*); void internalShowContextMenu(const WebCore::IntPoint& menuLocation, const WebHitTestResult::Data&, const Vector<WebContextMenuItemData>&, CoreIPC::ArgumentDecoder*); +#endif // Search popup results void saveRecentSearches(const String&, const Vector<String>&); @@ -835,6 +854,9 @@ private: void scriptValueCallback(const CoreIPC::DataReference&, uint64_t); void computedPagesCallback(const Vector<WebCore::IntRect>&, double totalScaleFactorForPrinting, uint64_t); void validateCommandCallback(const String&, bool, int, uint64_t); +#if PLATFORM(GTK) + void printFinishedCallback(const WebCore::ResourceError&, uint64_t); +#endif void focusedFrameChanged(uint64_t frameID); void frameSetLargestFrameChanged(uint64_t frameID); @@ -866,7 +888,7 @@ private: void clearLoadDependentCallbacks(); - void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&); + void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&, const SandboxExtension::HandleArray&); void updateBackingStoreDiscardableState(); @@ -876,6 +898,11 @@ private: void setRenderTreeSize(uint64_t treeSize) { m_renderTreeSize = treeSize; } +#if PLUGIN_ARCHITECTURE(X11) + void createPluginContainer(uint64_t& windowID); + void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID); +#endif + PageClient* m_pageClient; WebLoaderClient m_loaderClient; WebPolicyClient m_policyClient; @@ -883,7 +910,9 @@ private: WebResourceLoadClient m_resourceLoadClient; WebUIClient m_uiClient; WebFindClient m_findClient; +#if ENABLE(CONTEXT_MENUS) WebPageContextMenuClient m_contextMenuClient; +#endif OwnPtr<DrawingAreaProxy> m_drawingArea; RefPtr<WebProcessProxy> m_process; @@ -912,9 +941,16 @@ private: HashMap<uint64_t, RefPtr<ScriptValueCallback> > m_scriptValueCallbacks; HashMap<uint64_t, RefPtr<ComputedPagesCallback> > m_computedPagesCallbacks; HashMap<uint64_t, RefPtr<ValidateCommandCallback> > m_validateCommandCallbacks; +#if PLATFORM(GTK) + HashMap<uint64_t, RefPtr<PrintFinishedCallback> > m_printFinishedCallbacks; +#endif HashSet<WebEditCommandProxy*> m_editCommandSet; +#if PLATFORM(MAC) + HashSet<String> m_knownKeypressCommandNames; +#endif + RefPtr<WebPopupMenuProxy> m_activePopupMenu; RefPtr<WebContextMenuProxy> m_activeContextMenu; WebHitTestResult::Data m_activeContextMenuHitTestResultData; @@ -1044,6 +1080,10 @@ private: #if PLATFORM(QT) WTF::HashSet<RefPtr<QtRefCountedNetworkRequestData> > m_applicationSchemeRequests; #endif + +#if ENABLE(PAGE_VISIBILITY_API) + WebCore::PageVisibilityState m_visibilityState; +#endif }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in index 347aa933d..400aced5d 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in @@ -31,7 +31,7 @@ messages -> WebPageProxy { ShouldInterruptJavaScript() -> (bool shouldInterupt) MouseDidMoveOverElement(WebKit::WebHitTestResult::Data hitTestResultData, uint32_t modifiers, WebKit::InjectedBundleUserMessageEncoder userData); MissingPluginButtonClicked(WTF::String mimeType, WTF::String url, WTF::String pluginsPageURL) - DidChangeViewportProperties(WebCore::ViewportArguments arguments) + DidChangeViewportProperties(WebCore::ViewportAttributes attributes) DidReceiveEvent(uint32_t type, bool handled) StopResponsivenessTimer() SetCursor(WebCore::Cursor cursor) @@ -144,6 +144,9 @@ messages -> WebPageProxy { ScriptValueCallback(CoreIPC::DataReference resultData, uint64_t callbackID) ComputedPagesCallback(Vector<WebCore::IntRect> pageRects, double totalScaleFactorForPrinting, uint64_t callbackID) ValidateCommandCallback(WTF::String command, bool isEnabled, int32_t state, uint64_t callbackID) +#if PLATFORM(GTK) + PrintFinishedCallback(WebCore::ResourceError error, uint64_t callbackID) +#endif PageScaleFactorDidChange(double scaleFactor) @@ -163,7 +166,7 @@ messages -> WebPageProxy { BackForwardForwardListCount() -> (int32_t count) BackForwardClear() ShouldGoToBackForwardListItem(uint64_t itemID) -> (bool shouldGoToBackForwardListItem) - WillGoToBackForwardListItem(uint64_t itemID) + WillGoToBackForwardListItem(uint64_t itemID, WebKit::InjectedBundleUserMessageEncoder userData) # Undo/Redo messages RegisterEditCommandForUndo(uint64_t commandID, uint32_t editAction) @@ -193,8 +196,10 @@ messages -> WebPageProxy { SetPopupMenuSelectedIndex(int32_t selectedIndex) #endif +#if ENABLE(CONTEXT_MENUS) # ContextMenu messages ShowContextMenu(WebCore::IntPoint menuLocation, WebKit::WebHitTestResult::Data hitTestResultData, Vector<WebKit::WebContextMenuItemData> items, WebKit::InjectedBundleUserMessageEncoder userData) +#endif # Authentication messages CanAuthenticateAgainstProtectionSpaceInFrame(uint64_t frameID, WebCore::ProtectionSpace protectionSpace) -> (bool canAuthenticate) @@ -208,7 +213,7 @@ messages -> WebPageProxy { # Notification messages RequestNotificationPermission(uint64_t requestID, WTF::String originIdentifier) - ShowNotification(WTF::String title, WTF::String body, WTF::String iconURL, WTF::String replaceID, WTF::String originIdentifier, uint64_t notificationID) + ShowNotification(WTF::String title, WTF::String body, WTF::String iconURL, WTF::String tag, WTF::String originIdentifier, uint64_t notificationID) # Spelling and grammar messages #if USE(UNIFIED_TEXT_CHECKING) @@ -227,6 +232,7 @@ messages -> WebPageProxy { DidPerformDragControllerAction(WebCore::DragSession dragSession) #if PLATFORM(MAC) SetDragImage(WebCore::IntPoint clientPosition, WebKit::ShareableBitmap::Handle dragImage, bool linkDrag) + SetPromisedData(WTF::String pasteboardName, WebKit::SharedMemory::Handle imageHandle, uint64_t imageSize, WTF::String filename, WTF::String extension, WTF::String title, WTF::String url, WTF::String visibleURL, WebKit::SharedMemory::Handle archiveHandle, uint64_t archiveSize) #endif #if PLATFORM(WIN) StartDragDrop(WebCore::IntPoint imagePoint, WebCore::IntPoint dragPoint, uint64_t okEffect, HashMap<UINT,Vector<String> > dataMap, uint64_t fileSize, String pathname, WebKit::SharedMemory::Handle fileContentHandle, WebCore::IntSize dragImageSize, WebKit::SharedMemory::Handle dragImage, bool linkDrag) @@ -280,6 +286,12 @@ messages -> WebPageProxy { ScheduleChildWindowGeometryUpdate(WebKit::WindowGeometry geometry) #endif +#if PLUGIN_ARCHITECTURE(X11) + # X11 windowed plugin messages + CreatePluginContainer() -> (uint64_t windowID) + WindowedPluginGeometryDidChange(WebCore::IntRect frameRect, WebCore::IntRect clipRect, uint64_t windowID) +#endif + # Search popup menus SaveRecentSearches(WTF::String name, Vector<String> searchItems) LoadRecentSearches(WTF::String name) -> (Vector<String> result) diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.cpp b/Source/WebKit2/UIProcess/WebProcessProxy.cpp index 9ce54407e..455df4d9b 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit2/UIProcess/WebProcessProxy.cpp @@ -255,7 +255,7 @@ bool WebProcessProxy::checkURLReceivedFromWebProcess(const KURL& url) } // A Web process that was never asked to load a file URL should not ever ask us to do anything with a file URL. - fprintf(stderr, "Received an unexpected URL from the web process: '%s'\n", url.string().utf8().data()); + WTFLogAlways("Received an unexpected URL from the web process: '%s'\n", url.string().utf8().data()); return false; } @@ -271,18 +271,17 @@ void WebProcessProxy::addBackForwardItem(uint64_t itemID, const String& original MESSAGE_CHECK_URL(originalURL); MESSAGE_CHECK_URL(url); - std::pair<WebBackForwardListItemMap::iterator, bool> result = m_backForwardListItemMap.add(itemID, 0); - if (result.second) { - // New item. - result.first->second = WebBackForwardListItem::create(originalURL, url, title, backForwardData.data(), backForwardData.size(), itemID); + WebBackForwardListItemMap::AddResult result = m_backForwardListItemMap.add(itemID, 0); + if (result.isNewEntry) { + result.iterator->second = WebBackForwardListItem::create(originalURL, url, title, backForwardData.data(), backForwardData.size(), itemID); return; } // Update existing item. - result.first->second->setOriginalURL(originalURL); - result.first->second->setURL(url); - result.first->second->setTitle(title); - result.first->second->setBackForwardData(backForwardData.data(), backForwardData.size()); + result.iterator->second->setOriginalURL(originalURL); + result.iterator->second->setURL(url); + result.iterator->second->setTitle(title); + result.iterator->second->setBackForwardData(backForwardData.data(), backForwardData.size()); } #if ENABLE(PLUGIN_PROCESS) @@ -315,6 +314,9 @@ void WebProcessProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC || messageID.is<CoreIPC::MessageClassWebKeyValueStorageManagerProxy>() || messageID.is<CoreIPC::MessageClassWebMediaCacheManagerProxy>() || messageID.is<CoreIPC::MessageClassWebNotificationManagerProxy>() +#if USE(SOUP) + || messageID.is<CoreIPC::MessageClassWebSoupRequestManagerProxy>() +#endif || messageID.is<CoreIPC::MessageClassWebResourceCacheManagerProxy>()) { m_context->didReceiveMessage(connection, messageID, arguments); return; @@ -378,7 +380,7 @@ void WebProcessProxy::didClose(CoreIPC::Connection*) void WebProcessProxy::didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID) { - fprintf(stderr, "Received an invalid message from the web process with message ID %x\n", messageID.toInt()); + WTFLogAlways("Received an invalid message from the web process with message ID %x\n", messageID.toInt()); // Terminate the WebProcesses. terminate(); @@ -396,6 +398,14 @@ void WebProcessProxy::didBecomeUnresponsive(ResponsivenessTimer*) pages[i]->processDidBecomeUnresponsive(); } +void WebProcessProxy::interactionOccurredWhileUnresponsive(ResponsivenessTimer*) +{ + Vector<RefPtr<WebPageProxy> > pages; + copyValuesToVector(m_pageMap, pages); + for (size_t i = 0, size = pages.size(); i < size; ++i) + pages[i]->interactionOccurredWhileProcessUnresponsive(); +} + void WebProcessProxy::didBecomeResponsive(ResponsivenessTimer*) { Vector<RefPtr<WebPageProxy> > pages; diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.h b/Source/WebKit2/UIProcess/WebProcessProxy.h index 11cfa5b27..0cc1c6168 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.h +++ b/Source/WebKit2/UIProcess/WebProcessProxy.h @@ -158,8 +158,9 @@ private: virtual void didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, bool& didHandleMessage); // ResponsivenessTimer::Client - void didBecomeUnresponsive(ResponsivenessTimer*); - void didBecomeResponsive(ResponsivenessTimer*); + void didBecomeUnresponsive(ResponsivenessTimer*) OVERRIDE; + void interactionOccurredWhileUnresponsive(ResponsivenessTimer*) OVERRIDE; + void didBecomeResponsive(ResponsivenessTimer*) OVERRIDE; // ProcessLauncher::Client virtual void didFinishLaunching(ProcessLauncher*, CoreIPC::Connection::Identifier); diff --git a/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp b/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp new file mode 100644 index 000000000..b295687c1 --- /dev/null +++ b/Source/WebKit2/UIProcess/efl/WebFullScreenManagerProxyEfl.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT HOLDER OR + * 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. + */ + +#include "config.h" +#include "WebFullScreenManagerProxy.h" + +#if ENABLE(FULLSCREEN_API) + +#include <WebCore/NotImplemented.h> + +using namespace WebCore; + +namespace WebKit { + +void WebFullScreenManagerProxy::invalidate() +{ + m_webView = 0; +} + +void WebFullScreenManagerProxy::close() +{ + notImplemented(); +} + +bool WebFullScreenManagerProxy::isFullScreen() +{ + notImplemented(); + return false; +} + +void WebFullScreenManagerProxy::enterFullScreen() +{ + notImplemented(); +} + +void WebFullScreenManagerProxy::exitFullScreen() +{ + notImplemented(); +} + +void WebFullScreenManagerProxy::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame) +{ + notImplemented(); +} + +void WebFullScreenManagerProxy::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame) +{ + notImplemented(); +} + +} // namespace WebKit + +#endif // ENABLE(FULLSCREEN_API) diff --git a/Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.cpp new file mode 100644 index 000000000..ba22485e1 --- /dev/null +++ b/Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 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. + */ + +#include "config.h" +#include "WebFullScreenClientGtk.h" + +#include "WKAPICast.h" +#include "WKSharedAPICast.h" + +namespace WebKit { + +bool WebFullScreenClientGtk::willEnterFullScreen() +{ + if (!m_client.willEnterFullScreen) + return true; + + return m_client.willEnterFullScreen(m_client.clientInfo); +} + +bool WebFullScreenClientGtk::willExitFullScreen() +{ + if (!m_client.willExitFullScreen) + return true; + + return m_client.willExitFullScreen(m_client.clientInfo); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.h b/Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.h new file mode 100644 index 000000000..f39376449 --- /dev/null +++ b/Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 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 WebFullScreenClientGtk_h +#define WebFullScreenClientGtk_h + +#include "APIClient.h" +#include "WKFullScreenClientGtk.h" + +namespace WebKit { + +class APIObject; + +class WebFullScreenClientGtk : public APIClient<WKFullScreenClientGtk, kWKFullScreenClientGtkCurrentVersion> { +public: + bool willEnterFullScreen(); + bool willExitFullScreen(); +}; + +} // namespace WebKit + +#endif // WebFullScreenClientGtk_h diff --git a/Source/WebKit2/UIProcess/gtk/WebFullScreenManagerProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebFullScreenManagerProxyGtk.cpp index a136008cd..16147dccf 100644 --- a/Source/WebKit2/UIProcess/gtk/WebFullScreenManagerProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebFullScreenManagerProxyGtk.cpp @@ -25,8 +25,8 @@ #include "WebContext.h" #include "WebFullScreenManagerMessages.h" #include "WebFullScreenManagerProxyMessages.h" +#include "WebKitWebViewBasePrivate.h" #include "WebProcess.h" - #include <WebCore/NotImplemented.h> using namespace WebCore; @@ -38,14 +38,31 @@ void WebFullScreenManagerProxy::invalidate() m_webView = 0; } -void WebFullScreenManagerProxy::enterFullScreen() +void WebFullScreenManagerProxy::close() { notImplemented(); } -void WebFullScreenManagerProxy::exitFullScreen() +bool WebFullScreenManagerProxy::isFullScreen() { notImplemented(); + return false; +} + +void WebFullScreenManagerProxy::enterFullScreen() +{ + if (!m_webView) + return; + + webkitWebViewBaseEnterFullScreen(m_webView); +} + +void WebFullScreenManagerProxy::exitFullScreen() +{ + if (!m_webView) + return; + + webkitWebViewBaseExitFullScreen(m_webView); } void WebFullScreenManagerProxy::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame) diff --git a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp index f6b300eb7..dc8235210 100644 --- a/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp @@ -30,6 +30,8 @@ #include "NativeWebKeyboardEvent.h" #include "NotImplemented.h" #include "PageClientImpl.h" +#include "WebKitWebViewBasePrivate.h" +#include <gtk/gtkx.h> namespace WebKit { @@ -64,4 +66,45 @@ void WebPageProxy::loadRecentSearches(const String&, Vector<String>&) notImplemented(); } +typedef HashMap<uint64_t, GtkWidget* > PluginWindowMap; +static PluginWindowMap& pluginWindowMap() +{ + DEFINE_STATIC_LOCAL(PluginWindowMap, map, ()); + return map; +} + +static gboolean pluginContainerPlugRemoved(GtkSocket* socket) +{ + uint64_t windowID = static_cast<uint64_t>(gtk_socket_get_id(socket)); + pluginWindowMap().remove(windowID); + return FALSE; +} + +void WebPageProxy::createPluginContainer(uint64_t& windowID) +{ + GtkWidget* socket = gtk_socket_new(); + g_signal_connect(socket, "plug-removed", G_CALLBACK(pluginContainerPlugRemoved), 0); + gtk_container_add(GTK_CONTAINER(viewWidget()), socket); + gtk_widget_show(socket); + + windowID = static_cast<uint64_t>(gtk_socket_get_id(GTK_SOCKET(socket))); + pluginWindowMap().set(windowID, socket); +} + +void WebPageProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) +{ + GtkWidget* plugin = pluginWindowMap().get(windowID); + if (!plugin) + return; + + if (gtk_widget_get_realized(plugin)) { + GdkRectangle clip = clipRect; + cairo_region_t* clipRegion = cairo_region_create_rectangle(&clip); + gdk_window_shape_combine_region(gtk_widget_get_window(plugin), clipRegion, 0, 0); + cairo_region_destroy(clipRegion); + } + + webkitWebViewBaseChildMoveResize(WEBKIT_WEB_VIEW_BASE(viewWidget()), plugin, frameRect); +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/mac/BackingStoreMac.mm b/Source/WebKit2/UIProcess/mac/BackingStoreMac.mm index 9ec30b216..40f2c2ae7 100644 --- a/Source/WebKit2/UIProcess/mac/BackingStoreMac.mm +++ b/Source/WebKit2/UIProcess/mac/BackingStoreMac.mm @@ -97,8 +97,13 @@ void BackingStore::resetScrolledRect() return; } + IntSize scaledSize = m_scrolledRect.size(); + scaledSize.scale(m_deviceScaleFactor); + RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, m_scrolledRect.size().width(), m_scrolledRect.size().height(), 8, m_scrolledRect.size().width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); + RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, scaledSize.width(), scaledSize.height(), 8, scaledSize.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); + + CGContextScaleCTM(context.get(), m_deviceScaleFactor, m_deviceScaleFactor); CGContextTranslateCTM(context.get(), -m_scrolledRect.location().x(), -m_scrolledRect.location().y()); CGContextTranslateCTM(context.get(), 0, m_scrolledRect.size().height()); @@ -106,7 +111,7 @@ void BackingStore::resetScrolledRect() paint(context.get(), m_scrolledRect); IntRect sourceRect(IntPoint(), m_scrolledRect.size()); - paintBitmapContext(backingStoreContext(), context.get(), m_scrolledRect.location(), sourceRect); + paintBitmapContext(backingStoreContext(), context.get(), m_deviceScaleFactor, m_scrolledRect.location(), sourceRect); m_scrolledRect = IntRect(); m_scrolledRectOffset = IntSize(); @@ -132,7 +137,7 @@ void BackingStore::paint(PlatformGraphicsContext context, const IntRect& rect) source = part; source.origin.x += offset.width(); source.origin.y += offset.height(); - paintBitmapContext(context, m_bitmapContext.get(), part.location(), source); + paintBitmapContext(context, m_bitmapContext.get(), m_deviceScaleFactor, part.location(), source); }); } @@ -154,7 +159,7 @@ CGContextRef BackingStore::backingStoreContext() if (m_bitmapContext) { // Paint the contents of the bitmap into the layer context. - paintBitmapContext(layerContext, m_bitmapContext.get(), CGPointZero, CGRectMake(0, 0, m_size.width(), m_size.height())); + paintBitmapContext(layerContext, m_bitmapContext.get(), m_deviceScaleFactor, CGPointZero, CGRectMake(0, 0, m_size.width(), m_size.height())); m_bitmapContext = nullptr; } @@ -163,11 +168,15 @@ CGContextRef BackingStore::backingStoreContext() if (!m_bitmapContext) { RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - - m_bitmapContext.adoptCF(CGBitmapContextCreate(0, m_size.width(), m_size.height(), 8, m_size.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); + + IntSize scaledSize(m_size); + scaledSize.scale(m_deviceScaleFactor); + m_bitmapContext.adoptCF(CGBitmapContextCreate(0, scaledSize.width(), scaledSize.height(), 8, scaledSize.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); CGContextSetBlendMode(m_bitmapContext.get(), kCGBlendModeCopy); + CGContextScaleCTM(m_bitmapContext.get(), m_deviceScaleFactor, m_deviceScaleFactor); + // We want the origin to be in the top left corner so flip the backing store context. CGContextTranslateCTM(m_bitmapContext.get(), 0, m_size.height()); CGContextScaleCTM(m_bitmapContext.get(), 1, -1); diff --git a/Source/WebKit2/UIProcess/mac/CorrectionPanel.h b/Source/WebKit2/UIProcess/mac/CorrectionPanel.h index 66793a974..9fcfcca4c 100644 --- a/Source/WebKit2/UIProcess/mac/CorrectionPanel.h +++ b/Source/WebKit2/UIProcess/mac/CorrectionPanel.h @@ -26,11 +26,12 @@ #ifndef CorrectionPanel_h #define CorrectionPanel_h -#if !defined(BUILDING_ON_SNOW_LEOPARD) #import <AppKit/NSSpellChecker.h> -#import <WebCore/SpellingCorrectionController.h> +#import <WebCore/AlternativeTextClient.h> #import <wtf/RetainPtr.h> +#if USE(AUTOCORRECTION_PANEL) + @class WKView; namespace WebKit { @@ -39,23 +40,23 @@ class CorrectionPanel { public: CorrectionPanel(); ~CorrectionPanel(); - void show(WKView*, WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); - String dismiss(WebCore::ReasonForDismissingCorrectionPanel); + void show(WKView*, WebCore::AlternativeTextType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); + String dismiss(WebCore::ReasonForDismissingAlternativeText); static void recordAutocorrectionResponse(WKView*, NSCorrectionResponse, const String& replacedString, const String& replacementString); private: bool isShowing() const { return m_view; } - String dismissInternal(WebCore::ReasonForDismissingCorrectionPanel, bool dismissingExternally); + String dismissInternal(WebCore::ReasonForDismissingAlternativeText, bool dismissingExternally); void handleAcceptedReplacement(NSString* acceptedReplacement, NSString* replaced, NSString* proposedReplacement, NSCorrectionIndicatorType); bool m_wasDismissedExternally; - WebCore::ReasonForDismissingCorrectionPanel m_reasonForDismissing; + WebCore::ReasonForDismissingAlternativeText m_reasonForDismissing; RetainPtr<WKView> m_view; RetainPtr<NSString> m_resultForDismissal; }; } // namespace WebKit -#endif // !defined(BUILDING_ON_SNOW_LEOPARD) +#endif // USE(AUTOCORRECTION_PANEL) #endif // CorrectionPanel_h diff --git a/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm b/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm index 86dd16a56..94171f737 100644 --- a/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm +++ b/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm @@ -24,23 +24,23 @@ */ #import "config.h" -#if !defined(BUILDING_ON_SNOW_LEOPARD) #import "CorrectionPanel.h" +#if !defined(BUILDING_ON_SNOW_LEOPARD) #import "WebPageProxy.h" #import "WKView.h" #import "WKViewInternal.h" using namespace WebCore; -static inline NSCorrectionIndicatorType correctionIndicatorType(CorrectionPanelInfo::PanelType panelType) +static inline NSCorrectionIndicatorType correctionIndicatorType(AlternativeTextType alternativeTextType) { - switch (panelType) { - case CorrectionPanelInfo::PanelTypeCorrection: + switch (alternativeTextType) { + case AlternativeTextTypeCorrection: return NSCorrectionIndicatorTypeDefault; - case CorrectionPanelInfo::PanelTypeReversion: + case AlternativeTextTypeReversion: return NSCorrectionIndicatorTypeReversion; - case CorrectionPanelInfo::PanelTypeSpellingSuggestions: + case AlternativeTextTypeSpellingSuggestions: return NSCorrectionIndicatorTypeGuesses; } ASSERT_NOT_REACHED(); @@ -51,18 +51,18 @@ namespace WebKit { CorrectionPanel::CorrectionPanel() : m_wasDismissedExternally(false) - , m_reasonForDismissing(ReasonForDismissingCorrectionPanelIgnored) + , m_reasonForDismissing(ReasonForDismissingAlternativeTextIgnored) { } CorrectionPanel::~CorrectionPanel() { - dismissInternal(ReasonForDismissingCorrectionPanelIgnored, false); + dismissInternal(ReasonForDismissingAlternativeTextIgnored, false); } -void CorrectionPanel::show(WKView* view, CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) +void CorrectionPanel::show(WKView* view, AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) { - dismissInternal(ReasonForDismissingCorrectionPanelIgnored, false); + dismissInternal(ReasonForDismissingAlternativeTextIgnored, false); if (!view) return; @@ -86,12 +86,12 @@ void CorrectionPanel::show(WKView* view, CorrectionPanelInfo::PanelType type, co }]; } -String CorrectionPanel::dismiss(ReasonForDismissingCorrectionPanel reason) +String CorrectionPanel::dismiss(ReasonForDismissingAlternativeText reason) { return dismissInternal(reason, true); } -String CorrectionPanel::dismissInternal(ReasonForDismissingCorrectionPanel reason, bool dismissingExternally) +String CorrectionPanel::dismissInternal(ReasonForDismissingAlternativeText reason, bool dismissingExternally) { if (!isShowing()) return String(); @@ -121,7 +121,7 @@ void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, N if (acceptedReplacement) [spellChecker recordResponse:NSCorrectionResponseAccepted toCorrection:acceptedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag]; else { - if (!m_wasDismissedExternally || m_reasonForDismissing == ReasonForDismissingCorrectionPanelCancelled) + if (!m_wasDismissedExternally || m_reasonForDismissing == ReasonForDismissingAlternativeTextCancelled) [spellChecker recordResponse:NSCorrectionResponseRejected toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag]; else [spellChecker recordResponse:NSCorrectionResponseIgnored toCorrection:proposedReplacement forWord:replaced language:nil inSpellDocumentWithTag:documentTag]; @@ -145,5 +145,5 @@ void CorrectionPanel::handleAcceptedReplacement(NSString* acceptedReplacement, N } // namespace WebKit -#endif //!defined(BUILDING_ON_SNOW_LEOPARD) +#endif // !defined(BUILDING_ON_SNOW_LEOPARD) diff --git a/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h b/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h index df6c41179..c5b6f0e91 100644 --- a/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h +++ b/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h @@ -26,6 +26,8 @@ #ifndef TiledCoreAnimationDrawingAreaProxy_h #define TiledCoreAnimationDrawingAreaProxy_h +#if ENABLE(THREADED_SCROLLING) + #include "DrawingAreaProxy.h" #include <wtf/PassOwnPtr.h> @@ -42,7 +44,9 @@ private: // DrawingAreaProxy virtual void deviceScaleFactorDidChange() OVERRIDE; virtual void layerHostingModeDidChange() OVERRIDE; + virtual void visibilityDidChange() OVERRIDE; virtual void sizeDidChange() OVERRIDE; + virtual void waitForPossibleGeometryUpdate() OVERRIDE; virtual void enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext&) OVERRIDE; virtual void exitAcceleratedCompositingMode(uint64_t backingStoreStateID, const UpdateInfo&) OVERRIDE; @@ -62,4 +66,6 @@ private: } // namespace WebKit +#endif // ENABLE(THREADED_SCROLLING) + #endif // TiledCoreAnimationDrawingAreaProxy_h diff --git a/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm b/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm index d8f7d9d49..747ed1103 100644 --- a/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm +++ b/Source/WebKit2/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm @@ -26,6 +26,8 @@ #import "config.h" #import "TiledCoreAnimationDrawingAreaProxy.h" +#if ENABLE(THREADED_SCROLLING) + #import "DrawingAreaMessages.h" #import "DrawingAreaProxyMessages.h" #import "LayerTreeContext.h" @@ -56,6 +58,14 @@ void TiledCoreAnimationDrawingAreaProxy::deviceScaleFactorDidChange() m_webPageProxy->process()->send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy->deviceScaleFactor()), m_webPageProxy->pageID()); } +void TiledCoreAnimationDrawingAreaProxy::visibilityDidChange() +{ + if (!m_webPageProxy->isViewVisible()) + m_webPageProxy->process()->send(Messages::DrawingArea::SuspendPainting(), m_webPageProxy->pageID()); + else + m_webPageProxy->process()->send(Messages::DrawingArea::ResumePainting(), m_webPageProxy->pageID()); +} + void TiledCoreAnimationDrawingAreaProxy::layerHostingModeDidChange() { m_webPageProxy->process()->send(Messages::DrawingArea::SetLayerHostingMode(m_webPageProxy->layerHostingMode()), m_webPageProxy->pageID()); @@ -72,6 +82,12 @@ void TiledCoreAnimationDrawingAreaProxy::sizeDidChange() return; sendUpdateGeometry(); +} + +void TiledCoreAnimationDrawingAreaProxy::waitForPossibleGeometryUpdate() +{ + if (!m_isWaitingForDidUpdateGeometry) + return; if (m_webPageProxy->process()->isLaunching()) return; @@ -119,3 +135,5 @@ void TiledCoreAnimationDrawingAreaProxy::sendUpdateGeometry() } } // namespace WebKit + +#endif // ENABLE(THREADED_SCROLLING) diff --git a/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.h b/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.h index 4e9cbf08b..9ce88ae5a 100644 --- a/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.h +++ b/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.h @@ -50,6 +50,7 @@ class IntRect; RetainPtr<NSWindow> _backgroundWindow; NSRect _initialFrame; NSRect _finalFrame; + RetainPtr<NSTimer> _watchdogTimer; BOOL _isEnteringFullScreen; BOOL _isExitingFullScreen; @@ -60,6 +61,8 @@ class IntRect; - (WKView*)webView; - (void)setWebView:(WKView*)webView; +- (BOOL)isFullScreen; + - (void)enterFullScreen:(NSScreen *)screen; - (void)exitFullScreen; - (void)close; diff --git a/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.mm b/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.mm index b32d5c9ee..9b3c11422 100644 --- a/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.mm +++ b/Source/WebKit2/UIProcess/mac/WKFullScreenWindowController.mm @@ -51,6 +51,7 @@ using namespace WebCore; static RetainPtr<NSWindow> createBackgroundFullscreenWindow(NSRect frame); static const CFTimeInterval defaultAnimationDuration = 0.5; +static const NSTimeInterval DefaultWatchdogTimerInterval = 1; @interface WKFullScreenWindowController(Private)<NSAnimationDelegate> - (void)_updateMenuAndDockForFullScreen; @@ -130,12 +131,22 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; _webView = webView; } +- (BOOL)isFullScreen +{ + return _isFullScreen; +} + #pragma mark - #pragma mark NSWindowController overrides - (void)cancelOperation:(id)sender { - [self performSelector:@selector(exitFullScreen) withObject:nil afterDelay:0]; + [self _manager]->requestExitFullScreen(); + + // If the page doesn't respond in DefaultWatchdogTimerInterval seconds, it could be because + // the WebProcess has hung, so exit anyway. + if (!_watchdogTimer) + _watchdogTimer = adoptNS([NSTimer scheduledTimerWithTimeInterval:DefaultWatchdogTimerInterval target:self selector:@selector(exitFullScreen) userInfo:nil repeats:NO]); } #pragma mark - @@ -216,8 +227,8 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; [[self window] makeResponder:webWindowFirstResponder firstResponderIfDescendantOfView:_webView]; - [self _manager]->willEnterFullScreen(); [self _manager]->setAnimatingFullScreen(true); + [self _manager]->willEnterFullScreen(); } - (void)beganEnterFullScreenWithInitialFrame:(const WebCore::IntRect&)initialFrame finalFrame:(const WebCore::IntRect&)finalFrame @@ -243,8 +254,8 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; if (completed) { // Screen updates to be re-enabled ta the end of the current block. NSDisableScreenUpdates(); - [self _manager]->setAnimatingFullScreen(false); [self _manager]->didEnterFullScreen(); + [self _manager]->setAnimatingFullScreen(false); NSRect windowBounds = [[self window] frame]; windowBounds.origin = NSZeroPoint; @@ -275,6 +286,11 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; - (void)exitFullScreen { + if (_watchdogTimer) { + [_watchdogTimer.get() invalidate]; + _watchdogTimer.clear(); + } + if (!_isFullScreen) return; _isFullScreen = NO; @@ -283,8 +299,8 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; NSDisableScreenUpdates(); [[self window] setAutodisplay:NO]; - [self _manager]->willExitFullScreen(); [self _manager]->setAnimatingFullScreen(true); + [self _manager]->willExitFullScreen(); } - (void)beganExitFullScreenWithInitialFrame:(const WebCore::IntRect&)initialFrame finalFrame:(const WebCore::IntRect&)finalFrame @@ -307,7 +323,7 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; #endif // If the user has moved the fullScreen window into a new space, temporarily change // the collectionBehavior of the webView's window so that it is pulled into the active space: - if (![webWindow isOnActiveSpace]) { + if (!([webWindow respondsToSelector:@selector(isOnActiveSpace)] ? [webWindow isOnActiveSpace] : YES)) { NSWindowCollectionBehavior behavior = [webWindow collectionBehavior]; [webWindow setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces]; [webWindow orderWindow:NSWindowBelow relativeTo:[[self window] windowNumber]]; @@ -322,6 +338,8 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; [self _startExitFullScreenAnimationWithDuration:defaultAnimationDuration]; } +static void completeFinishExitFullScreenAnimationAfterRepaint(WKErrorRef, void*); + - (void)finishedExitFullScreenAnimation:(bool)completed { if (!_isExitingFullScreen) @@ -330,11 +348,9 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; [self _updateMenuAndDockForFullScreen]; - // Screen updates to be re-enabled ta the end of the current function. + // Screen updates to be re-enabled in completeFinishExitFullScreenAnimationAfterRepaint. NSDisableScreenUpdates(); - - [self _manager]->setAnimatingFullScreen(false); - [self _manager]->didExitFullScreen(); + [[_webViewPlaceholder.get() window] setAutodisplay:NO]; NSResponder *firstResponder = [[self window] firstResponder]; [self _swapView:_webViewPlaceholder.get() with:_webView]; @@ -354,9 +370,26 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; [_backgroundWindow.get() orderOut:self]; [_backgroundWindow.get() setFrame:NSZeroRect display:YES]; + [[_webView window] makeKeyAndOrderFront:self]; + + // These messages must be sent after the swap or flashing will occur during forceRepaint: + [self _manager]->didExitFullScreen(); + [self _manager]->setAnimatingFullScreen(false); + + [self _page]->forceRepaint(VoidCallback::create(self, completeFinishExitFullScreenAnimationAfterRepaint)); +} + +- (void)completeFinishExitFullScreenAnimationAfterRepaint +{ + [[_webView window] setAutodisplay:YES]; NSEnableScreenUpdates(); } +static void completeFinishExitFullScreenAnimationAfterRepaint(WKErrorRef, void* _self) +{ + [(WKFullScreenWindowController*)_self completeFinishExitFullScreenAnimationAfterRepaint]; +} + - (void)close { // We are being asked to close rapidly, most likely because the page @@ -410,7 +443,7 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; [NSApp setPresentationOptions:options]; else #endif - SetSystemUIMode(_isFullScreen ? kUIModeNormal : kUIModeAllHidden, 0); + SetSystemUIMode(_isFullScreen ? kUIModeAllHidden : kUIModeNormal, 0); } - (WebPageProxy*)_page @@ -433,7 +466,8 @@ static const CFTimeInterval defaultAnimationDuration = 0.5; [otherView setFrame:[view frame]]; [otherView setAutoresizingMask:[view autoresizingMask]]; [otherView removeFromSuperview]; - [[view superview] replaceSubview:view with:otherView]; + [[view superview] addSubview:otherView positioned:NSWindowAbove relativeTo:view]; + [view removeFromSuperview]; [CATransaction commit]; } @@ -449,6 +483,9 @@ static RetainPtr<NSWindow> createBackgroundFullscreenWindow(NSRect frame) static NSRect windowFrameFromApparentFrames(NSRect screenFrame, NSRect initialFrame, NSRect finalFrame) { NSRect initialWindowFrame; + if (!NSWidth(initialFrame) || !NSWidth(finalFrame) || !NSHeight(initialFrame) || !NSHeight(finalFrame)) + return screenFrame; + CGFloat xScale = NSWidth(screenFrame) / NSWidth(finalFrame); CGFloat yScale = NSHeight(screenFrame) / NSHeight(finalFrame); CGFloat xTrans = NSMinX(screenFrame) - NSMinX(finalFrame); diff --git a/Source/WebKit2/UIProcess/mac/WebContextMac.mm b/Source/WebKit2/UIProcess/mac/WebContextMac.mm index ab5721bb8..243027974 100644 --- a/Source/WebKit2/UIProcess/mac/WebContextMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebContextMac.mm @@ -111,9 +111,7 @@ void WebContext::platformInitializeWebProcess(WebProcessCreationParameters& para // FIXME: This should really be configurable; we shouldn't just blindly allow read access to the UI process bundle. parameters.uiProcessBundleResourcePath = [[NSBundle mainBundle] resourcePath]; -#if USE(CFURLSTORAGESESSIONS) parameters.uiProcessBundleIdentifier = String([[NSBundle mainBundle] bundleIdentifier]); -#endif // Listen for enhanced accessibility changes and propagate them to the WebProcess. m_enhancedAccessibilityObserver = [[NSNotificationCenter defaultCenter] addObserverForName:WebKitApplicationDidChangeAccessibilityEnhancedUserInterfaceNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) { @@ -203,6 +201,16 @@ void WebContext::getPasteboardColor(const String& pasteboardName, WebCore::Color color = PlatformPasteboard(pasteboardName).color(); } +void WebContext::getPasteboardURL(const String& pasteboardName, WTF::String& urlString) +{ + urlString = PlatformPasteboard(pasteboardName).url().string(); +} + +void WebContext::addPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes) +{ + PlatformPasteboard(pasteboardName).addTypes(pasteboardTypes); +} + void WebContext::setPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes) { PlatformPasteboard(pasteboardName).setTypes(pasteboardTypes); diff --git a/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm index 04667b6cd..6325fca45 100644 --- a/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebFullScreenManagerProxyMac.mm @@ -46,6 +46,23 @@ void WebFullScreenManagerProxy::invalidate() m_webView = 0; } +void WebFullScreenManagerProxy::close() +{ + if (!m_webView) + return; + [[m_webView fullScreenWindowController] close]; +} + +bool WebFullScreenManagerProxy::isFullScreen() +{ + if (!m_webView) + return false; + if (![m_webView hasFullScreenWindowController]) + return false; + + return [[m_webView fullScreenWindowController] isFullScreen]; +} + void WebFullScreenManagerProxy::enterFullScreen() { if (!m_webView) diff --git a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm index 0db662c42..cfb756cdb 100644 --- a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm @@ -39,9 +39,11 @@ #import <WebKitSystemInterface.h> #import <WebCore/InspectorFrontendClientLocal.h> #import <WebCore/LocalizedStrings.h> -#import <WebCore/NotImplemented.h> +#import <WebCore/SoftLinking.h> #import <wtf/text/WTFString.h> +SOFT_LINK_STAGED_FRAMEWORK_OPTIONAL(WebInspector, PrivateFrameworks) + using namespace WebCore; using namespace WebKit; @@ -102,11 +104,27 @@ static const CGFloat windowContentBorderThickness = 55; namespace WebKit { +static bool inspectorReallyUsesWebKitUserInterface(WebPreferences* preferences) +{ + // This matches a similar check in WebInspectorMac.mm. Keep them in sync. + + // Call the soft link framework function to dlopen it, then [NSBundle bundleWithIdentifier:] will work. + WebInspectorLibrary(); + + if (![[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] pathForResource:@"Main" ofType:@"html"]) + return true; + + if (![[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"]) + return false; + + return preferences->inspectorUsesWebKitUserInterface(); +} + void WebInspectorProxy::createInspectorWindow() { ASSERT(!m_inspectorWindow); - bool useTexturedWindow = page()->process()->context()->overrideWebInspectorPagePath().isEmpty(); + bool useTexturedWindow = inspectorReallyUsesWebKitUserInterface(page()->pageGroup()->preferences()); NSUInteger styleMask = (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask); if (useTexturedWindow) @@ -253,6 +271,7 @@ void WebInspectorProxy::platformAttach() [m_inspectorView.get() setHidden:!m_isVisible]; [[inspectedView superview] addSubview:m_inspectorView.get() positioned:NSWindowBelow relativeTo:inspectedView]; + [[inspectedView window] makeFirstResponder:m_inspectorView.get()]; if (m_inspectorWindow) { [m_inspectorWindow.get() setDelegate:nil]; @@ -270,11 +289,6 @@ void WebInspectorProxy::platformDetach() [m_inspectorView.get() removeFromSuperview]; - createInspectorWindow(); - - // Make the inspector view visible in case it is still hidden from loading while attached. - [m_inspectorView.get() setHidden:NO]; - // Make sure that we size the inspected view's frame after detaching so that it takes up the space that the // attached inspector used to. This assumes the previous height was the Y origin. NSRect inspectedViewRect = [inspectedView frame]; @@ -282,8 +296,17 @@ void WebInspectorProxy::platformDetach() inspectedViewRect.origin.y = 0.0; [inspectedView setFrame:inspectedViewRect]; - if (m_isVisible) - [m_inspectorWindow.get() makeKeyAndOrderFront:nil]; + // Return early if we are not visible. This means the inspector was closed while attached + // and we should not create and show the inspector window. + if (!m_isVisible) + return; + + createInspectorWindow(); + + // Make the inspector view visible in case it is still hidden from loading while attached. + [m_inspectorView.get() setHidden:NO]; + + [m_inspectorWindow.get() makeKeyAndOrderFront:nil]; } void WebInspectorProxy::platformSetAttachedWindowHeight(unsigned height) @@ -302,9 +325,11 @@ void WebInspectorProxy::platformSetAttachedWindowHeight(unsigned height) String WebInspectorProxy::inspectorPageURL() const { - NSString *path = page()->process()->context()->overrideWebInspectorPagePath(); - if (![path length]) + NSString *path; + if (inspectorReallyUsesWebKitUserInterface(page()->pageGroup()->preferences())) path = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] pathForResource:@"inspector" ofType:@"html" inDirectory:@"inspector"]; + else + path = [[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] pathForResource:@"Main" ofType:@"html"]; ASSERT([path length]); @@ -313,11 +338,11 @@ String WebInspectorProxy::inspectorPageURL() const String WebInspectorProxy::inspectorBaseURL() const { - NSString *path = page()->process()->context()->overrideWebInspectorBaseDirectory(); - if (![path length]) { - // WebCore's Web Inspector uses localized strings, which are not contained within inspector directory. + NSString *path; + if (inspectorReallyUsesWebKitUserInterface(page()->pageGroup()->preferences())) path = [[NSBundle bundleWithIdentifier:@"com.apple.WebCore"] resourcePath]; - } + else + path = [[NSBundle bundleWithIdentifier:@"com.apple.WebInspector"] resourcePath]; ASSERT([path length]); diff --git a/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm index 120dc5d28..c21f16a6d 100644 --- a/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm @@ -38,6 +38,7 @@ #import "TextChecker.h" #import "WebPageMessages.h" #import "WebProcessProxy.h" +#import <WebCore/SharedBuffer.h> #import <WebKitSystemInterface.h> #import <wtf/text/StringConcatenate.h> @@ -256,15 +257,30 @@ bool WebPageProxy::executeKeypressCommands(const Vector<WebCore::KeypressCommand return result; } -bool WebPageProxy::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes) +String WebPageProxy::stringSelectionForPasteboard() { + String value; if (!isValid()) - return false; + return value; + + const double messageTimeout = 20; + process()->sendSync(Messages::WebPage::GetStringSelectionForPasteboard(), Messages::WebPage::GetStringSelectionForPasteboard::Reply(value), m_pageID, messageTimeout); + return value; +} - bool result = false; +PassRefPtr<WebCore::SharedBuffer> WebPageProxy::dataSelectionForPasteboard(const String& pasteboardType) +{ + if (!isValid()) + return 0; + SharedMemory::Handle handle; + uint64_t size = 0; const double messageTimeout = 20; - process()->sendSync(Messages::WebPage::WriteSelectionToPasteboard(pasteboardName, pasteboardTypes), Messages::WebPage::WriteSelectionToPasteboard::Reply(result), m_pageID, messageTimeout); - return result; + process()->sendSync(Messages::WebPage::GetDataSelectionForPasteboard(pasteboardType), + Messages::WebPage::GetDataSelectionForPasteboard::Reply(handle, size), m_pageID, messageTimeout); + if (handle.isNull()) + return 0; + RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::create(handle, SharedMemory::ReadOnly); + return SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), size); } bool WebPageProxy::readSelectionFromPasteboard(const String& pasteboardName) @@ -287,6 +303,20 @@ void WebPageProxy::setDragImage(const WebCore::IntPoint& clientPosition, const S m_pageClient->setDragImage(clientPosition, dragImage.release(), isLinkDrag); } +void WebPageProxy::setPromisedData(const String& pasteboardName, const SharedMemory::Handle& imageHandle, uint64_t imageSize, const String& filename, const String& extension, + const String& title, const String& url, const String& visibleURL, const SharedMemory::Handle& archiveHandle, uint64_t archiveSize) +{ + RefPtr<SharedMemory> sharedMemoryImage = SharedMemory::create(imageHandle, SharedMemory::ReadOnly); + RefPtr<SharedBuffer> imageBuffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryImage->data()), imageSize); + RefPtr<SharedBuffer> archiveBuffer; + + if (!archiveHandle.isNull()) { + RefPtr<SharedMemory> sharedMemoryArchive = SharedMemory::create(archiveHandle, SharedMemory::ReadOnly);; + archiveBuffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryArchive->data()), archiveSize); + } + m_pageClient->setPromisedData(pasteboardName, imageBuffer, filename, extension, title, url, visibleURL, archiveBuffer); +} + void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point) { if (!isValid()) @@ -372,6 +402,8 @@ void WebPageProxy::setPluginComplexTextInputState(uint64_t pluginComplexTextInpu void WebPageProxy::executeSavedCommandBySelector(const String& selector, bool& handled) { + MESSAGE_CHECK(isValidKeypressCommandName(selector)); + handled = m_pageClient->executeSavedCommandBySelector(selector); } diff --git a/Source/WebKit2/UIProcess/qt/LayerBackingStore.cpp b/Source/WebKit2/UIProcess/qt/LayerBackingStore.cpp index d66cc19b7..caaffe9e5 100644 --- a/Source/WebKit2/UIProcess/qt/LayerBackingStore.cpp +++ b/Source/WebKit2/UIProcess/qt/LayerBackingStore.cpp @@ -22,9 +22,9 @@ #if USE(UI_SIDE_COMPOSITING) #include "GraphicsLayer.h" +#include "ShareableSurface.h" #include "TextureMapper.h" - -#include "stdio.h" +#include "TextureMapperGL.h" using namespace WebCore; @@ -32,7 +32,7 @@ namespace WebKit { void LayerBackingStoreTile::swapBuffers(WebCore::TextureMapper* textureMapper) { - if (!m_backBuffer) + if (!m_surface) return; FloatRect targetRect(m_targetRect); @@ -49,20 +49,19 @@ void LayerBackingStoreTile::swapBuffers(WebCore::TextureMapper* textureMapper) shouldReset = true; } - QImage qImage = m_backBuffer->createQImage(); - if (shouldReset) - texture->reset(m_sourceRect.size(), qImage.hasAlphaChannel() ? BitmapTexture::SupportsAlpha : 0); + texture->reset(m_targetRect.size(), m_surface->flags() & ShareableBitmap::SupportsAlpha ? BitmapTexture::SupportsAlpha : 0); - texture->updateContents(qImage.constBits(), m_sourceRect); - m_backBuffer.clear(); + m_surface->copyToTexture(texture, m_sourceRect, m_surfaceOffset); + m_surface.clear(); } -void LayerBackingStoreTile::setBackBuffer(const WebCore::IntRect& targetRect, const WebCore::IntRect& sourceRect, ShareableBitmap* buffer) +void LayerBackingStoreTile::setBackBuffer(const IntRect& targetRect, const IntRect& sourceRect, PassRefPtr<ShareableSurface> buffer, const IntPoint& offset) { m_sourceRect = sourceRect; m_targetRect = targetRect; - m_backBuffer = buffer; + m_surfaceOffset = offset; + m_surface = buffer; } void LayerBackingStore::createTile(int id, float scale) @@ -73,14 +72,15 @@ void LayerBackingStore::createTile(int id, float scale) void LayerBackingStore::removeTile(int id) { - m_tiles.remove(id); + m_tilesToRemove.append(id); } -void LayerBackingStore::updateTile(int id, const IntRect& sourceRect, const IntRect& targetRect, ShareableBitmap* backBuffer) + +void LayerBackingStore::updateTile(int id, const IntRect& sourceRect, const IntRect& targetRect, PassRefPtr<ShareableSurface> backBuffer, const IntPoint& offset) { HashMap<int, LayerBackingStoreTile>::iterator it = m_tiles.find(id); ASSERT(it != m_tiles.end()); - it->second.setBackBuffer(targetRect, sourceRect, backBuffer); + it->second.setBackBuffer(targetRect, sourceRect, backBuffer, offset); } PassRefPtr<BitmapTexture> LayerBackingStore::texture() const @@ -119,27 +119,23 @@ void LayerBackingStore::paintToTextureMapper(TextureMapper* textureMapper, const continue; tilesToPaint.prepend(&tile); - coveredRect.unite(tile.rect()); } - bool shouldClip = !targetRect.contains(coveredRect); - - if (shouldClip) - textureMapper->beginClip(transform, targetRect); - for (size_t i = 0; i < tilesToPaint.size(); ++i) tilesToPaint[i]->paint(textureMapper, transform, opacity, mask); - - if (shouldClip) - textureMapper->endClip(); } -void LayerBackingStore::swapBuffers(TextureMapper* textureMapper) +void LayerBackingStore::commitTileOperations(TextureMapper* textureMapper) { - HashMap<int, LayerBackingStoreTile>::iterator end = m_tiles.end(); - for (HashMap<int, LayerBackingStoreTile>::iterator it = m_tiles.begin(); it != end; ++it) + Vector<int>::iterator tilesToRemoveEnd = m_tilesToRemove.end(); + for (Vector<int>::iterator it = m_tilesToRemove.begin(); it != tilesToRemoveEnd; ++it) + m_tiles.remove(*it); + m_tilesToRemove.clear(); + + HashMap<int, LayerBackingStoreTile>::iterator tilesEnd = m_tiles.end(); + for (HashMap<int, LayerBackingStoreTile>::iterator it = m_tiles.begin(); it != tilesEnd; ++it) it->second.swapBuffers(textureMapper); } -} +} // namespace WebKit #endif diff --git a/Source/WebKit2/UIProcess/qt/LayerBackingStore.h b/Source/WebKit2/UIProcess/qt/LayerBackingStore.h index 9b9913e38..a3e219b04 100644 --- a/Source/WebKit2/UIProcess/qt/LayerBackingStore.h +++ b/Source/WebKit2/UIProcess/qt/LayerBackingStore.h @@ -21,13 +21,15 @@ #define LayerBackingStore_h #if USE(UI_SIDE_COMPOSITING) -#include "HashMap.h" -#include "ShareableBitmap.h" + #include "TextureMapper.h" #include "TextureMapperBackingStore.h" +#include <wtf/HashMap.h> namespace WebKit { +class ShareableSurface; + class LayerBackingStoreTile : public WebCore::TextureMapperTile { public: LayerBackingStoreTile(float scale = 1) @@ -38,12 +40,13 @@ public: inline float scale() const { return m_scale; } void swapBuffers(WebCore::TextureMapper*); - void setBackBuffer(const WebCore::IntRect&, const WebCore::IntRect&, ShareableBitmap* buffer); + void setBackBuffer(const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<ShareableSurface> buffer, const WebCore::IntPoint&); private: - RefPtr<ShareableBitmap> m_backBuffer; + RefPtr<ShareableSurface> m_surface; WebCore::IntRect m_sourceRect; WebCore::IntRect m_targetRect; + WebCore::IntPoint m_surfaceOffset; float m_scale; }; @@ -51,9 +54,9 @@ class LayerBackingStore : public WebCore::TextureMapperBackingStore { public: void createTile(int, float); void removeTile(int); - void updateTile(int, const WebCore::IntRect&, const WebCore::IntRect&, ShareableBitmap*); + void updateTile(int, const WebCore::IntRect&, const WebCore::IntRect&, PassRefPtr<ShareableSurface>, const WebCore::IntPoint&); static PassRefPtr<LayerBackingStore> create() { return adoptRef(new LayerBackingStore); } - void swapBuffers(WebCore::TextureMapper*); + void commitTileOperations(WebCore::TextureMapper*); PassRefPtr<WebCore::BitmapTexture> texture() const; virtual void paintToTextureMapper(WebCore::TextureMapper*, const WebCore::FloatRect&, const WebCore::TransformationMatrix&, float, WebCore::BitmapTexture*); @@ -62,10 +65,11 @@ private: : m_scale(1.) { } HashMap<int, LayerBackingStoreTile> m_tiles; + Vector<int> m_tilesToRemove; float m_scale; }; -} +} // namespace WebKit #endif #endif // LayerBackingStore_h diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp index 16c642934..6e41c8b39 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp @@ -21,12 +21,17 @@ #include "config.h" #include "QtDialogRunner.h" -#include <QtDeclarative/QDeclarativeComponent> -#include <QtDeclarative/QDeclarativeContext> -#include <QtDeclarative/QDeclarativeEngine> +#include "WKRetainPtr.h" +#include "WKStringQt.h" +#include "qwebpermissionrequest_p.h" +#include <QtQml/QQmlComponent> +#include <QtQml/QQmlContext> +#include <QtQml/QQmlEngine> #include <QtQuick/QQuickItem> #include <wtf/PassOwnPtr.h> +namespace WebKit { + QtDialogRunner::QtDialogRunner() : QEventLoop() , m_wasAccepted(false) @@ -69,23 +74,20 @@ private: QString m_defaultValue; }; -class AuthenticationDialogContextObject : public QObject { +class BaseAuthenticationContextObject : 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) + BaseAuthenticationContextObject(const QString& hostname, 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: @@ -98,41 +100,41 @@ signals: private: QString m_hostname; - QString m_realm; QString m_prefilledUsername; }; -class ProxyAuthenticationDialogContextObject : public QObject { +class HttpAuthenticationDialogContextObject : public BaseAuthenticationContextObject { + Q_OBJECT + Q_PROPERTY(QString realm READ realm CONSTANT) + +public: + HttpAuthenticationDialogContextObject(const QString& hostname, const QString& realm, const QString& prefilledUsername) + : BaseAuthenticationContextObject(hostname, prefilledUsername) + , m_realm(realm) + { + } + + QString realm() const { return m_realm; } + +private: + QString m_realm; +}; + +class ProxyAuthenticationDialogContextObject : public BaseAuthenticationContextObject { Q_OBJECT - Q_PROPERTY(QString hostname READ hostname CONSTANT) Q_PROPERTY(quint16 port READ port CONSTANT) - Q_PROPERTY(QString prefilledUsername READ prefilledUsername CONSTANT) public: ProxyAuthenticationDialogContextObject(const QString& hostname, quint16 port, const QString& prefilledUsername) - : QObject() - , m_hostname(hostname) + : BaseAuthenticationContextObject(hostname, prefilledUsername) , m_port(port) - , m_prefilledUsername(prefilledUsername) { } - QString hostname() const { return m_hostname; } quint16 port() const { return m_port; } - 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; quint16 m_port; - QString m_prefilledUsername; }; class CertificateVerificationDialogContextObject : public QObject { @@ -160,7 +162,97 @@ private: QString m_hostname; }; -bool QtDialogRunner::initForAlert(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& message) +class FilePickerContextObject : public QObject { + Q_OBJECT + Q_PROPERTY(QStringList fileList READ fileList CONSTANT) + Q_PROPERTY(bool allowMultipleFiles READ allowMultipleFiles CONSTANT) + +public: + FilePickerContextObject(const QStringList& selectedFiles, bool allowMultiple) + : QObject() + , m_allowMultiple(allowMultiple) + , m_fileList(selectedFiles) + { + } + + QStringList fileList() const { return m_fileList; } + bool allowMultipleFiles() const { return m_allowMultiple;} + +public slots: + void reject() { emit rejected();} + void accept(const QVariant& path) + { + QStringList filesPath = path.toStringList(); + // For single file upload, send only the first element if there are more than one file paths + if (!m_allowMultiple && filesPath.count() > 1) + filesPath = QStringList(filesPath.at(0)); + emit fileSelected(filesPath); + } + +signals: + void rejected(); + void fileSelected(const QStringList&); + +private: + bool m_allowMultiple; + QStringList m_fileList; +}; + +class DatabaseQuotaDialogContextObject : public QObject { + Q_OBJECT + Q_PROPERTY(QString databaseName READ databaseName CONSTANT) + Q_PROPERTY(QString displayName READ displayName CONSTANT) + Q_PROPERTY(quint64 currentQuota READ currentQuota CONSTANT) + Q_PROPERTY(quint64 currentOriginUsage READ currentOriginUsage CONSTANT) + Q_PROPERTY(quint64 currentDatabaseUsage READ currentDatabaseUsage CONSTANT) + Q_PROPERTY(quint64 expectedUsage READ expectedUsage CONSTANT) + Q_PROPERTY(QtWebSecurityOrigin* origin READ securityOrigin CONSTANT) + +public: + DatabaseQuotaDialogContextObject(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) + : QObject() + , m_databaseName(databaseName) + , m_displayName(displayName) + , m_currentQuota(currentQuota) + , m_currentOriginUsage(currentOriginUsage) + , m_currentDatabaseUsage(currentDatabaseUsage) + , m_expectedUsage(expectedUsage) + { + WKRetainPtr<WKStringRef> scheme = adoptWK(WKSecurityOriginCopyProtocol(securityOrigin)); + WKRetainPtr<WKStringRef> host = adoptWK(WKSecurityOriginCopyHost(securityOrigin)); + + m_securityOrigin.setScheme(WKStringCopyQString(scheme.get())); + m_securityOrigin.setHost(WKStringCopyQString(host.get())); + m_securityOrigin.setPort(static_cast<int>(WKSecurityOriginGetPort(securityOrigin))); + } + + QString databaseName() const { return m_databaseName; } + QString displayName() const { return m_displayName; } + quint64 currentQuota() const { return m_currentQuota; } + quint64 currentOriginUsage() const { return m_currentOriginUsage; } + quint64 currentDatabaseUsage() const { return m_currentDatabaseUsage; } + quint64 expectedUsage() const { return m_expectedUsage; } + QtWebSecurityOrigin* securityOrigin() { return &m_securityOrigin; } + +public slots: + void accept(quint64 size) { emit accepted(size); } + void reject() { emit rejected(); } + +signals: + void accepted(quint64 size); + void rejected(); + +private: + QString m_databaseName; + QString m_displayName; + quint64 m_currentQuota; + quint64 m_currentOriginUsage; + quint64 m_currentDatabaseUsage; + quint64 m_expectedUsage; + QtWebSecurityOrigin m_securityOrigin; +}; + +bool QtDialogRunner::initForAlert(QQmlComponent* component, QQuickItem* dialogParent, const QString& message) { DialogContextObject* contextObject = new DialogContextObject(message); if (!createDialog(component, dialogParent, contextObject)) @@ -170,7 +262,7 @@ bool QtDialogRunner::initForAlert(QDeclarativeComponent* component, QQuickItem* return true; } -bool QtDialogRunner::initForConfirm(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& message) +bool QtDialogRunner::initForConfirm(QQmlComponent* component, QQuickItem* dialogParent, const QString& message) { DialogContextObject* contextObject = new DialogContextObject(message); if (!createDialog(component, dialogParent, contextObject)) @@ -182,7 +274,7 @@ bool QtDialogRunner::initForConfirm(QDeclarativeComponent* component, QQuickItem return true; } -bool QtDialogRunner::initForPrompt(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& message, const QString& defaultValue) +bool QtDialogRunner::initForPrompt(QQmlComponent* component, QQuickItem* dialogParent, const QString& message, const QString& defaultValue) { DialogContextObject* contextObject = new DialogContextObject(message, defaultValue); if (!createDialog(component, dialogParent, contextObject)) @@ -194,9 +286,9 @@ bool QtDialogRunner::initForPrompt(QDeclarativeComponent* component, QQuickItem* return true; } -bool QtDialogRunner::initForAuthentication(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername) +bool QtDialogRunner::initForAuthentication(QQmlComponent* component, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername) { - AuthenticationDialogContextObject* contextObject = new AuthenticationDialogContextObject(hostname, realm, prefilledUsername); + HttpAuthenticationDialogContextObject* contextObject = new HttpAuthenticationDialogContextObject(hostname, realm, prefilledUsername); if (!createDialog(component, dialogParent, contextObject)) return false; @@ -207,7 +299,7 @@ bool QtDialogRunner::initForAuthentication(QDeclarativeComponent* component, QQu return true; } -bool QtDialogRunner::initForProxyAuthentication(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& hostname, uint16_t port, const QString& prefilledUsername) +bool QtDialogRunner::initForProxyAuthentication(QQmlComponent* component, QQuickItem* dialogParent, const QString& hostname, uint16_t port, const QString& prefilledUsername) { ProxyAuthenticationDialogContextObject* contextObject = new ProxyAuthenticationDialogContextObject(hostname, port, prefilledUsername); if (!createDialog(component, dialogParent, contextObject)) @@ -220,7 +312,7 @@ bool QtDialogRunner::initForProxyAuthentication(QDeclarativeComponent* component return true; } -bool QtDialogRunner::initForCertificateVerification(QDeclarativeComponent* component, QQuickItem* dialogParent, const QString& hostname) +bool QtDialogRunner::initForCertificateVerification(QQmlComponent* component, QQuickItem* dialogParent, const QString& hostname) { CertificateVerificationDialogContextObject* contextObject = new CertificateVerificationDialogContextObject(hostname); if (!createDialog(component, dialogParent, contextObject)) @@ -233,12 +325,38 @@ bool QtDialogRunner::initForCertificateVerification(QDeclarativeComponent* compo return true; } -bool QtDialogRunner::createDialog(QDeclarativeComponent* component, QQuickItem* dialogParent, QObject* contextObject) +bool QtDialogRunner::initForFilePicker(QQmlComponent* component, QQuickItem* dialogParent, const QStringList& selectedFiles, bool allowMultiple) +{ + FilePickerContextObject* contextObject = new FilePickerContextObject(selectedFiles, allowMultiple); + if (!createDialog(component, dialogParent, contextObject)) + return false; + + connect(contextObject, SIGNAL(fileSelected(QStringList)), SLOT(onFileSelected(QStringList))); + connect(contextObject, SIGNAL(fileSelected(QStringList)), SLOT(quit())); + connect(contextObject, SIGNAL(rejected()), SLOT(quit())); + + return true; +} + +bool QtDialogRunner::initForDatabaseQuotaDialog(QQmlComponent* component, QQuickItem* dialogParent, const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) { - QDeclarativeContext* baseContext = component->creationContext(); + DatabaseQuotaDialogContextObject* contextObject = new DatabaseQuotaDialogContextObject(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); + if (!createDialog(component, dialogParent, contextObject)) + return false; + + connect(contextObject, SIGNAL(accepted(quint64)), SLOT(onDatabaseQuotaAccepted(quint64))); + connect(contextObject, SIGNAL(accepted(quint64)), SLOT(quit())); + connect(contextObject, SIGNAL(rejected()), SLOT(quit())); + + return true; +} + +bool QtDialogRunner::createDialog(QQmlComponent* component, QQuickItem* dialogParent, QObject* contextObject) +{ + QQmlContext* baseContext = component->creationContext(); if (!baseContext) - baseContext = QDeclarativeEngine::contextForObject(dialogParent); - m_dialogContext = adoptPtr(new QDeclarativeContext(baseContext)); + baseContext = QQmlEngine::contextForObject(dialogParent); + m_dialogContext = adoptPtr(new QQmlContext(baseContext)); // This makes both "message" and "model.message" work for the dialog, just like QtQuick's ListView delegates. contextObject->setParent(m_dialogContext.get()); @@ -262,5 +380,8 @@ bool QtDialogRunner::createDialog(QDeclarativeComponent* component, QQuickItem* return true; } +} // namespace WebKit + #include "QtDialogRunner.moc" #include "moc_QtDialogRunner.cpp" + diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h index 7fbace1ce..f53fc92f4 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h @@ -21,12 +21,18 @@ #ifndef QtDialogRunner_h #define QtDialogRunner_h +#include "WKSecurityOrigin.h" #include <QtCore/QEventLoop> +#include <QtCore/QStringList> #include <wtf/OwnPtr.h> +QT_BEGIN_NAMESPACE class QDeclarativeComponent; class QDeclarativeContext; class QQuickItem; +QT_END_NAMESPACE + +namespace WebKit { class QtDialogRunner : public QEventLoop { Q_OBJECT @@ -41,6 +47,8 @@ public: bool initForAuthentication(QDeclarativeComponent*, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername); bool initForCertificateVerification(QDeclarativeComponent*, QQuickItem*, const QString& hostname); bool initForProxyAuthentication(QDeclarativeComponent*, QQuickItem*, const QString& hostname, uint16_t port, const QString& prefilledUsername); + bool initForFilePicker(QDeclarativeComponent*, QQuickItem*, const QStringList& selectedFiles, bool allowMultiple); + bool initForDatabaseQuotaDialog(QDeclarativeComponent*, QQuickItem*, const QString& databaseName, const QString& displayName, WKSecurityOriginRef, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage); QQuickItem* dialog() const { return m_dialog.get(); } @@ -50,6 +58,10 @@ public: QString username() const { return m_username; } QString password() const { return m_password; } + quint64 databaseQuota() const { return m_databaseQuota; } + + QStringList filePaths() const { return m_filepaths; } + public slots: void onAccepted(const QString& result = QString()) { @@ -63,6 +75,18 @@ public slots: m_password = password; } + void onFileSelected(const QStringList& filePaths) + { + m_wasAccepted = true; + m_filepaths = filePaths; + } + + void onDatabaseQuotaAccepted(quint64 quota) + { + m_wasAccepted = true; + m_databaseQuota = quota; + } + private: bool createDialog(QDeclarativeComponent*, QQuickItem* dialogParent, QObject* contextObject); @@ -73,6 +97,10 @@ private: QString m_username; QString m_password; + QStringList m_filepaths; + quint64 m_databaseQuota; }; +} // namespace WebKit + #endif // QtDialogRunner_h diff --git a/Source/WebKit2/UIProcess/qt/QtDownloadManager.cpp b/Source/WebKit2/UIProcess/qt/QtDownloadManager.cpp index 99c4dc58e..eb76f1aed 100644 --- a/Source/WebKit2/UIProcess/qt/QtDownloadManager.cpp +++ b/Source/WebKit2/UIProcess/qt/QtDownloadManager.cpp @@ -142,4 +142,4 @@ void QtDownloadManager::didReceiveDataForDownload(WKContextRef, WKDownloadRef do toQtDownloadManager(clientInfo)->downloadDataReceived(toImpl(download), length); } -} +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtDownloadManager.h b/Source/WebKit2/UIProcess/qt/QtDownloadManager.h index 5e8d5ee43..a49f5e2a4 100644 --- a/Source/WebKit2/UIProcess/qt/QtDownloadManager.h +++ b/Source/WebKit2/UIProcess/qt/QtDownloadManager.h @@ -24,7 +24,6 @@ #include <QMap> #include <WKContext.h> -class QtWebError; class QWebDownloadItem; namespace WebCore { @@ -34,6 +33,7 @@ class ResourceResponse; namespace WebKit { class DownloadProxy; +class QtWebError; class WebContext; class QtDownloadManager { @@ -60,5 +60,6 @@ private: QMap<uint64_t, QWebDownloadItem*> m_downloads; }; -} +} // namespace WebKit + #endif /* QtDownloadManager_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtFlickProvider.cpp b/Source/WebKit2/UIProcess/qt/QtFlickProvider.cpp deleted file mode 100644 index b34bba642..000000000 --- a/Source/WebKit2/UIProcess/qt/QtFlickProvider.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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 "config.h" -#include "QtFlickProvider.h" - -#include "qquickwebpage_p.h" -#include "qquickwebview_p.h" - -#include <QCoreApplication> -#include <QDeclarativeEngine> -#include <QMouseEvent> -#include <QPointF> -#include <QQuickCanvas> -#include <QQuickItem> -#include <QTouchEvent> -#include <wtf/Assertions.h> - -namespace { - -inline QMetaMethod resolveMetaMethod(QObject* flickable, const char* name) -{ - ASSERT(flickable); - - const QMetaObject* metaObject = flickable->metaObject(); - ASSERT(metaObject); - - int methodIndex = metaObject->indexOfMethod(name); - ASSERT(methodIndex != -1); - - return metaObject->method(methodIndex); -} - -inline QMetaProperty resolveMetaProperty(QObject* flickable, const char* name) -{ - ASSERT(flickable); - - const QMetaObject* metaObject = flickable->metaObject(); - ASSERT(metaObject); - - int propertyIndex = metaObject->indexOfProperty(name); - ASSERT(propertyIndex != -1); - - return metaObject->property(propertyIndex); -} - -} // namespace - -QtFlickProvider::QtFlickProvider(QQuickWebView* viewItem, QQuickWebPage* pageItem) - : QObject(viewItem) -{ - ASSERT(viewItem); - ASSERT(pageItem); - - QDeclarativeEngine* engine = qmlEngine(viewItem); - QDeclarativeContext* context = qmlContext(viewItem); - - ASSERT(engine); - ASSERT(context); - - QDeclarativeComponent component(engine, viewItem); - - // Create the internal Flickable instance dynamically. - // We only use public QML API so that we do not depend - // on private API of the QtDeclarative module. - component.setData(QByteArrayLiteral("import QtQuick 2.0\nFlickable {}"), QUrl()); - - m_flickable = qobject_cast<QQuickItem*>(component.create(context)); - - QMetaProperty content = resolveMetaProperty(m_flickable, "contentItem"); - m_contentItem = content.read(m_flickable).value<QQuickItem*>(); - ASSERT(m_contentItem); - - // Resolve meta methods and properties of the Flickable instance. - m_returnToBoundsMethod = resolveMetaMethod(m_flickable, "returnToBounds()"); - m_cancelFlickMethod = resolveMetaMethod(m_flickable, "cancelFlick()"); - - m_contentWidth = resolveMetaProperty(m_flickable, "contentWidth"); - m_contentHeight = resolveMetaProperty(m_flickable, "contentHeight"); - m_contentX = resolveMetaProperty(m_flickable, "contentX"); - m_contentY = resolveMetaProperty(m_flickable, "contentY"); - m_moving = resolveMetaProperty(m_flickable, "moving"); - m_dragging = resolveMetaProperty(m_flickable, "dragging"); - m_flicking = resolveMetaProperty(m_flickable, "flicking"); - - m_flickableData = resolveMetaProperty(m_flickable, "flickableData"); - - // Set the viewItem as the parent of the flickable instance - // and reparent the page so it is placed on the flickable contentItem. - m_flickable->setParentItem(viewItem); - pageItem->setParentItem(m_contentItem); - - // Propagate flickable signals. - connect(m_flickable, SIGNAL(movementStarted()), SIGNAL(movementStarted()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(movementEnded()), SIGNAL(movementEnded()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(flickingChanged()), SIGNAL(flickingChanged()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(draggingChanged()), SIGNAL(draggingChanged()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(contentWidthChanged()), SIGNAL(contentWidthChanged()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(contentHeightChanged()), SIGNAL(contentHeightChanged()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(contentXChanged()), SIGNAL(contentXChanged()), Qt::DirectConnection); - connect(m_flickable, SIGNAL(contentYChanged()), SIGNAL(contentYChanged()), Qt::DirectConnection); -} - -void QtFlickProvider::handleTouchFlickEvent(QTouchEvent* touchEvent) -{ - // Since the Flickable does not handle touch events directly the sent - // touch event would end up in the WebView again and would thus trigger - // an infinite loop. - // Hence do the touch to mouse event conversion for the Flickable here. - QEvent::Type mouseEventType = QEvent::None; - Qt::MouseButton mouseButton = Qt::NoButton; - - switch (touchEvent->type()) { - case QEvent::TouchBegin: - mouseEventType = QEvent::MouseButtonPress; - - // We need to set the mouse button so that the Flickable - // item receives the initial mouse press event. - mouseButton = Qt::LeftButton; - break; - case QEvent::TouchUpdate: - mouseEventType = QEvent::MouseMove; - break; - case QEvent::TouchEnd: - mouseEventType = QEvent::MouseButtonRelease; - break; - default: - ASSERT_NOT_REACHED(); - break; - } - - QPointF touchPosition = touchEvent->touchPoints().last().pos(); - QMouseEvent mouseEvent(mouseEventType, touchPosition, mouseButton, mouseButton, Qt::NoModifier); - - // Send the event to the canvas and let the canvas propagate it - // to the Flickable. This makes sure that the Flickable grabs - // the mouse so that it also receives the events of gestures - // which started inside the viewport but ended outside of it. - QCoreApplication::sendEvent(m_flickable->canvas(), &mouseEvent); -} - -QQuickItem* QtFlickProvider::contentItem() -{ - ASSERT(m_contentItem); - return m_contentItem; -} - -QDeclarativeListProperty<QObject> QtFlickProvider::flickableData() -{ - return m_flickableData.read(m_flickable).value<QDeclarativeListProperty<QObject> >(); -} - -QPointF QtFlickProvider::contentPos() const -{ - qreal x = m_contentX.read(m_flickable).value<qreal>(); - qreal y = m_contentY.read(m_flickable).value<qreal>(); - return QPointF(x, y); -} -void QtFlickProvider::setContentPos(const QPointF& pos) -{ - m_contentX.write(m_flickable, pos.x()); - m_contentY.write(m_flickable, pos.y()); -} - -QSizeF QtFlickProvider::viewportSize() const -{ - qreal width = m_flickable->width(); - qreal height = m_flickable->height(); - - return QSizeF(width, height); -} - -void QtFlickProvider::setViewportSize(const QSizeF& size) -{ - ASSERT(size.isValid()); - m_flickable->setWidth(size.width()); - m_flickable->setHeight(size.height()); -} - -void QtFlickProvider::returnToBounds() -{ - m_returnToBoundsMethod.invoke(m_flickable, Qt::DirectConnection); -} - -void QtFlickProvider::cancelFlick() -{ - m_cancelFlickMethod.invoke(m_flickable, Qt::DirectConnection); -} - -bool QtFlickProvider::isMoving() const -{ - return m_moving.read(m_flickable).value<bool>(); -} - -bool QtFlickProvider::isDragging() const -{ - return m_dragging.read(m_flickable).value<bool>(); -} - -bool QtFlickProvider::isFlicking() const -{ - return m_flicking.read(m_flickable).value<bool>(); -} - -qreal QtFlickProvider::contentWidth() const -{ - return m_contentWidth.read(m_flickable).value<qreal>(); -} - -void QtFlickProvider::setContentWidth(qreal width) -{ - m_contentWidth.write(m_flickable, width); -} - -qreal QtFlickProvider::contentHeight() const -{ - return m_contentHeight.read(m_flickable).value<qreal>(); -} - -void QtFlickProvider::setContentHeight(qreal height) -{ - m_contentHeight.write(m_flickable, height); -} - -qreal QtFlickProvider::contentX() const -{ - return m_contentX.read(m_flickable).value<qreal>(); -} - -void QtFlickProvider::setContentX(qreal x) -{ - m_contentX.write(m_flickable, x); -} - -qreal QtFlickProvider::contentY() const -{ - return m_contentY.read(m_flickable).value<qreal>(); -} - -void QtFlickProvider::setContentY(qreal y) -{ - m_contentY.write(m_flickable, y); -} diff --git a/Source/WebKit2/UIProcess/qt/QtFlickProvider.h b/Source/WebKit2/UIProcess/qt/QtFlickProvider.h deleted file mode 100644 index 275810bbf..000000000 --- a/Source/WebKit2/UIProcess/qt/QtFlickProvider.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 QtFlickProvider_h -#define QtFlickProvider_h - -#include <QDeclarativeListProperty> -#include <QMetaMethod> -#include <QMetaProperty> -#include <QObject> - -QT_BEGIN_NAMESPACE -class QPointF; -class QSizeF; -class QQuickItem; -class QQuickWebPage; -class QQuickWebView; -class QTouchEvent; -QT_END_NAMESPACE - -class QtFlickProvider : public QObject { - Q_OBJECT -public: - QtFlickProvider(QQuickWebView* viewItem, QQuickWebPage* pageItem); - - void handleTouchFlickEvent(QTouchEvent*); - - QQuickItem* contentItem(); - QDeclarativeListProperty<QObject> flickableData(); - - QPointF contentPos() const; - void setContentPos(const QPointF&); - - QSizeF viewportSize() const; - void setViewportSize(const QSizeF&); - - void returnToBounds(); - void cancelFlick(); - - bool isMoving() const; - bool isDragging() const; - bool isFlicking() const; - - qreal contentWidth() const; - void setContentWidth(qreal); - qreal contentHeight() const; - void setContentHeight(qreal); - qreal contentX() const; - void setContentX(qreal); - qreal contentY() const; - void setContentY(qreal); - -Q_SIGNALS: - void contentWidthChanged(); - void contentHeightChanged(); - void contentXChanged(); - void contentYChanged(); - void movementStarted(); - void movementEnded(); - void flickingChanged(); - void draggingChanged(); - -private: - QMetaMethod m_returnToBoundsMethod; - QMetaMethod m_cancelFlickMethod; - - QMetaProperty m_contentWidth; - QMetaProperty m_contentHeight; - QMetaProperty m_contentX; - QMetaProperty m_contentY; - - QMetaProperty m_moving; - QMetaProperty m_dragging; - QMetaProperty m_flicking; - - QMetaProperty m_flickableData; - - QQuickItem* m_contentItem; - QQuickItem* m_flickable; -}; - -#endif // QtFlickProvider_h diff --git a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp index 0c62452c6..3c2196b04 100644 --- a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.cpp @@ -46,4 +46,4 @@ QtViewportInteractionEngine* QtGestureRecognizer::interactionEngine() return m_eventHandler->interactionEngine(); } -} +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h index 4c191f6e2..5af3ba6b5 100644 --- a/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h +++ b/Source/WebKit2/UIProcess/qt/QtGestureRecognizer.h @@ -26,11 +26,10 @@ #ifndef QtGestureRecognizer_h #define QtGestureRecognizer_h -class QtWebPageEventHandler; - namespace WebKit { class QtViewportInteractionEngine; +class QtWebPageEventHandler; class QtGestureRecognizer { public: @@ -50,6 +49,6 @@ protected: QtViewportInteractionEngine* interactionEngine(); }; -} +} // namespace WebKit #endif /* QtGestureRecognizer_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp index d7049cb3b..8e9ab2efd 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.cpp @@ -21,22 +21,27 @@ #include "config.h" #include "QtPageClient.h" +#include "DrawingAreaProxy.h" +#include "LayerTreeContext.h" #include "QtWebPageEventHandler.h" #include "QtWebUndoController.h" +#include "ShareableBitmap.h" #include "WebContextMenuProxyQt.h" #include "WebEditCommandProxy.h" #include "WebPopupMenuProxyQt.h" #include "qquickwebview_p.h" #include "qquickwebview_p_p.h" #include <QGuiApplication> +#include <QQuickCanvas> #include <WebCore/Cursor.h> #include <WebCore/DragData.h> #include <WebCore/FloatRect.h> #include <WebCore/NotImplemented.h> -using namespace WebKit; using namespace WebCore; +namespace WebKit { + QtPageClient::QtPageClient() : m_webView(0) , m_eventHandler(0) @@ -85,9 +90,9 @@ void QtPageClient::didChangeContentsSize(const IntSize& newSize) QQuickWebViewPrivate::get(m_webView)->didChangeContentsSize(newSize); } -void QtPageClient::didChangeViewportProperties(const WebCore::ViewportArguments& args) +void QtPageClient::didChangeViewportProperties(const WebCore::ViewportAttributes& attr) { - QQuickWebViewPrivate::get(m_webView)->didChangeViewportProperties(args); + QQuickWebViewPrivate::get(m_webView)->didChangeViewportProperties(attr); } void QtPageClient::startDrag(const WebCore::DragData& dragData, PassRefPtr<ShareableBitmap> dragImage) @@ -270,6 +275,11 @@ bool QtPageClient::isViewVisible() { if (!m_webView) return false; + + // FIXME: this is a workaround while QWindow::isExposed() is not ready. + if (m_webView->canvas() && m_webView->canvas()->windowState() == Qt::WindowMinimized) + return false; + return m_webView->isVisible() && m_webView->page()->isVisible(); } @@ -294,3 +304,4 @@ void QtPageClient::updateAcceleratedCompositingMode(const LayerTreeContext&) // FIXME: Implement. } +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtPageClient.h b/Source/WebKit2/UIProcess/qt/QtPageClient.h index f09db8243..e33dadf61 100644 --- a/Source/WebKit2/UIProcess/qt/QtPageClient.h +++ b/Source/WebKit2/UIProcess/qt/QtPageClient.h @@ -21,24 +21,24 @@ #ifndef QtPageClient_h #define QtPageClient_h -#include "DrawingAreaProxy.h" -#include "LayerTreeContext.h" #include "PageClient.h" -#include "ShareableBitmap.h" -#include "ViewportArguments.h" -class QtWebPageEventHandler; -class QtWebUndoController; class QQuickWebView; -using namespace WebKit; +namespace WebKit { + +class DrawingAreaProxy; +class LayerTreeContext; +class QtWebPageEventHandler; +class QtWebUndoController; +class ShareableBitmap; -class QtPageClient : public WebKit::PageClient { +class QtPageClient : public PageClient { public: QtPageClient(); ~QtPageClient(); - void initialize(QQuickWebView*, QtWebPageEventHandler*, QtWebUndoController*); + void initialize(QQuickWebView*, QtWebPageEventHandler*, WebKit::QtWebUndoController*); // QQuickWebView. virtual void setViewNeedsDisplay(const WebCore::IntRect&); @@ -48,7 +48,7 @@ public: virtual void didReceiveMessageFromNavigatorQtObject(const String&); virtual void pageDidRequestScroll(const WebCore::IntPoint&); virtual void didChangeContentsSize(const WebCore::IntSize&); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); virtual void processDidCrash(); virtual void didRelaunchProcess(); virtual PassOwnPtr<DrawingAreaProxy> createDrawingAreaProxy(); @@ -98,7 +98,9 @@ public: virtual void didFindZoomableArea(const WebCore::IntPoint&, const WebCore::IntRect&); virtual void updateTextInputState(); virtual void doneWithGestureEvent(const WebGestureEvent&, bool wasEventHandled); +#if ENABLE(TOUCH_EVENTS) virtual void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled); +#endif private: QQuickWebView* m_webView; @@ -106,4 +108,6 @@ private: QtWebUndoController* m_undoController; }; +} // namespace WebKit + #endif /* QtPageClient_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp index be17aacbf..118373844 100644 --- a/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.cpp @@ -23,11 +23,10 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" - #include "QtPanGestureRecognizer.h" +#include "QtViewportInteractionEngine.h" #include "QtWebPageEventHandler.h" -#include <QTouchEvent> namespace WebKit { @@ -37,71 +36,58 @@ QtPanGestureRecognizer::QtPanGestureRecognizer(QtWebPageEventHandler* eventHandl reset(); } -bool QtPanGestureRecognizer::recognize(const QTouchEvent* event) +bool QtPanGestureRecognizer::update(const QTouchEvent::TouchPoint& touchPoint, qint64 eventTimestampMillis) { if (!interactionEngine()) return false; - // Pan gesture always starts on TouchBegin unless the engine is suspended, or - // we ignored the event. - if (m_state == NoGesture && event->type() != QEvent::TouchBegin) - return false; - - // Having multiple touch points cancel the panning gesture. - if (event->touchPoints().size() > 1) { - if (m_state == GestureRecognized) - interactionEngine()->panGestureCancelled(); - reset(); - return false; - } - - const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first(); + m_lastPosition = touchPoint.pos(); + m_lastEventTimestampMillis = eventTimestampMillis; - switch (event->type()) { - case QEvent::TouchBegin: - ASSERT(m_state == NoGesture); + switch (m_state) { + case NoGesture: m_state = GestureRecognitionStarted; - m_firstPosition = touchPoint.screenPos(); - m_touchBegin.reset(new QTouchEvent(*event)); - interactionEngine()->panGestureCancelled(); + m_firstScreenPosition = touchPoint.scenePos(); + interactionEngine()->cancelScrollAnimation(); return false; - case QEvent::TouchUpdate: { - ASSERT(m_state != NoGesture); - if (m_state == GestureRecognitionStarted) { - // To start the gesture, the delta from start in screen coordinates - // must be bigger than the trigger threshold. - QPointF totalOffsetFromStart(touchPoint.screenPos() - m_firstPosition); - if (qAbs(totalOffsetFromStart.x()) < panningInitialTriggerDistanceThreshold && qAbs(totalOffsetFromStart.y()) < panningInitialTriggerDistanceThreshold) - return false; + case GestureRecognitionStarted: { + // To start the gesture, the delta from start in screen coordinates + // must be bigger than the trigger threshold. + QPointF totalOffsetFromStart(touchPoint.scenePos() - m_firstScreenPosition); + if (qAbs(totalOffsetFromStart.x()) < panningInitialTriggerDistanceThreshold && qAbs(totalOffsetFromStart.y()) < panningInitialTriggerDistanceThreshold) + return false; - m_state = GestureRecognized; - ASSERT(m_touchBegin); - interactionEngine()->panGestureStarted(m_touchBegin.data()); - } - - ASSERT(m_state == GestureRecognized); - interactionEngine()->panGestureRequestUpdate(event); + m_state = GestureRecognized; + interactionEngine()->panGestureStarted(touchPoint.pos(), eventTimestampMillis); return true; } - case QEvent::TouchEnd: - if (m_state == GestureRecognized) { - interactionEngine()->panGestureEnded(event); - reset(); - return true; - } - ASSERT(m_state == GestureRecognitionStarted); - reset(); - return false; + case GestureRecognized: + interactionEngine()->panGestureRequestUpdate(touchPoint.pos(), eventTimestampMillis); + return true; default: ASSERT_NOT_REACHED(); } return false; } -void QtPanGestureRecognizer::reset() +void QtPanGestureRecognizer::finish(const QTouchEvent::TouchPoint& touchPoint, qint64 eventTimestampMillis) +{ + if (m_state == NoGesture) + return; + + ASSERT(interactionEngine()); + interactionEngine()->panGestureEnded(touchPoint.pos(), eventTimestampMillis); + reset(); +} + +void QtPanGestureRecognizer::cancel() { - QtGestureRecognizer::reset(); - m_firstPosition = QPointF(); + if (m_state == NoGesture) + return; + + interactionEngine()->panGestureEnded(m_lastPosition, m_lastEventTimestampMillis); + interactionEngine()->panGestureCancelled(); + reset(); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.h b/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.h index e1e9ff3fd..bf3da4cd6 100644 --- a/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.h +++ b/Source/WebKit2/UIProcess/qt/QtPanGestureRecognizer.h @@ -27,14 +27,8 @@ #define QtPanGestureRecognizer_h #include "QtGestureRecognizer.h" - #include <QPointF> -#include <QScopedPointer> -#include <QtCore/QtGlobal> - -QT_BEGIN_NAMESPACE -class QTouchEvent; -QT_END_NAMESPACE +#include <QTouchEvent> namespace WebKit { @@ -43,12 +37,14 @@ const qreal panningInitialTriggerDistanceThreshold = 5.; class QtPanGestureRecognizer : public QtGestureRecognizer { public: QtPanGestureRecognizer(QtWebPageEventHandler*); - bool recognize(const QTouchEvent*); - void reset(); + bool update(const QTouchEvent::TouchPoint&, qint64 eventTimestampMillis); + void finish(const QTouchEvent::TouchPoint&, qint64 eventTimestampMillis); + void cancel(); private: - QPointF m_firstPosition; - QScopedPointer<QTouchEvent> m_touchBegin; + QPointF m_firstScreenPosition; + QPointF m_lastPosition; + qint64 m_lastEventTimestampMillis; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp index 7699ad366..0d57ffa05 100644 --- a/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "QtPinchGestureRecognizer.h" +#include "QtViewportInteractionEngine.h" #include "QtWebPageEventHandler.h" #include <QtCore/QLineF> @@ -33,17 +34,6 @@ namespace WebKit { const qreal pinchInitialTriggerDistanceThreshold = 5.; -static inline int findTouchPointIndex(const QList<QTouchEvent::TouchPoint>& touchPoints, const QtPinchGestureRecognizer::TouchPointInformation& pointInformation) -{ - const int touchCount = touchPoints.size(); - for (int i = 0; i < touchCount; ++i) { - const QTouchEvent::TouchPoint& touchPoint = touchPoints.at(i); - if (touchPoint.id() == pointInformation.id) - return i; - } - return -1; -} - static inline QPointF computePinchCenter(const QTouchEvent::TouchPoint& point1, const QTouchEvent::TouchPoint& point2) { return (point1.pos() + point2.pos()) / 2.0f; @@ -55,103 +45,60 @@ QtPinchGestureRecognizer::QtPinchGestureRecognizer(QtWebPageEventHandler* eventH reset(); } -bool QtPinchGestureRecognizer::recognize(const QTouchEvent* event) +bool QtPinchGestureRecognizer::update(const QTouchEvent::TouchPoint& point1, const QTouchEvent::TouchPoint& point2) { - if (!interactionEngine()) + ASSERT(interactionEngine()); + const qreal currentFingerDistance = QLineF(point1.screenPos(), point2.screenPos()).length(); + switch (m_state) { + case NoGesture: + m_initialFingerDistance = currentFingerDistance; + m_state = GestureRecognitionStarted; return false; + case GestureRecognitionStarted: { + const qreal pinchDistance = qAbs(currentFingerDistance - m_initialFingerDistance); + if (pinchDistance < pinchInitialTriggerDistanceThreshold) + return false; + m_state = GestureRecognized; + interactionEngine()->pinchGestureStarted(computePinchCenter(point1, point2)); - const QList<QTouchEvent::TouchPoint>& touchPoints = event->touchPoints(); - if (touchPoints.size() < 2) { - if (m_state == GestureRecognized) - interactionEngine()->pinchGestureEnded(); - reset(); - return false; - } + // We reset the initial span distance to the current distance of the + // touch points in order to avoid the jump caused by the events which + // were skipped between the recognition start and the actual recognition. + m_initialFingerDistance = currentFingerDistance; - switch (event->type()) { - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - switch (m_state) { - case NoGesture: - initializeGesture(touchPoints); - return false; - case GestureRecognitionStarted: - case GestureRecognized: - ASSERT(m_point1.isValid()); - ASSERT(m_point2.isValid()); - - const int point1Index = findTouchPointIndex(touchPoints, m_point1); - if (point1Index < 0) { - reset(); - return false; - } - const int point2Index = findTouchPointIndex(touchPoints, m_point2); - if (point2Index < 0) { - reset(); - return false; - } - - const QTouchEvent::TouchPoint& point1 = touchPoints.at(point1Index); - const QTouchEvent::TouchPoint& point2 = touchPoints.at(point2Index); - if (m_state == GestureRecognitionStarted) { - // FIXME: The gesture should only start if the touch events were not accepted at the start of the touch sequence. - const qreal pinchDistance = qAbs(QLineF(point1.screenPos(), point2.screenPos()).length() - QLineF(m_point1.initialScreenPosition, m_point2.initialScreenPosition).length()); - if (pinchDistance < pinchInitialTriggerDistanceThreshold) - return false; - m_state = GestureRecognized; - interactionEngine()->pinchGestureStarted(computePinchCenter(point1, point2)); - - // We reset the initial position to the previous position in order to avoid the jump caused - // by skipping all the events between the beginning and when the threshold is hit. - m_point1.initialPosition = point1.lastPos(); - m_point1.initialScreenPosition = point1.lastScreenPos(); - m_point2.initialPosition = point2.lastPos(); - m_point2.initialScreenPosition = point2.lastScreenPos(); - } - ASSERT(m_state == GestureRecognized); - const qreal currentSpanDistance = QLineF(point1.screenPos(), point2.screenPos()).length(); - const qreal initialSpanDistance = QLineF(m_point1.initialScreenPosition, m_point2.initialScreenPosition).length(); - const qreal totalScaleFactor = currentSpanDistance / initialSpanDistance; - const QPointF touchCenterInViewCoordinates = computePinchCenter(point1, point2); - interactionEngine()->pinchGestureRequestUpdate(touchCenterInViewCoordinates, totalScaleFactor); - return true; - break; - } - break; - case QEvent::TouchEnd: - if (m_state == GestureRecognized) { - interactionEngine()->pinchGestureEnded(); - reset(); - return true; - } - reset(); + // fall through + } + case GestureRecognized: + const qreal totalScaleFactor = currentFingerDistance / m_initialFingerDistance; + const QPointF touchCenterInViewCoordinates = computePinchCenter(point1, point2); + interactionEngine()->pinchGestureRequestUpdate(touchCenterInViewCoordinates, totalScaleFactor); + return true; break; - default: - ASSERT_NOT_REACHED(); } + ASSERT_NOT_REACHED(); return false; } -void QtPinchGestureRecognizer::reset() +void QtPinchGestureRecognizer::finish() { - QtGestureRecognizer::reset(); - m_point1 = TouchPointInformation(); - m_point2 = TouchPointInformation(); + if (m_state == NoGesture) + return; + + ASSERT(interactionEngine()); + interactionEngine()->pinchGestureEnded(); + reset(); } -void QtPinchGestureRecognizer::initializeGesture(const QList<QTouchEvent::TouchPoint>& touchPoints) +void QtPinchGestureRecognizer::cancel() { - ASSERT(!m_point1.isValid()); - ASSERT(!m_point2.isValid()); - - m_state = GestureRecognitionStarted; + if (m_state == NoGesture) + return; - m_point1 = TouchPointInformation(touchPoints.at(0)); - m_point2 = TouchPointInformation(touchPoints.at(1)); - - ASSERT(m_point1.isValid()); - ASSERT(m_point2.isValid()); + ASSERT(interactionEngine()); + interactionEngine()->pinchGestureCancelled(); + reset(); } -} +} // namespace WebKit + diff --git a/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.h b/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.h index 7dd3d911b..5fbfc095d 100644 --- a/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.h +++ b/Source/WebKit2/UIProcess/qt/QtPinchGestureRecognizer.h @@ -27,15 +27,9 @@ #define QtPinchGestureRecognizer_h #include "QtGestureRecognizer.h" - #include <QTouchEvent> -#include <QtCore/QList> #include <QtCore/QPointF> -QT_BEGIN_NAMESPACE -class QTouchEvent; -QT_END_NAMESPACE - namespace WebKit { class QtPinchGestureRecognizer : public QtGestureRecognizer { @@ -51,33 +45,14 @@ public: }; QtPinchGestureRecognizer(QtWebPageEventHandler*); - bool recognize(const QTouchEvent*); - void reset(); + bool update(const QTouchEvent::TouchPoint& point1, const QTouchEvent::TouchPoint& point2); + void finish(); + void cancel(); private: - void initializeGesture(const QList<QTouchEvent::TouchPoint>& touchPoints); - - TouchPointInformation m_point1; - TouchPointInformation m_point2; + qreal m_initialFingerDistance; }; -inline QtPinchGestureRecognizer::TouchPointInformation::TouchPointInformation() - : id(-1) -{ -} - -inline QtPinchGestureRecognizer::TouchPointInformation::TouchPointInformation(const QTouchEvent::TouchPoint& touchPoint) - : id(touchPoint.id()) - , initialScreenPosition(touchPoint.screenPos()) - , initialPosition(touchPoint.pos()) -{ -} - -inline bool QtPinchGestureRecognizer::TouchPointInformation::isValid() const -{ - return id >= 0; -} - -} +} // namespace WebKit #endif /* QtPinchGestureRecognizer_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp b/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp index 7032220d5..007659b2f 100644 --- a/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp +++ b/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp @@ -33,86 +33,57 @@ namespace WebKit { QtTapGestureRecognizer::QtTapGestureRecognizer(QtWebPageEventHandler* eventHandler) : QtGestureRecognizer(eventHandler) - , m_tapState(NoTap) + , m_candidate(Invalid) { } -bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTimestampMillis) +bool QtTapGestureRecognizer::withinDistance(const QTouchEvent::TouchPoint& touchPoint, int distance) { - if (event->touchPoints().size() != 1) { - reset(); - return false; - } + return QLineF(touchPoint.screenPos(), m_lastTouchPoint.screenPos()).length() < distance; +} - switch (event->type()) { +bool QtTapGestureRecognizer::update(QEvent::Type eventType, const QTouchEvent::TouchPoint& touchPoint) +{ + ASSERT(m_eventHandler); + + switch (eventType) { case QEvent::TouchBegin: - ASSERT(m_tapState == NoTap); - ASSERT(!m_tapAndHoldTimer.isActive()); + m_doubleTapTimer.stop(); // Cancel other pending single tap event. + ASSERT(!m_tapAndHoldTimer.isActive()); m_tapAndHoldTimer.start(tapAndHoldTime, this); - if (m_doubleTapTimer.isActive()) { - // Might be double tap. - ASSERT(m_touchBeginEventForTap); - m_doubleTapTimer.stop(); - QPointF lastPosition = m_touchBeginEventForTap->touchPoints().first().screenPos(); - QPointF newPosition = event->touchPoints().first().screenPos(); - if (QLineF(lastPosition, newPosition).length() < maxDoubleTapDistance) - m_tapState = DoubleTapCandidate; - else { - // Received a new tap, that is unrelated to the previous one. - tapTimeout(); - m_tapState = SingleTapStarted; - } - } 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); + if (m_lastTouchPoint.id() != -1 && withinDistance(touchPoint, maxDoubleTapDistance)) + m_candidate = DoubleTapCandidate; + else { + m_candidate = SingleTapCandidate; + // The below in facts resets any previous single tap event. + m_highlightTimer.start(highlightDelay, this); + m_lastTouchPoint = touchPoint; + m_doubleTapTimer.start(maxDoubleTapInterval, this); } break; + case QEvent::TouchUpdate: // If the touch point moves further than the threshold, we cancel the tap gesture. - if (m_tapState == SingleTapStarted) { - const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first(); - QPointF offset(touchPoint.scenePos() - m_touchBeginEventForTap->touchPoints().first().scenePos()); - const qreal distX = qAbs(offset.x()); - const qreal distY = qAbs(offset.y()); - if (distX > initialTriggerDistanceThreshold || distY > initialTriggerDistanceThreshold) - reset(); - } + if (m_candidate != Invalid && !withinDistance(touchPoint, maxPanDistance)) + reset(); break; + case QEvent::TouchEnd: m_tapAndHoldTimer.stop(); - m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); - switch (m_tapState) { - case DoubleTapCandidate: - { - ASSERT(!m_doubleTapTimer.isActive()); - m_tapState = NoTap; - - const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first(); - QPointF startPosition = touchPoint.startScreenPos(); - QPointF endPosition = touchPoint.screenPos(); - if (QLineF(endPosition, startPosition).length() < maxDoubleTapDistance && m_eventHandler) - m_eventHandler->handleDoubleTapEvent(touchPoint); - break; - } - case SingleTapStarted: - ASSERT(!m_doubleTapTimer.isActive()); - m_doubleTapTimer.start(doubleClickInterval, this); - m_tapState = NoTap; - break; - case TapAndHold: - m_tapState = NoTap; - break; - default: + if (m_candidate == Invalid) break; + + if (m_candidate == DoubleTapCandidate) { + m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); + m_eventHandler->handleDoubleTapEvent(touchPoint); + reset(); } + break; + default: break; } @@ -120,36 +91,63 @@ bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTim return false; } -void QtTapGestureRecognizer::tapTimeout() +void QtTapGestureRecognizer::cancel() +{ + if (m_candidate == Invalid) + return; + + reset(); +} + +void QtTapGestureRecognizer::highlightTimeout() +{ + m_highlightTimer.stop(); + + if (m_candidate != SingleTapCandidate) + return; + + ASSERT(m_lastTouchPoint.id() != -1); + m_eventHandler->handlePotentialSingleTapEvent(m_lastTouchPoint); +} + +void QtTapGestureRecognizer::singleTapTimeout() { m_doubleTapTimer.stop(); - m_eventHandler->handleSingleTapEvent(m_touchBeginEventForTap->touchPoints().at(0)); - m_touchBeginEventForTap.clear(); + + // Finger is still pressed, ignore. + if (m_tapAndHoldTimer.isActive()) + return; + + ASSERT(m_lastTouchPoint.id() != -1); + + if (m_candidate == SingleTapCandidate) { + m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); + m_eventHandler->handleSingleTapEvent(m_lastTouchPoint); + } + reset(); } void QtTapGestureRecognizer::tapAndHoldTimeout() { - ASSERT(m_touchBeginEventForTap); m_tapAndHoldTimer.stop(); + + ASSERT(m_lastTouchPoint.id() != -1); #if 0 // No support for synthetic context menus in WK2 yet. - QTouchEvent::TouchPoint tapPoint = m_touchBeginEventForTap->touchPoints().at(0); - WebGestureEvent gesture(WebEvent::GestureTapAndHold, tapPoint.pos().toPoint(), tapPoint.screenPos().toPoint(), WebEvent::Modifiers(0), 0); - if (m_webPageProxy) - m_webPageProxy->handleGestureEvent(gesture); + m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); + m_eventHandler->handleTapAndHoldEvent(m_lastTouchPoint); #endif - m_touchBeginEventForTap.clear(); - m_tapState = TapAndHold; - - ASSERT(!m_doubleTapTimer.isActive()); - m_doubleTapTimer.stop(); + reset(); } void QtTapGestureRecognizer::reset() { - m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); + if (m_candidate != Invalid) + m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint()); - m_tapState = NoTap; - m_touchBeginEventForTap.clear(); + m_candidate = Invalid; + m_lastTouchPoint.setId(-1); + m_highlightTimer.stop(); + m_doubleTapTimer.stop(); m_tapAndHoldTimer.stop(); QtGestureRecognizer::reset(); @@ -158,8 +156,10 @@ void QtTapGestureRecognizer::reset() void QtTapGestureRecognizer::timerEvent(QTimerEvent* ev) { int timerId = ev->timerId(); - if (timerId == m_doubleTapTimer.timerId()) - tapTimeout(); + if (timerId == m_highlightTimer.timerId()) + highlightTimeout(); + else if (timerId == m_doubleTapTimer.timerId()) + singleTapTimeout(); else if (timerId == m_tapAndHoldTimer.timerId()) tapAndHoldTimeout(); else diff --git a/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h b/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h index a4ec41eff..2cbcf9375 100644 --- a/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h +++ b/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h @@ -27,48 +27,47 @@ #define QtTapGestureRecognizer_h #include "QtGestureRecognizer.h" - +#include <QTouchEvent> #include <QtCore/QBasicTimer> #include <QtCore/QObject> -#include <QtCore/QtGlobal> -#include <wtf/OwnPtr.h> - -QT_BEGIN_NAMESPACE -class QTouchEvent; -QT_END_NAMESPACE // FIXME: These constants should possibly depend on DPI. -const qreal initialTriggerDistanceThreshold = 5; -const qreal maxDoubleTapDistance = 120; +const int maxPanDistance = 10; +const int maxDoubleTapDistance = 120; const int tapAndHoldTime = 800; -const int doubleClickInterval = 400; - -class QtWebPageEventHandler; +const int maxDoubleTapInterval = 400; +const int highlightDelay = 80; namespace WebKit { +class QtWebPageEventHandler; + class QtTapGestureRecognizer : public QObject, private QtGestureRecognizer { public: QtTapGestureRecognizer(QtWebPageEventHandler*); - bool recognize(const QTouchEvent*, qint64 eventTimestampMillis); - void reset(); + bool update(QEvent::Type eventType, const QTouchEvent::TouchPoint&); + void cancel(); protected: void timerEvent(QTimerEvent*); - void tapTimeout(); + void highlightTimeout(); + void singleTapTimeout(); void tapAndHoldTimeout(); private: + void reset(); + bool withinDistance(const QTouchEvent::TouchPoint&, int distance); + + QBasicTimer m_highlightTimer; QBasicTimer m_doubleTapTimer; QBasicTimer m_tapAndHoldTimer; - OwnPtr<QTouchEvent> m_touchBeginEventForTap; + QTouchEvent::TouchPoint m_lastTouchPoint; enum { - NoTap, - SingleTapStarted, + Invalid, + SingleTapCandidate, DoubleTapCandidate, - TapAndHold - } m_tapState; + } m_candidate; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp index c838767b6..09f632456 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp +++ b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp @@ -22,14 +22,13 @@ #include "config.h" #include "QtViewportInteractionEngine.h" -#include "PassOwnPtr.h" -#include "QtFlickProvider.h" #include "qquickwebpage_p.h" #include "qquickwebview_p.h" #include <QPointF> #include <QTransform> #include <QWheelEvent> #include <QtQuick/qquickitem.h> +#include <wtf/PassOwnPtr.h> namespace WebKit { @@ -86,26 +85,32 @@ public: } // Make sure that tiles all around the viewport will be requested. - emit engine->contentWasMoved(QPointF()); + emit engine->contentViewportChanged(QPointF()); } private: QtViewportInteractionEngine* const engine; }; +// A floating point compare with absolute error. +static inline bool fuzzyCompare(qreal a, qreal b, qreal epsilon) +{ + return qAbs(a - b) < epsilon; +} + inline qreal QtViewportInteractionEngine::cssScaleFromItem(qreal itemScale) { - return itemScale / m_constraints.devicePixelRatio; + return itemScale / m_devicePixelRatio; } inline qreal QtViewportInteractionEngine::itemScaleFromCSS(qreal cssScale) { - return cssScale * m_constraints.devicePixelRatio; + return cssScale * m_devicePixelRatio; } inline qreal QtViewportInteractionEngine::itemCoordFromCSS(qreal value) { - return value * m_constraints.devicePixelRatio; + return value * m_devicePixelRatio; } inline QRectF QtViewportInteractionEngine::itemRectFromCSS(const QRectF& cssRect) @@ -120,22 +125,22 @@ inline QRectF QtViewportInteractionEngine::itemRectFromCSS(const QRectF& cssRect return itemRect; } -QtViewportInteractionEngine::QtViewportInteractionEngine(QQuickWebView* viewport, QQuickWebPage* content, QtFlickProvider* flickProvider) +QtViewportInteractionEngine::QtViewportInteractionEngine(QQuickWebView* viewport, QQuickWebPage* content) : m_viewport(viewport) , m_content(content) - , m_flickProvider(flickProvider) , m_suspendCount(0) , m_hasSuspendedContent(false) , m_hadUserInteraction(false) , m_scaleAnimation(new ScaleAnimation(this)) , m_pinchStartScale(-1) + , m_zoomOutScale(0.0) { reset(); connect(m_content, SIGNAL(widthChanged()), SLOT(itemSizeChanged()), Qt::DirectConnection); connect(m_content, SIGNAL(heightChanged()), SLOT(itemSizeChanged()), Qt::DirectConnection); - connect(m_flickProvider, SIGNAL(movementStarted()), SLOT(flickableMoveStarted()), Qt::DirectConnection); - connect(m_flickProvider, SIGNAL(movementEnded()), SLOT(flickableMoveEnded()), Qt::DirectConnection); + connect(m_viewport, SIGNAL(movementStarted()), SLOT(flickableMoveStarted()), Qt::DirectConnection); + connect(m_viewport, SIGNAL(movementEnded()), SLOT(flickableMoveEnded()), Qt::DirectConnection); connect(m_scaleAnimation, SIGNAL(valueChanged(QVariant)), SLOT(scaleAnimationValueChanged(QVariant)), Qt::DirectConnection); @@ -149,15 +154,15 @@ QtViewportInteractionEngine::~QtViewportInteractionEngine() qreal QtViewportInteractionEngine::innerBoundedCSSScale(qreal cssScale) { - return qBound(m_constraints.minimumScale, cssScale, m_constraints.maximumScale); + return qBound(m_minimumScale, cssScale, m_maximumScale); } qreal QtViewportInteractionEngine::outerBoundedCSSScale(qreal cssScale) { - if (m_constraints.isUserScalable) { + if (m_allowsUserScaling) { // Bounded by [0.1, 10.0] like the viewport meta code in WebCore. - qreal hardMin = qMax<qreal>(0.1, qreal(0.5) * m_constraints.minimumScale); - qreal hardMax = qMin<qreal>(10, qreal(2.0) * m_constraints.maximumScale); + qreal hardMin = qMax<qreal>(0.1, qreal(0.5) * m_minimumScale); + qreal hardMax = qMin<qreal>(10, qreal(2.0) * m_maximumScale); return qBound(hardMin, cssScale, hardMax); } return innerBoundedCSSScale(cssScale); @@ -178,7 +183,7 @@ void QtViewportInteractionEngine::setItemRectVisible(const QRectF& itemRect) // and add it to the page position (displacement on the flickable contentItem because of additional items). QPointF newPosition(m_content->pos() + (itemRect.topLeft() * itemScale)); - m_flickProvider->setContentPos(newPosition); + m_viewport->setContentPos(newPosition); } bool QtViewportInteractionEngine::animateItemRectVisible(const QRectF& itemRect) @@ -199,30 +204,30 @@ bool QtViewportInteractionEngine::animateItemRectVisible(const QRectF& itemRect) void QtViewportInteractionEngine::flickableMoveStarted() { - Q_ASSERT(m_flickProvider->isMoving()); + Q_ASSERT(m_viewport->isMoving()); m_scrollUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); - m_lastScrollPosition = m_flickProvider->contentPos(); - connect(m_flickProvider, SIGNAL(contentXChanged()), SLOT(flickableMovingPositionUpdate())); - connect(m_flickProvider, SIGNAL(contentYChanged()), SLOT(flickableMovingPositionUpdate())); + m_lastScrollPosition = m_viewport->contentPos(); + connect(m_viewport, SIGNAL(contentXChanged()), SLOT(flickableMovingPositionUpdate())); + connect(m_viewport, SIGNAL(contentYChanged()), SLOT(flickableMovingPositionUpdate())); } void QtViewportInteractionEngine::flickableMoveEnded() { - Q_ASSERT(!m_flickProvider->isMoving()); + Q_ASSERT(!m_viewport->isMoving()); // This method is called on the end of the pan or pan kinetic animation. m_scrollUpdateDeferrer.clear(); m_lastScrollPosition = QPointF(); - disconnect(m_flickProvider, SIGNAL(contentXChanged()), this, SLOT(flickableMovingPositionUpdate())); - disconnect(m_flickProvider, SIGNAL(contentYChanged()), this, SLOT(flickableMovingPositionUpdate())); + disconnect(m_viewport, SIGNAL(contentXChanged()), this, SLOT(flickableMovingPositionUpdate())); + disconnect(m_viewport, SIGNAL(contentYChanged()), this, SLOT(flickableMovingPositionUpdate())); } void QtViewportInteractionEngine::flickableMovingPositionUpdate() { - QPointF newPosition = m_flickProvider->contentPos(); + QPointF newPosition = m_viewport->contentPos(); - emit contentWasMoved(m_lastScrollPosition - newPosition); + emit contentViewportChanged(m_lastScrollPosition - newPosition); m_lastScrollPosition = newPosition; } @@ -231,6 +236,7 @@ void QtViewportInteractionEngine::scaleAnimationStateChanged(QAbstractAnimation: { switch (newState) { case QAbstractAnimation::Running: + m_viewport->cancelFlick(); if (!m_scaleUpdateDeferrer) m_scaleUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); break; @@ -253,33 +259,29 @@ void QtViewportInteractionEngine::wheelEvent(QWheelEvent* ev) if (scrollAnimationActive() || scaleAnimationActive() || pinchGestureActive()) return; // Ignore. - int delta = ev->delta(); - QPointF newPos = -m_content->pos(); - - // A delta that is not mod 120 indicates a device that is sending - // fine-resolution scroll events, so use the delta as number of wheel ticks - // and number of pixels to scroll. See also webkit.org/b/29601 - bool fullTick = !(delta % 120); + // A normal scroll-tick should have a delta of 120 (1/8) degrees. Convert this to + // local standard scroll step of 3 lines of 20 pixels. static const int cDefaultQtScrollStep = 20; static const int wheelScrollLines = 3; - int scrollLines = (fullTick) ? wheelScrollLines * cDefaultQtScrollStep : 1; + const int wheelTick = wheelScrollLines * cDefaultQtScrollStep; - delta = (fullTick) ? delta / 120.0f : delta; - delta *= scrollLines; + int pixelDelta = ev->delta() * (wheelTick / 120.f); + + QPointF newPosition = m_viewport->contentPos(); if (ev->orientation() == Qt::Horizontal) - newPos.rx() += delta; + newPosition.rx() -= pixelDelta; else - newPos.ry() += delta; + newPosition.ry() -= pixelDelta; QRectF endPosRange = computePosRangeForItemAtScale(m_content->contentsScale()); - QPointF currentPosition = m_flickProvider->contentPos(); - QPointF newPosition = -boundPosition(endPosRange.topLeft(), newPos, endPosRange.bottomRight()); - m_flickProvider->setContentPos(newPosition); + QPointF currentPosition = m_viewport->contentPos(); + newPosition = boundPosition(endPosRange.topLeft(), newPosition, endPosRange.bottomRight()); + m_viewport->setContentPos(newPosition); - emit contentWasMoved(currentPosition - newPosition); + emit contentViewportChanged(currentPosition - newPosition); } void QtViewportInteractionEngine::pagePositionRequest(const QPoint& pagePosition) @@ -298,6 +300,18 @@ void QtViewportInteractionEngine::pagePositionRequest(const QPoint& pagePosition setItemRectVisible(endVisibleContentRect); } +void QtViewportInteractionEngine::touchBegin() +{ + // Prevents resuming the page between the user's flicks of the page while the animation is running. + if (scrollAnimationActive()) + m_touchUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); +} + +void QtViewportInteractionEngine::touchEnd() +{ + m_touchUpdateDeferrer.clear(); +} + QRectF QtViewportInteractionEngine::computePosRangeForItemAtScale(qreal itemScale) const { const QSizeF contentItemSize = m_content->contentsSize() * itemScale; @@ -351,18 +365,19 @@ void QtViewportInteractionEngine::zoomToAreaGestureEnded(const QPointF& touchPoi if (scrollAnimationActive() || scaleAnimationActive()) return; - const int margin = 10; // We want at least a little bit or margin. + const int margin = 10; // We want at least a little bit of margin. QRectF endArea = itemRectFromCSS(targetArea.adjusted(-margin, -margin, margin, margin)); const QRectF viewportRect = m_viewport->boundingRect(); qreal targetCSSScale = cssScaleFromItem(viewportRect.size().width() / endArea.size().width()); qreal endItemScale = itemScaleFromCSS(innerBoundedCSSScale(qMin(targetCSSScale, qreal(2.5)))); + qreal currentScale = m_content->contentsScale(); // We want to end up with the target area filling the whole width of the viewport (if possible), // and centralized vertically where the user requested zoom. Thus our hotspot is the center of // the targetArea x-wise and the requested zoom position, y-wise. - const QPointF hotspot = QPointF(endArea.center().x(), touchPoint.y() * m_constraints.devicePixelRatio); + const QPointF hotspot = QPointF(endArea.center().x(), touchPoint.y() * m_devicePixelRatio); const QPointF viewportHotspot = viewportRect.center(); QPointF endPosition = hotspot * endItemScale - viewportHotspot; @@ -372,13 +387,57 @@ void QtViewportInteractionEngine::zoomToAreaGestureEnded(const QPointF& touchPoi QRectF endVisibleContentRect(endPosition / endItemScale, viewportRect.size() / endItemScale); + enum { ZoomIn, ZoomBack, ZoomOut, NoZoom } zoomAction = ZoomIn; + + if (!m_scaleStack.isEmpty()) { + // Zoom back out if attempting to scale to the same current scale, or + // attempting to continue scaling out from the inner most level. + // Use fuzzy compare with a fixed error to be able to deal with largish differences due to pixel rounding. + if (fuzzyCompare(endItemScale, currentScale, 0.01)) { + // If moving the viewport would expose more of the targetRect and move at least 40 pixels, update position but do not scale out. + QRectF currentContentRect(m_viewport->contentPos() / currentScale, viewportRect.size() / currentScale); + QRectF targetIntersection = endVisibleContentRect.intersected(targetArea); + if (!currentContentRect.contains(targetIntersection) && (qAbs(endVisibleContentRect.top() - currentContentRect.top()) >= 40 || qAbs(endVisibleContentRect.left() - currentContentRect.left()) >= 40)) + zoomAction = NoZoom; + else + zoomAction = ZoomBack; + } else if (fuzzyCompare(endItemScale, m_zoomOutScale, 0.01)) + zoomAction = ZoomBack; + else if (endItemScale < currentScale) + zoomAction = ZoomOut; + } + + switch (zoomAction) { + case ZoomIn: + m_scaleStack.append(ScaleStackItem(currentScale, m_viewport->contentPos().x())); + m_zoomOutScale = endItemScale; + break; + case ZoomBack: { + ScaleStackItem lastScale = m_scaleStack.takeLast(); + endItemScale = lastScale.scale; + // Recalculate endPosition and bound it according to new scale. + endPosition.setY(hotspot.y() * endItemScale - viewportHotspot.y()); + endPosition.setX(lastScale.xPosition); + endPosRange = computePosRangeForItemAtScale(endItemScale); + endPosition = boundPosition(endPosRange.topLeft(), endPosition, endPosRange.bottomRight()); + endVisibleContentRect = QRectF(endPosition / endItemScale, viewportRect.size() / endItemScale); + break; + } + case ZoomOut: + // Unstack all scale-levels deeper than the new level, so a zoom-back won't end up zooming in. + while (!m_scaleStack.isEmpty() && m_scaleStack.last().scale >= endItemScale) + m_scaleStack.removeLast(); + m_zoomOutScale = endItemScale; + break; + case NoZoom: + break; + } + animateItemRectVisible(endVisibleContentRect); } bool QtViewportInteractionEngine::ensureContentWithinViewportBoundary(bool immediate) { - ASSERT(m_suspendCount); - if (scrollAnimationActive() || scaleAnimationActive()) return false; @@ -407,29 +466,32 @@ void QtViewportInteractionEngine::reset() m_hadUserInteraction = false; - m_flickProvider->cancelFlick(); + m_allowsUserScaling = false; + m_minimumScale = 1; + m_maximumScale = 1; + m_devicePixelRatio = 1; + m_pinchStartScale = -1; + m_zoomOutScale = 0.0; + + m_viewport->cancelFlick(); m_scaleAnimation->stop(); m_scaleUpdateDeferrer.clear(); m_scrollUpdateDeferrer.clear(); + m_scaleStack.clear(); } -void QtViewportInteractionEngine::applyConstraints(const Constraints& constraints) +void QtViewportInteractionEngine::setCSSScaleBounds(qreal minimum, qreal maximum) { - // We always have to apply the constrains even if they didn't change, as - // the initial scale might need to be applied. + m_minimumScale = minimum; + m_maximumScale = maximum; +} +void QtViewportInteractionEngine::setCSSScale(qreal scale) +{ ViewportUpdateDeferrer guard(this); - m_constraints = constraints; - - if (!m_hadUserInteraction) { - qreal initialScale = innerBoundedCSSScale(m_constraints.initialScale); - m_content->setContentsScale(itemScaleFromCSS(initialScale)); - } - - // If the web app successively changes the viewport on purpose - // it wants to be in control and we should disable animations. - ensureContentWithinViewportBoundary(/* immediate */ true); + qreal newScale = innerBoundedCSSScale(scale); + m_content->setContentsScale(itemScaleFromCSS(newScale)); } qreal QtViewportInteractionEngine::currentCSSScale() @@ -439,30 +501,31 @@ qreal QtViewportInteractionEngine::currentCSSScale() bool QtViewportInteractionEngine::scrollAnimationActive() const { - return m_flickProvider->isFlicking(); + return m_viewport->isFlicking(); } bool QtViewportInteractionEngine::panGestureActive() const { - return m_flickProvider->isDragging(); + return m_viewport->isDragging(); } -void QtViewportInteractionEngine::panGestureStarted(const QTouchEvent* event) +void QtViewportInteractionEngine::panGestureStarted(const QPointF& position, qint64 eventTimestampMillis) { m_hadUserInteraction = true; - - ASSERT(event->type() == QEvent::TouchBegin); - - m_flickProvider->handleTouchFlickEvent(const_cast<QTouchEvent*>(event)); - m_lastPinchCenterInViewportCoordinates = event->touchPoints().first().pos(); + m_viewport->handleFlickableMousePress(position, eventTimestampMillis); + m_lastPinchCenterInViewportCoordinates = position; } -void QtViewportInteractionEngine::panGestureRequestUpdate(const QTouchEvent* event) +void QtViewportInteractionEngine::panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis) { - ASSERT(event->type() == QEvent::TouchUpdate); + m_viewport->handleFlickableMouseMove(position, eventTimestampMillis); + m_lastPinchCenterInViewportCoordinates = position; +} - m_flickProvider->handleTouchFlickEvent(const_cast<QTouchEvent*>(event)); - m_lastPinchCenterInViewportCoordinates = event->touchPoints().first().pos(); +void QtViewportInteractionEngine::panGestureEnded(const QPointF& position, qint64 eventTimestampMillis) +{ + m_viewport->handleFlickableMouseRelease(position, eventTimestampMillis); + m_lastPinchCenterInViewportCoordinates = position; } void QtViewportInteractionEngine::panGestureCancelled() @@ -474,19 +537,25 @@ void QtViewportInteractionEngine::panGestureCancelled() // back inside valid bounds. // When the pinch gesture ends, the content is positioned and scaled // back to valid boundaries. - m_flickProvider->cancelFlick(); + m_viewport->cancelFlick(); } -void QtViewportInteractionEngine::panGestureEnded(const QTouchEvent* event) +bool QtViewportInteractionEngine::scaleAnimationActive() const { - ASSERT(event->type() == QEvent::TouchEnd); - m_flickProvider->handleTouchFlickEvent(const_cast<QTouchEvent*>(event)); - m_lastPinchCenterInViewportCoordinates = event->touchPoints().first().pos(); + return m_scaleAnimation->state() == QAbstractAnimation::Running; } -bool QtViewportInteractionEngine::scaleAnimationActive() const +void QtViewportInteractionEngine::cancelScrollAnimation() { - return m_scaleAnimation->state() == QAbstractAnimation::Running; + ViewportUpdateDeferrer guard(this); + + // If the pan gesture recognizer receives a touch begin event + // during an ongoing kinetic scroll animation of a previous + // pan gesture, the animation is stopped and the content is + // immediately positioned back to valid boundaries. + + m_viewport->cancelFlick(); + ensureContentWithinViewportBoundary(/*immediate*/ true); } void QtViewportInteractionEngine::interruptScaleAnimation() @@ -502,12 +571,12 @@ bool QtViewportInteractionEngine::pinchGestureActive() const void QtViewportInteractionEngine::pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates) { - ASSERT(!m_suspendCount); - - if (!m_constraints.isUserScalable) + if (!m_allowsUserScaling) return; m_hadUserInteraction = true; + m_scaleStack.clear(); + m_zoomOutScale = 0.0; m_scaleUpdateDeferrer = adoptPtr(new ViewportUpdateDeferrer(this, ViewportUpdateDeferrer::DeferUpdateAndSuspendContent)); @@ -515,14 +584,14 @@ void QtViewportInteractionEngine::pinchGestureStarted(const QPointF& pinchCenter m_pinchStartScale = m_content->contentsScale(); // Reset the tiling look-ahead vector so that tiles all around the viewport will be requested on pinch-end. - emit contentWasMoved(QPointF()); + emit contentViewportChanged(QPointF()); } void QtViewportInteractionEngine::pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor) { ASSERT(m_suspendCount); - if (!m_constraints.isUserScalable) + if (!m_allowsUserScaling) return; // Changes of the center position should move the page even if the zoom factor @@ -537,14 +606,14 @@ void QtViewportInteractionEngine::pinchGestureRequestUpdate(const QPointF& pinch const QPointF positionDiff = pinchCenterInViewportCoordinates - m_lastPinchCenterInViewportCoordinates; m_lastPinchCenterInViewportCoordinates = pinchCenterInViewportCoordinates; - m_flickProvider->setContentPos(m_flickProvider->contentPos() - positionDiff); + m_viewport->setContentPos(m_viewport->contentPos() - positionDiff); } void QtViewportInteractionEngine::pinchGestureEnded() { ASSERT(m_suspendCount); - if (!m_constraints.isUserScalable) + if (!m_allowsUserScaling) return; m_pinchStartScale = -1; @@ -553,6 +622,12 @@ void QtViewportInteractionEngine::pinchGestureEnded() m_scaleUpdateDeferrer.clear(); } +void QtViewportInteractionEngine::pinchGestureCancelled() +{ + m_pinchStartScale = -1; + m_scaleUpdateDeferrer.clear(); +} + void QtViewportInteractionEngine::itemSizeChanged() { // FIXME: This needs to be done smarter. What happens if it resizes when we were interacting? @@ -560,7 +635,7 @@ void QtViewportInteractionEngine::itemSizeChanged() return; ViewportUpdateDeferrer guard(this); - ensureContentWithinViewportBoundary(); + ensureContentWithinViewportBoundary(true); } void QtViewportInteractionEngine::scaleContent(const QPointF& centerInCSSCoordinates, qreal cssScale) @@ -569,9 +644,11 @@ void QtViewportInteractionEngine::scaleContent(const QPointF& centerInCSSCoordin m_content->setContentsScale(itemScaleFromCSS(cssScale)); QPointF newPinchCenterOnViewport = m_viewport->mapFromWebContent(centerInCSSCoordinates); - m_flickProvider->setContentPos(m_flickProvider->contentPos() + (newPinchCenterOnViewport - oldPinchCenterOnViewport)); + m_viewport->setContentPos(m_viewport->contentPos() + (newPinchCenterOnViewport - oldPinchCenterOnViewport)); } +} // namespace WebKit + #include "moc_QtViewportInteractionEngine.cpp" -} + diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h index 017c307cd..486d8417c 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h +++ b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h @@ -22,18 +22,14 @@ #ifndef QtViewportInteractionEngine_h #define QtViewportInteractionEngine_h -#include "OwnPtr.h" -#include "qwebkitglobal.h" -#include <QTouchEvent> #include <QtCore/QObject> #include <QtCore/QRectF> #include <QtCore/QVariant> #include <QtCore/QVariantAnimation> +#include <wtf/OwnPtr.h> QT_BEGIN_NAMESPACE class QPointF; -class QQuickItem; -class QtFlickProvider; class QQuickWebPage; class QQuickWebView; class QWheelEvent; @@ -47,43 +43,41 @@ class QtViewportInteractionEngine : public QObject { Q_OBJECT public: - QtViewportInteractionEngine(QQuickWebView*, QQuickWebPage*, QtFlickProvider*); + QtViewportInteractionEngine(QQuickWebView*, QQuickWebPage*); ~QtViewportInteractionEngine(); - struct Constraints { - Constraints() - : initialScale(1.0) - , minimumScale(0.25) - , maximumScale(1.8) - , devicePixelRatio(1.0) - , isUserScalable(true) - , layoutSize(QSize()) - { } + void reset(); - qreal initialScale; - qreal minimumScale; - qreal maximumScale; - qreal devicePixelRatio; - bool isUserScalable; - QSize layoutSize; - }; + bool hadUserInteraction() const { return m_hadUserInteraction; } - void reset(); - void applyConstraints(const Constraints&); + void setCSSScaleBounds(qreal minimum, qreal maximum); + void setCSSScale(qreal); + + qreal currentCSSScale(); + + bool ensureContentWithinViewportBoundary(bool immediate = false); + + void setAllowsUserScaling(bool allow) { m_allowsUserScaling = allow; } + void setContentToDevicePixelRatio(qreal ratio) {m_devicePixelRatio = ratio; } void setItemRectVisible(const QRectF&); bool animateItemRectVisible(const QRectF&); void wheelEvent(QWheelEvent*); void pagePositionRequest(const QPoint& pos); + void touchBegin(); + void touchEnd(); bool scrollAnimationActive() const; + void cancelScrollAnimation(); bool panGestureActive() const; - void panGestureStarted(const QTouchEvent*); - void panGestureRequestUpdate(const QTouchEvent*); + + void panGestureStarted(const QPointF& position, qint64 eventTimestampMillis); + void panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis); + void panGestureEnded(const QPointF& position, qint64 eventTimestampMillis); + void panGestureCancelled(); - void panGestureEnded(const QTouchEvent*); bool scaleAnimationActive() const; void interruptScaleAnimation(); @@ -92,19 +86,16 @@ public: void pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates); void pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor); void pinchGestureEnded(); + void pinchGestureCancelled(); void zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea); void focusEditableArea(const QRectF& caretArea, const QRectF& targetArea); - const Constraints& constraints() const { return m_constraints; } - qreal currentCSSScale(); - Q_SIGNALS: void contentSuspendRequested(); void contentResumeRequested(); - void contentWasMoved(const QPointF& trajectoryVector); - void contentWasScaled(); + void contentViewportChanged(const QPointF& trajectory = QPointF()); void viewportTrajectoryVectorChanged(const QPointF&); void visibleContentRectAndScaleChanged(); @@ -123,6 +114,10 @@ private Q_SLOTS: private: friend class ViewportUpdateDeferrer; + friend class QWebViewportInfo; + + QQuickWebView* const m_viewport; + QQuickWebPage* const m_content; qreal cssScaleFromItem(qreal); qreal itemScaleFromCSS(qreal); @@ -132,22 +127,22 @@ private: qreal innerBoundedCSSScale(qreal); qreal outerBoundedCSSScale(qreal); - QRectF computePosRangeForItemAtScale(qreal itemScale) const; - bool ensureContentWithinViewportBoundary(bool immediate = false); + bool m_allowsUserScaling; + qreal m_minimumScale; + qreal m_maximumScale; + qreal m_devicePixelRatio; - void scaleContent(const QPointF& centerInCSSCoordinates, qreal cssScale); - - QQuickWebView* const m_viewport; - QQuickWebPage* const m_content; + QSize m_layoutSize; - QtFlickProvider* const m_flickProvider; + QRectF computePosRangeForItemAtScale(qreal itemScale) const; - Constraints m_constraints; + void scaleContent(const QPointF& centerInCSSCoordinates, qreal cssScale); int m_suspendCount; bool m_hasSuspendedContent; OwnPtr<ViewportUpdateDeferrer> m_scaleUpdateDeferrer; OwnPtr<ViewportUpdateDeferrer> m_scrollUpdateDeferrer; + OwnPtr<ViewportUpdateDeferrer> m_touchUpdateDeferrer; bool m_hadUserInteraction; @@ -160,20 +155,24 @@ private: virtual void updateCurrentValue(const QVariant&) { } }; + struct ScaleStackItem { + ScaleStackItem(qreal scale, qreal xPosition) + : scale(scale) + , xPosition(xPosition) + { } + + qreal scale; + qreal xPosition; + }; + ScaleAnimation* m_scaleAnimation; QPointF m_lastPinchCenterInViewportCoordinates; QPointF m_lastScrollPosition; qreal m_pinchStartScale; + qreal m_zoomOutScale; + QList<ScaleStackItem> m_scaleStack; }; -inline bool operator==(const QtViewportInteractionEngine::Constraints& a, const QtViewportInteractionEngine::Constraints& b) -{ - return a.initialScale == b.initialScale - && a.minimumScale == b.minimumScale - && a.maximumScale == b.maximumScale - && a.isUserScalable == b.isUserScalable; -} - -} +} // namespace WebKit #endif // QtViewportInteractionEngine_h diff --git a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp index a800fef15..30d59c2a4 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp @@ -26,6 +26,7 @@ #include "QtWebIconDatabaseClient.h" #include "WKAPICast.h" #include "WebContext.h" +#include "WebInspectorServer.h" #include "WebPageProxy.h" #include <WKArray.h> #include <WKPage.h> @@ -44,6 +45,46 @@ static HashMap<uint64_t, QtWebContext*> contextMap; QtWebContext* QtWebContext::s_defaultContext = 0; +static void initInspectorServer() +{ + QString inspectorEnv = QString::fromUtf8(qgetenv("QTWEBKIT_INSPECTOR_SERVER")); + if (!inspectorEnv.isEmpty()) { + QString bindAddress = QLatin1String("127.0.0.1"); + QString portStr = inspectorEnv; + int port = 0; + + int portColonPos = inspectorEnv.lastIndexOf(':'); + if (portColonPos != -1) { + portStr = inspectorEnv.mid(portColonPos + 1); + bindAddress = inspectorEnv.mid(0, portColonPos); + } + + bool ok = false; + port = portStr.toInt(&ok); + if (!ok) { + qWarning("Non numeric port for the inspector server \"%s\". Examples of valid input: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface).", qPrintable(portStr)); + return; + } + + bool success = WebInspectorServer::shared().listen(bindAddress, port); + if (success) { + QString inspectorServerUrl = QString::fromLatin1("http://%1:%2").arg(bindAddress).arg(port); + qWarning("Inspector server started successfully. Try pointing a WebKit browser to %s", qPrintable(inspectorServerUrl)); + } else + qWarning("Couldn't start the inspector server on bind address \"%s\" and port \"%d\". In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface).", qPrintable(bindAddress), port); + } +} + +static void globalInitialization() +{ + static bool initialized = false; + if (initialized) + return; + + initInspectorServer(); + initialized = true; +} + QtWebContext::QtWebContext(WebContext* context) : m_contextID(generateContextID()) , m_context(context) @@ -63,6 +104,7 @@ QtWebContext::~QtWebContext() // Used only by WebKitTestRunner. It avoids calling initialize(), so that we don't register any clients. PassRefPtr<QtWebContext> QtWebContext::create(WebContext* context) { + globalInitialization(); return adoptRef(new QtWebContext(context)); } @@ -150,4 +192,5 @@ void QtWebContext::didReceiveMessageFromInjectedBundle(WKStringRef messageName, toImpl(page)->didReceiveMessageFromNavigatorQtObject(toImpl(str)->string()); } -} +} // namespace WebKit + diff --git a/Source/WebKit2/UIProcess/qt/QtWebContext.h b/Source/WebKit2/UIProcess/qt/QtWebContext.h index 7703db459..a1e12ff0f 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebContext.h +++ b/Source/WebKit2/UIProcess/qt/QtWebContext.h @@ -21,11 +21,12 @@ #ifndef QtWebContext_h #define QtWebContext_h +#include <QtGlobal> #include <WKContext.h> #include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> -#include <qglobal.h> QT_BEGIN_NAMESPACE class QString; @@ -76,6 +77,6 @@ private: OwnPtr<QtWebIconDatabaseClient> m_iconDatabase; }; -} +} // namespace WebKit #endif // QtWebContext_h diff --git a/Source/WebKit2/UIProcess/qt/QtWebError.cpp b/Source/WebKit2/UIProcess/qt/QtWebError.cpp index d5b1cbd1b..87ac17edf 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebError.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebError.cpp @@ -29,7 +29,7 @@ #include <WKURL.h> #include <WKURLQt.h> -using namespace WebKit; +namespace WebKit { QtWebError::QtWebError(WKErrorRef errorRef) : error(errorRef) @@ -65,3 +65,5 @@ QString QtWebError::description() const { return WKStringCopyQString(WKErrorCopyLocalizedDescription(error.get())); } + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtWebError.h b/Source/WebKit2/UIProcess/qt/QtWebError.h index 3fe9eb906..3c36f701d 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebError.h +++ b/Source/WebKit2/UIProcess/qt/QtWebError.h @@ -22,7 +22,6 @@ #define QtWebError_h #include "qwebdownloaditem_p.h" -#include "qwebkitglobal.h" #include <QtNetwork/QNetworkReply> #include <WKError.h> #include <WKRetainPtr.h> @@ -31,6 +30,8 @@ QT_BEGIN_NAMESPACE class QUrl; QT_END_NAMESPACE +namespace WebKit { + class QtWebError { public: enum Type { @@ -58,4 +59,6 @@ private: WKRetainPtr<WKErrorRef> error; }; +} // namespace WebKit + #endif /* QtWebError_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp index 19ba336ae..d94b634b3 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp @@ -32,7 +32,7 @@ #include <QtCore/QUrl> #include <QtGui/QImage> -using namespace WebKit; +namespace WebKit { static inline QtWebIconDatabaseClient* toQtWebIconDatabaseClient(const void* clientInfo) { @@ -120,4 +120,7 @@ void QtWebIconDatabaseClient::releaseIconForPageURL(const String& pageURL) m_iconDatabase->releaseIconForPageURL(pageURL); } +} // namespace WebKit + #include "moc_QtWebIconDatabaseClient.cpp" + diff --git a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h index b2c00a8ee..933ad9abe 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h +++ b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.h @@ -25,15 +25,20 @@ #include "qwebkitglobal.h" #include <QtCore/QObject> #include <QtCore/QSize> +#include <wtf/RefPtr.h> #include <wtf/Threading.h> -#include <wtf/text/WTFString.h> QT_BEGIN_NAMESPACE class QImage; class QUrl; QT_END_NAMESPACE +namespace WTF { +class String; +} + namespace WebKit { + class QtWebContext; class WebIconDatabase; @@ -44,9 +49,9 @@ public: QtWebIconDatabaseClient(QtWebContext*); ~QtWebIconDatabaseClient(); - QImage iconImageForPageURL(const String& pageURL, const QSize& iconSize = QSize(32, 32)); - void retainIconForPageURL(const String&); - void releaseIconForPageURL(const String&); + QImage iconImageForPageURL(const WTF::String& pageURL, const QSize& iconSize = QSize(32, 32)); + void retainIconForPageURL(const WTF::String&); + void releaseIconForPageURL(const WTF::String&); public Q_SLOTS: void requestIconForPageURL(const QUrl&); @@ -55,13 +60,13 @@ public: Q_SIGNAL void iconChangedForPageURL(const QUrl& pageURL, const QUrl& iconURL); private: - unsigned iconURLHashForPageURL(const String&); + unsigned iconURLHashForPageURL(const WTF::String&); static void didChangeIconForPageURL(WKIconDatabaseRef, WKURLRef pageURL, const void* clientInfo); uint64_t m_contextId; RefPtr<WebKit::WebIconDatabase> m_iconDatabase; Mutex m_imageLock; }; -} +} // namespace WebKit #endif diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp index 95ed43191..bbfab1a5a 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp @@ -25,11 +25,11 @@ #include "NativeWebMouseEvent.h" #include "NativeWebWheelEvent.h" #include "QtViewportInteractionEngine.h" +#include "WebPageProxy.h" #include "qquickwebpage_p.h" #include "qquickwebview_p.h" #include <QCursor> #include <QDrag> -#include <QGraphicsSceneMouseEvent> #include <QGuiApplication> #include <QInputPanel> #include <QMimeData> @@ -41,9 +41,10 @@ #include <WebCore/DragData.h> #include <WebCore/Editor.h> -using namespace WebKit; using namespace WebCore; +namespace WebKit { + static inline Qt::DropAction dragOperationToDropAction(unsigned dragOperation) { Qt::DropAction result = Qt::IgnoreAction; @@ -221,7 +222,8 @@ void QtWebPageEventHandler::handleDropEvent(QDropEvent* ev) // FIXME: Should not use QCursor::pos() DragData dragData(ev->mimeData(), fromItemTransform.map(ev->pos()), QCursor::pos(), dropActionToDragOperation(ev->possibleActions())); SandboxExtension::Handle handle; - m_webPageProxy->performDrag(&dragData, String(), handle); + SandboxExtension::HandleArray sandboxExtensionForUpload; + m_webPageProxy->performDrag(&dragData, String(), handle, sandboxExtensionForUpload); ev->setDropAction(dragOperationToDropAction(m_webPageProxy->dragSession().operation)); ev->accept(); @@ -230,8 +232,17 @@ void QtWebPageEventHandler::handleDropEvent(QDropEvent* ev) void QtWebPageEventHandler::handlePotentialSingleTapEvent(const QTouchEvent::TouchPoint& point) { - QTransform fromItemTransform = m_webPage->transformFromItem(); - m_webPageProxy->handlePotentialActivation(fromItemTransform.map(point.pos()).toPoint()); +#if ENABLE(TOUCH_EVENTS) + if (point.pos() == QPointF()) { + // An empty point deactivates the highlighting. + m_webPageProxy->handlePotentialActivation(IntPoint(), IntSize()); + } else { + QTransform fromItemTransform = m_webPage->transformFromItem(); + m_webPageProxy->handlePotentialActivation(IntPoint(fromItemTransform.map(point.pos()).toPoint()), IntSize(point.rect().size().toSize())); + } +#else + Q_UNUSED(point); +#endif } void QtWebPageEventHandler::handleSingleTapEvent(const QTouchEvent::TouchPoint& point) @@ -246,7 +257,7 @@ void QtWebPageEventHandler::handleSingleTapEvent(const QTouchEvent::TouchPoint& void QtWebPageEventHandler::handleDoubleTapEvent(const QTouchEvent::TouchPoint& point) { QTransform fromItemTransform = m_webPage->transformFromItem(); - m_webPageProxy->findZoomableAreaForPoint(fromItemTransform.map(point.pos()).toPoint()); + m_webPageProxy->findZoomableAreaForPoint(fromItemTransform.map(point.pos()).toPoint(), IntSize(point.rect().size().toSize())); } void QtWebPageEventHandler::timerEvent(QTimerEvent* ev) @@ -364,9 +375,9 @@ void QtWebPageEventHandler::handleTouchEvent(QTouchEvent* event) void QtWebPageEventHandler::resetGestureRecognizers() { - m_panGestureRecognizer.reset(); - m_pinchGestureRecognizer.reset(); - m_tapGestureRecognizer.reset(); + m_panGestureRecognizer.cancel(); + m_pinchGestureRecognizer.cancel(); + m_tapGestureRecognizer.cancel(); } static void setInputPanelVisible(bool visible) @@ -383,7 +394,7 @@ void QtWebPageEventHandler::inputPanelVisibleChanged() return; // We only respond to the input panel becoming visible. - if (!m_webView->hasFocus() || !qApp->inputPanel()->visible()) + if (!m_webView->hasActiveFocus() || !qApp->inputPanel()->visible()) return; const EditorState& editor = m_webPageProxy->editorState(); @@ -398,12 +409,14 @@ void QtWebPageEventHandler::updateTextInputState() const EditorState& editor = m_webPageProxy->editorState(); - if (!m_webView->hasFocus()) + m_webView->setFlag(QQuickItem::ItemAcceptsInputMethod, editor.isContentEditable); + + if (!m_webView->hasActiveFocus()) return; - // Ignore input method requests not due to a tap gesture. - if (!editor.isContentEditable) - setInputPanelVisible(false); + qApp->inputPanel()->update(Qt::ImQueryInput | Qt::ImEnabled); + + setInputPanelVisible(editor.isContentEditable); } void QtWebPageEventHandler::doneWithGestureEvent(const WebGestureEvent& event, bool wasEventHandled) @@ -413,15 +426,13 @@ void QtWebPageEventHandler::doneWithGestureEvent(const WebGestureEvent& event, b m_postponeTextInputStateChanged = false; - if (!wasEventHandled || !m_webView->hasFocus()) + if (!wasEventHandled || !m_webView->hasActiveFocus()) return; - const EditorState& editor = m_webPageProxy->editorState(); - bool newVisible = editor.isContentEditable; - - setInputPanelVisible(newVisible); + updateTextInputState(); } +#if ENABLE(TOUCH_EVENTS) void QtWebPageEventHandler::doneWithTouchEvent(const NativeWebTouchEvent& event, bool wasEventHandled) { if (!m_interactionEngine) @@ -438,17 +449,21 @@ void QtWebPageEventHandler::doneWithTouchEvent(const NativeWebTouchEvent& event, case QEvent::TouchBegin: ASSERT(!m_interactionEngine->panGestureActive()); ASSERT(!m_interactionEngine->pinchGestureActive()); + m_interactionEngine->touchBegin(); // The interaction engine might still be animating kinetic scrolling or a scale animation // such as double-tap to zoom or the bounce back effect. A touch stops the kinetic scrolling // where as it does not stop the scale animation. - // Sending the event to the flickProvider will stop the kinetic scrolling animation. + // The gesture recognizer stops the kinetic scrolling animation if needed. break; case QEvent::TouchUpdate: // The scale animation can only be interrupted by a pinch gesture, which will then take over. if (m_interactionEngine->scaleAnimationActive() && m_pinchGestureRecognizer.isRecognized()) m_interactionEngine->interruptScaleAnimation(); break; + case QEvent::TouchEnd: + m_interactionEngine->touchEnd(); + break; default: break; } @@ -458,17 +473,47 @@ void QtWebPageEventHandler::doneWithTouchEvent(const NativeWebTouchEvent& event, if (m_interactionEngine->scaleAnimationActive()) return; - m_panGestureRecognizer.recognize(ev); - m_pinchGestureRecognizer.recognize(ev); + const QList<QTouchEvent::TouchPoint>& touchPoints = ev->touchPoints(); + const int touchPointCount = touchPoints.size(); + qint64 eventTimestampMillis = ev->timestamp(); + QList<QTouchEvent::TouchPoint> activeTouchPoints; + activeTouchPoints.reserve(touchPointCount); - if (m_panGestureRecognizer.isRecognized() || m_pinchGestureRecognizer.isRecognized()) - m_tapGestureRecognizer.reset(); - else { - // Convert the event timestamp from second to millisecond. - qint64 eventTimestampMillis = static_cast<qint64>(event.timestamp() * 1000); - m_tapGestureRecognizer.recognize(ev, eventTimestampMillis); + for (int i = 0; i < touchPointCount; ++i) { + if (touchPoints[i].state() != Qt::TouchPointReleased) + activeTouchPoints << touchPoints[i]; } + + const int activeTouchPointCount = activeTouchPoints.size(); + + if (!activeTouchPointCount) { + if (touchPointCount == 1) { + // No active touch points, one finger released. + if (!m_panGestureRecognizer.isRecognized()) + m_tapGestureRecognizer.update(ev->type(), touchPoints.first()); + m_panGestureRecognizer.finish(touchPoints.first(), eventTimestampMillis); + } else + m_pinchGestureRecognizer.finish(); + + // Early return since this was a touch-end event. + return; + } else if (activeTouchPointCount == 1) { + // If the pinch gesture recognizer was previously in active state the content might + // be out of valid zoom boundaries, thus we need to finish the pinch gesture here. + // This will resume the content to valid zoom levels before the pan gesture is started. + m_pinchGestureRecognizer.finish(); + m_panGestureRecognizer.update(activeTouchPoints.first(), eventTimestampMillis); + } else if (activeTouchPointCount == 2) { + m_panGestureRecognizer.cancel(); + m_pinchGestureRecognizer.update(activeTouchPoints.first(), activeTouchPoints.last()); + } + + if (m_panGestureRecognizer.isRecognized() || m_pinchGestureRecognizer.isRecognized() || m_webView->isMoving()) + m_tapGestureRecognizer.cancel(); + else if (touchPointCount == 1) + m_tapGestureRecognizer.update(ev->type(), touchPoints.first()); } +#endif void QtWebPageEventHandler::didFindZoomableArea(const IntPoint& target, const IntRect& area) { @@ -508,4 +553,7 @@ void QtWebPageEventHandler::startDrag(const WebCore::DragData& dragData, PassRef m_webPageProxy->dragEnded(clientPosition, globalPosition, dropActionToDragOperation(actualDropAction)); } +} // namespace WebKit + #include "moc_QtWebPageEventHandler.cpp" + diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h index 519ec5471..74acdb77e 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.h @@ -24,17 +24,32 @@ #include "QtPanGestureRecognizer.h" #include "QtPinchGestureRecognizer.h" #include "QtTapGestureRecognizer.h" -#include "QtViewportInteractionEngine.h" -#include "WebPageProxy.h" #include <QBasicTimer> -#include <QKeyEvent> -#include <QInputMethodEvent> #include <QTouchEvent> #include <WKPage.h> +#include <wtf/PassRefPtr.h> + +QT_BEGIN_NAMESPACE +class QInputMethodEvent; +class QKeyEvent; +QT_END_NAMESPACE class QQuickWebPage; +class QQuickWebView; + +namespace WebCore { +class DragData; +class IntPoint; +class IntRect; +} -using namespace WebKit; +namespace WebKit { + +class NativeWebTouchEvent; +class QtViewportInteractionEngine; +class ShareableBitmap; +class WebGestureEvent; +class WebPageProxy; class QtWebPageEventHandler : public QObject { Q_OBJECT @@ -69,7 +84,9 @@ public: void didFindZoomableArea(const WebCore::IntPoint& target, const WebCore::IntRect& area); void updateTextInputState(); void doneWithGestureEvent(const WebGestureEvent& event, bool wasEventHandled); +#if ENABLE(TOUCH_EVENTS) void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled); +#endif void resetGestureRecognizers(); QtViewportInteractionEngine* interactionEngine() { return m_interactionEngine; } @@ -98,4 +115,6 @@ private: bool m_postponeTextInputStateChanged; }; +} // namespace WebKit + #endif /* QtWebPageEventHandler_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.cpp index de22a9fb3..f510016de 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.cpp @@ -21,14 +21,22 @@ #include "config.h" #include "QtWebPageLoadClient.h" +#include "QtWebError.h" #include "WKStringQt.h" #include "qquickwebview_p.h" #include "qquickwebview_p_p.h" #include "qwebloadrequest_p.h" +#include <KURL.h> #include <WKFrame.h> +#include <WebPageProxy.h> + +using namespace WebCore; + +namespace WebKit { QtWebPageLoadClient::QtWebPageLoadClient(WKPageRef pageRef, QQuickWebView* webView) : m_webView(webView) + , m_webPageProxy(toImpl(pageRef)) , m_loadProgress(0) { WKPageLoaderClient loadClient; @@ -50,31 +58,45 @@ QtWebPageLoadClient::QtWebPageLoadClient(WKPageRef pageRef, QQuickWebView* webVi WKPageSetPageLoaderClient(pageRef, &loadClient); } -void QtWebPageLoadClient::didStartProvisionalLoadForFrame(const QUrl& url) +void QtWebPageLoadClient::completeLoadWhenProcessDidCrashIfNeeded() +{ + // Check if loading was ongoing, when process crashed. + if (!m_loadProgress || m_loadProgress == 100) + return; + + QUrl url(KURL(WebCore::ParsedURLString, m_webPageProxy->urlAtProcessExit())); + QWebLoadRequest loadRequest(url, QQuickWebView::LoadFailedStatus, QLatin1String("The web process crashed."), QQuickWebView::InternalErrorDomain, 0); + + emit m_webView->loadingChanged(&loadRequest); + setLoadProgress(100); +} + +void QtWebPageLoadClient::didStartProvisionalLoad(const QUrl& url) { QWebLoadRequest loadRequest(url, QQuickWebView::LoadStartedStatus); - m_webView->d_func()->didChangeLoadingState(&loadRequest); + emit m_webView->loadingChanged(&loadRequest); } -void QtWebPageLoadClient::didCommitLoadForFrame() +void QtWebPageLoadClient::didCommitLoad() { emit m_webView->navigationHistoryChanged(); emit m_webView->urlChanged(); + emit m_webView->titleChanged(); m_webView->d_func()->loadDidCommit(); } -void QtWebPageLoadClient::didSameDocumentNavigationForFrame() +void QtWebPageLoadClient::didSameDocumentNavigation() { emit m_webView->navigationHistoryChanged(); emit m_webView->urlChanged(); } -void QtWebPageLoadClient::didReceiveTitleForFrame() +void QtWebPageLoadClient::didReceiveTitle() { emit m_webView->titleChanged(); } -void QtWebPageLoadClient::didFirstVisuallyNonEmptyLayoutForFrame() +void QtWebPageLoadClient::didFirstVisuallyNonEmptyLayout() { m_webView->d_func()->didFinishFirstNonEmptyLayout(); } @@ -122,7 +144,7 @@ void QtWebPageLoadClient::didStartProvisionalLoadForFrame(WKPageRef, WKFrameRef WebFrameProxy* wkframe = toImpl(frame); QString urlStr(wkframe->provisionalURL()); QUrl qUrl = urlStr; - toQtWebPageLoadClient(clientInfo)->didStartProvisionalLoadForFrame(qUrl); + toQtWebPageLoadClient(clientInfo)->didStartProvisionalLoad(qUrl); } void QtWebPageLoadClient::didFailProvisionalLoadWithErrorForFrame(WKPageRef, WKFrameRef frame, WKErrorRef error, WKTypeRef, const void* clientInfo) @@ -136,7 +158,7 @@ void QtWebPageLoadClient::didCommitLoadForFrame(WKPageRef, WKFrameRef frame, WKT { if (!WKFrameIsMainFrame(frame)) return; - toQtWebPageLoadClient(clientInfo)->didCommitLoadForFrame(); + toQtWebPageLoadClient(clientInfo)->didCommitLoad(); } void QtWebPageLoadClient::didFinishLoadForFrame(WKPageRef, WKFrameRef frame, WKTypeRef, const void* clientInfo) @@ -153,16 +175,18 @@ void QtWebPageLoadClient::didFailLoadWithErrorForFrame(WKPageRef, WKFrameRef fra toQtWebPageLoadClient(clientInfo)->dispatchLoadFailed(error); } -void QtWebPageLoadClient::didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void* clientInfo) +void QtWebPageLoadClient::didSameDocumentNavigationForFrame(WKPageRef, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void* clientInfo) { - toQtWebPageLoadClient(clientInfo)->didSameDocumentNavigationForFrame(); + if (!WKFrameIsMainFrame(frame)) + return; + toQtWebPageLoadClient(clientInfo)->didSameDocumentNavigation(); } void QtWebPageLoadClient::didReceiveTitleForFrame(WKPageRef, WKStringRef title, WKFrameRef frame, WKTypeRef, const void* clientInfo) { if (!WKFrameIsMainFrame(frame)) return; - toQtWebPageLoadClient(clientInfo)->didReceiveTitleForFrame(); + toQtWebPageLoadClient(clientInfo)->didReceiveTitle(); } void QtWebPageLoadClient::didStartProgress(WKPageRef, const void* clientInfo) @@ -186,10 +210,12 @@ void QtWebPageLoadClient::didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef, WKFr { if (!WKFrameIsMainFrame(frame)) return; - toQtWebPageLoadClient(clientInfo)->didFirstVisuallyNonEmptyLayoutForFrame(); + toQtWebPageLoadClient(clientInfo)->didFirstVisuallyNonEmptyLayout(); } void QtWebPageLoadClient::didChangeBackForwardList(WKPageRef, WKBackForwardListItemRef, WKArrayRef, const void *clientInfo) { toQtWebPageLoadClient(clientInfo)->didChangeBackForwardList(); } + +} // namespace Webkit diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.h b/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.h index 672597af7..a4afd25f8 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.h +++ b/Source/WebKit2/UIProcess/qt/QtWebPageLoadClient.h @@ -21,29 +21,37 @@ #ifndef QtWebPageLoadClient_h #define QtWebPageLoadClient_h -#include "QtWebError.h" -#include <QtCore/QString> -#include <QtCore/QUrl> +#include <QtGlobal> #include <WKPage.h> +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + class QQuickWebView; +namespace WebKit { + +class WebPageProxy; + class QtWebPageLoadClient { public: QtWebPageLoadClient(WKPageRef, QQuickWebView*); int loadProgress() const { return m_loadProgress; } + void completeLoadWhenProcessDidCrashIfNeeded(); private: - void didStartProvisionalLoadForFrame(const QUrl&); - void didCommitLoadForFrame(); - void didSameDocumentNavigationForFrame(); - void didReceiveTitleForFrame(); - void didFirstVisuallyNonEmptyLayoutForFrame(); + void didStartProvisionalLoad(const QUrl&); + void didCommitLoad(); + void didSameDocumentNavigation(); + void didReceiveTitle(); + void didFirstVisuallyNonEmptyLayout(); void didChangeBackForwardList(); void dispatchLoadSucceeded(); void dispatchLoadFailed(WKErrorRef); + void setLoadProgress(int); // WKPageLoadClient callbacks. @@ -61,7 +69,10 @@ private: static void didChangeBackForwardList(WKPageRef, WKBackForwardListItemRef, WKArrayRef, const void *clientInfo); QQuickWebView* m_webView; + WebPageProxy* m_webPageProxy; int m_loadProgress; }; +} // namespace Webkit + #endif // QtWebPageLoadClient_h diff --git a/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp b/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp index ad5f6aa12..1f0ad1431 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.cpp @@ -27,8 +27,11 @@ #include "qwebnavigationrequest_p.h" #include <QtCore/QObject> #include <WKFramePolicyListener.h> +#include <WKRetainPtr.h> #include <WKURLRequest.h> +namespace WebKit { + QtWebPagePolicyClient::QtWebPagePolicyClient(WKPageRef pageRef, QQuickWebView* webView) : m_webView(webView) { @@ -152,3 +155,6 @@ void QtWebPagePolicyClient::decidePolicyForResponse(WKPageRef page, WKFrameRef f WKFramePolicyListenerUse(listener); } + +} // namespace WebKit + diff --git a/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h b/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h index 9e397fb77..9515c020e 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h +++ b/Source/WebKit2/UIProcess/qt/QtWebPagePolicyClient.h @@ -22,10 +22,15 @@ #define QtWebPagePolicyClient_h #include "qquickwebview_p.h" -#include <QtCore/QUrl> +#include <QtGlobal> #include <WKPage.h> -class QQuickWebView; +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE + +namespace WebKit { + class QtWebPagePolicyClient { public: QtWebPagePolicyClient(WKPageRef, QQuickWebView*); @@ -40,4 +45,6 @@ private: QQuickWebView* m_webView; }; +} // namespace WebKit + #endif // QtWebPagePolicyClient_h diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp new file mode 100644 index 000000000..4de77f70a --- /dev/null +++ b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2012 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 "config.h" +#include "QtWebPageSGNode.h" + +#include "WebLayerTreeRenderer.h" +#include <QtGui/QPolygonF> +#include <QtQuick/QSGSimpleRectNode> +#include <private/qsgrendernode_p.h> + +using namespace WebCore; + +namespace WebKit { + +class ContentsSGNode : public QSGRenderNode { +public: + ContentsSGNode(PassRefPtr<WebLayerTreeRenderer> renderer) + : m_renderer(renderer) + { + layerTreeRenderer()->setActive(true); + } + + virtual StateFlags changedStates() + { + return StateFlags(StencilState) | ColorState | BlendState; + } + + virtual void render(const RenderState& state) + { + QMatrix4x4 renderMatrix = matrix() ? *matrix() : QMatrix4x4(); + + // When rendering to an intermediate surface, Qt will + // mirror the projection matrix to fit on the destination coordinate system. + const QMatrix4x4* projection = state.projectionMatrix; + bool mirrored = projection && (*projection)(0, 0) * (*projection)(1, 1) - (*projection)(0, 1) * (*projection)(1, 0) > 0; + + // FIXME: Support non-rectangular clippings. + layerTreeRenderer()->paintToCurrentGLContext(renderMatrix, inheritedOpacity(), clipRect(), mirrored ? TextureMapper::PaintingMirrored : 0); + } + + ~ContentsSGNode() + { + layerTreeRenderer()->purgeGLResources(); + } + + WebLayerTreeRenderer* layerTreeRenderer() const { return m_renderer.get(); } + +private: + QRectF clipRect() const + { + // Start with an invalid rect. + QRectF resultRect(0, 0, -1, -1); + + for (const QSGClipNode* clip = clipList(); clip; clip = clip->clipList()) { + QMatrix4x4 clipMatrix; + if (clip->matrix()) + clipMatrix = *clip->matrix(); + QRectF currentClip; + + if (clip->isRectangular()) + currentClip = clipMatrix.mapRect(clip->clipRect()); + else { + const QSGGeometry* geometry = clip->geometry(); + // Assume here that clipNode has only coordinate data. + const QSGGeometry::Point2D* geometryPoints = geometry->vertexDataAsPoint2D(); + + // Clip region should be at least triangle to make valid clip. + if (geometry->vertexCount() < 3) + continue; + + QPolygonF polygon; + + for (int i = 0; i < geometry->vertexCount(); i++) + polygon.append(clipMatrix.map(QPointF(geometryPoints[i].x, geometryPoints[i].y))); + currentClip = polygon.boundingRect(); + } + + if (currentClip.isEmpty()) + continue; + + if (resultRect.isValid()) + resultRect &= currentClip; + else + resultRect = currentClip; + } + + return resultRect; + } + + RefPtr<WebLayerTreeRenderer> m_renderer; +}; + +QtWebPageSGNode::QtWebPageSGNode() + : m_contentsNode(0) + , m_backgroundNode(new QSGSimpleRectNode) +{ + appendChildNode(m_backgroundNode); +} + +void QtWebPageSGNode::setBackground(const QRectF& rect, const QColor& color) +{ + m_backgroundNode->setRect(rect); + m_backgroundNode->setColor(color); +} + +void QtWebPageSGNode::setScale(float scale) +{ + QMatrix4x4 matrix; + matrix.scale(scale); + setMatrix(matrix); +} + +void QtWebPageSGNode::setRenderer(PassRefPtr<WebLayerTreeRenderer> renderer) +{ + if (m_contentsNode && m_contentsNode->layerTreeRenderer() == renderer) + return; + + delete m_contentsNode; + m_contentsNode = new ContentsSGNode(renderer); + appendChildNode(m_contentsNode); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h new file mode 100644 index 000000000..4c0fcfca2 --- /dev/null +++ b/Source/WebKit2/UIProcess/qt/QtWebPageSGNode.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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 QtWebPageSGNode_h +#define QtWebPageSGNode_h + +#include <QtQuick/QSGTransformNode> +#include <wtf/PassRefPtr.h> + +class QSGSimpleRectNode; + +namespace WebKit { + +class ContentsSGNode; +class WebLayerTreeRenderer; + +class QtWebPageSGNode : public QSGTransformNode { + public: + QtWebPageSGNode(); + void setBackground(const QRectF&, const QColor&); + void setScale(float); + void setRenderer(PassRefPtr<WebLayerTreeRenderer>); + + private: + ContentsSGNode* m_contentsNode; + QSGSimpleRectNode* m_backgroundNode; +}; + +} // namespace WebKit + +#endif /* QtWebPageSGNode_h */ diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.cpp index ef764c5c9..6d3447b05 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.cpp @@ -30,6 +30,9 @@ #include <WKHitTestResult.h> #include <WKOpenPanelParameters.h> #include <WKOpenPanelResultListener.h> +#include <WKRetainPtr.h> + +namespace WebKit { QtWebPageUIClient::QtWebPageUIClient(WKPageRef pageRef, QQuickWebView* webView) : m_webView(webView) @@ -43,10 +46,16 @@ QtWebPageUIClient::QtWebPageUIClient(WKPageRef pageRef, QQuickWebView* webView) uiClient.runJavaScriptPrompt = runJavaScriptPrompt; uiClient.runOpenPanel = runOpenPanel; uiClient.mouseDidMoveOverElement = mouseDidMoveOverElement; + uiClient.exceededDatabaseQuota = exceededDatabaseQuota; uiClient.decidePolicyForGeolocationPermissionRequest = policyForGeolocationPermissionRequest; WKPageSetPageUIClient(pageRef, &uiClient); } +quint64 QtWebPageUIClient::exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) +{ + return m_webView->d_func()->exceededDatabaseQuota(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); +} + void QtWebPageUIClient::runJavaScriptAlert(const QString& message) { m_webView->d_func()->runJavaScriptAlert(message); @@ -88,6 +97,13 @@ static QtWebPageUIClient* toQtWebPageUIClient(const void* clientInfo) return reinterpret_cast<QtWebPageUIClient*>(const_cast<void*>(clientInfo)); } +unsigned long long QtWebPageUIClient::exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef securityOrigin, WKStringRef databaseName, WKStringRef displayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage, const void *clientInfo) +{ + QString qDisplayName = WKStringCopyQString(displayName); + QString qDatabaseName = WKStringCopyQString(databaseName); + return toQtWebPageUIClient(clientInfo)->exceededDatabaseQuota(qDatabaseName, qDisplayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); +} + void QtWebPageUIClient::runJavaScriptAlert(WKPageRef, WKStringRef alertText, WKFrameRef, const void* clientInfo) { QString qAlertText = WKStringCopyQString(alertText); @@ -145,3 +161,4 @@ void QtWebPageUIClient::policyForGeolocationPermissionRequest(WKPageRef page, WK toQtWebPageUIClient(clientInfo)->permissionRequest(req); } +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.h b/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.h index 8cfe13c21..cdd7e407d 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.h +++ b/Source/WebKit2/UIProcess/qt/QtWebPageUIClient.h @@ -31,6 +31,8 @@ class QQuickWebView; class QWebPermissionRequest; +namespace WebKit { + class QtWebPageUIClient { public: enum FileChooserType { @@ -41,6 +43,7 @@ public: QtWebPageUIClient(WKPageRef, QQuickWebView*); private: + quint64 exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage); void runJavaScriptAlert(const QString& message); bool runJavaScriptConfirm(const QString& message); QString runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok); @@ -54,6 +57,7 @@ private: static WKStringRef runJavaScriptPrompt(WKPageRef, WKStringRef message, WKStringRef defaultValue, WKFrameRef, const void* clientInfo); static void runOpenPanel(WKPageRef, WKFrameRef, WKOpenPanelParametersRef, WKOpenPanelResultListenerRef, const void* clientInfo); static void mouseDidMoveOverElement(WKPageRef, WKHitTestResultRef, WKEventModifiers, WKTypeRef userData, const void* clientInfo); + static unsigned long long exceededDatabaseQuota(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKStringRef databaseName, WKStringRef displayName, unsigned long long currentQuota, unsigned long long currentOriginUsage, unsigned long long currentDatabaseUsage, unsigned long long expectedUsage, const void *clientInfo); static void policyForGeolocationPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKGeolocationPermissionRequestRef, const void*); QQuickWebView* m_webView; @@ -61,4 +65,6 @@ private: QString m_lastHoveredTitle; }; +} // namespace WebKit + #endif // QtWebPageUIClient_h diff --git a/Source/WebKit2/UIProcess/qt/QtWebUndoController.cpp b/Source/WebKit2/UIProcess/qt/QtWebUndoController.cpp index 62d31e8ab..e52eb2866 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebUndoController.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebUndoController.cpp @@ -21,10 +21,11 @@ #include "config.h" #include "QtWebUndoController.h" -#include <qglobal.h> +#include "WebEditCommandProxy.h" +#include <QtGlobal> #include <wtf/RefPtr.h> -using namespace WebKit; +namespace WebKit { void QtWebUndoController::registerEditCommand(PassRefPtr<WebEditCommandProxy> command, WebPageProxy::UndoOrRedo undoOrRedo) { @@ -61,3 +62,5 @@ void QtWebUndoController::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) command->reapply(); } } + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/QtWebUndoController.h b/Source/WebKit2/UIProcess/qt/QtWebUndoController.h index a260ca2fd..3274ce1c7 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebUndoController.h +++ b/Source/WebKit2/UIProcess/qt/QtWebUndoController.h @@ -21,10 +21,11 @@ #ifndef QtWebUndoController_h #define QtWebUndoController_h -#include "PageClient.h" #include "WebEditCommandProxy.h" #include "WebPageProxy.h" +namespace WebKit { + class QtWebUndoController { public: // Page Client. @@ -38,4 +39,6 @@ public: CommandVector m_redoStack; }; +} // namespace WebKit + #endif // QtWebUndoController_h diff --git a/Source/WebKit2/UIProcess/qt/WebContextMenuProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebContextMenuProxyQt.cpp index b00951014..d510c53ff 100644 --- a/Source/WebKit2/UIProcess/qt/WebContextMenuProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebContextMenuProxyQt.cpp @@ -51,3 +51,4 @@ void WebContextMenuProxyQt::hideContextMenu() #include "moc_WebContextMenuProxyQt.cpp" } // namespace WebKit + diff --git a/Source/WebKit2/UIProcess/qt/WebContextQt.cpp b/Source/WebKit2/UIProcess/qt/WebContextQt.cpp index b0d5ac4ba..5da97cb12 100644 --- a/Source/WebKit2/UIProcess/qt/WebContextQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebContextQt.cpp @@ -34,7 +34,6 @@ #include "WebGeolocationProviderQt.h" #endif #include "WebProcessCreationParameters.h" - #include <QCoreApplication> #include <QStandardPaths> #include <QDir> diff --git a/Source/WebKit2/UIProcess/qt/WebFullScreenManagerProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebFullScreenManagerProxyQt.cpp index bea1aebac..91d962e90 100644 --- a/Source/WebKit2/UIProcess/qt/WebFullScreenManagerProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebFullScreenManagerProxyQt.cpp @@ -26,7 +26,7 @@ #include "WebFullScreenManagerMessages.h" #include "WebFullScreenManagerProxyMessages.h" #include "WebProcess.h" - +#include "qquickwebview_p.h" #include <WebCore/NotImplemented.h> using namespace WebCore; @@ -38,14 +38,29 @@ void WebFullScreenManagerProxy::invalidate() m_webView = 0; } -void WebFullScreenManagerProxy::enterFullScreen() +void WebFullScreenManagerProxy::close() { notImplemented(); } -void WebFullScreenManagerProxy::exitFullScreen() +bool WebFullScreenManagerProxy::isFullScreen() { notImplemented(); + return false; +} + +void WebFullScreenManagerProxy::enterFullScreen() +{ + willEnterFullScreen(); + emit m_webView->experimental()->enterFullScreenRequested(); + didEnterFullScreen(); +} + +void WebFullScreenManagerProxy::exitFullScreen() +{ + willExitFullScreen(); + emit m_webView->experimental()->exitFullScreenRequested(); + didExitFullScreen(); } void WebFullScreenManagerProxy::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame) diff --git a/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.cpp b/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.cpp index 70d7b5733..8b87f0a72 100644 --- a/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.cpp @@ -22,10 +22,9 @@ #include "WebGeolocationProviderQt.h" #if ENABLE(GEOLOCATION) - #include <QtLocation/QGeoPositionInfoSource> -using namespace WebKit; +namespace WebKit { static inline const WebGeolocationProviderQt* toLocationProvider(const void* clientInfo) { @@ -114,6 +113,8 @@ void WebGeolocationProviderQt::stopUpdating() const m_source->stopUpdates(); } +} // namespace WebKit + #include "moc_WebGeolocationProviderQt.cpp" #endif // ENABLE(GEOLOCATION) diff --git a/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.h b/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.h index e59e3d75b..598c74a25 100644 --- a/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.h +++ b/Source/WebKit2/UIProcess/qt/WebGeolocationProviderQt.h @@ -29,6 +29,8 @@ class QGeoPositionInfoSource; class QGeoPositionInfo; +namespace WebKit { + class WebGeolocationProviderQt : public QObject { Q_OBJECT public: @@ -53,4 +55,6 @@ private: mutable QGeoPositionInfoSource* m_source; }; +} // namespace WebKit + #endif /* WebGeolocationProviderQt_h */ diff --git a/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp index bf86edce6..ae3c4aab6 100644 --- a/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp @@ -102,4 +102,16 @@ void WebPageProxy::sendApplicationSchemeReply(const QQuickNetworkReply* reply) } } +#if PLUGIN_ARCHITECTURE(X11) +void WebPageProxy::createPluginContainer(uint64_t& windowID) +{ + notImplemented(); +} + +void WebPageProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) +{ + notImplemented(); +} +#endif + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp index 4c0deadc2..9f9100a54 100644 --- a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp @@ -32,8 +32,8 @@ #include "qquickwebview_p.h" #include "qquickwebview_p_p.h" #include <QtCore/QAbstractListModel> -#include <QtDeclarative/QDeclarativeContext> -#include <QtDeclarative/QDeclarativeEngine> +#include <QtQml/QQmlContext> +#include <QtQml/QQmlEngine> using namespace WebCore; @@ -239,11 +239,13 @@ void WebPopupMenuProxyQt::showPopupMenu(const IntRect& rect, WebCore::TextDirect notifyValueChanged(); return; } + QQuickWebViewPrivate::get(m_webView)->setDialogActive(true); } void WebPopupMenuProxyQt::hidePopupMenu() { m_itemSelector.clear(); + QQuickWebViewPrivate::get(m_webView)->setDialogActive(false); m_context.clear(); notifyValueChanged(); } @@ -255,7 +257,7 @@ void WebPopupMenuProxyQt::selectIndex(int index) void WebPopupMenuProxyQt::createItem(QObject* contextObject) { - QDeclarativeComponent* component = m_webView->experimental()->itemSelector(); + QQmlComponent* component = m_webView->experimental()->itemSelector(); if (!component) { delete contextObject; return; @@ -287,12 +289,12 @@ void WebPopupMenuProxyQt::createItem(QObject* contextObject) m_itemSelector->setParentItem(m_webView); } -void WebPopupMenuProxyQt::createContext(QDeclarativeComponent* component, QObject* contextObject) +void WebPopupMenuProxyQt::createContext(QQmlComponent* component, QObject* contextObject) { - QDeclarativeContext* baseContext = component->creationContext(); + QQmlContext* baseContext = component->creationContext(); if (!baseContext) - baseContext = QDeclarativeEngine::contextForObject(m_webView); - m_context = adoptPtr(new QDeclarativeContext(baseContext)); + baseContext = QQmlEngine::contextForObject(m_webView); + m_context = adoptPtr(new QQmlContext(baseContext)); contextObject->setParent(m_context.get()); m_context->setContextProperty(QLatin1String("model"), contextObject); diff --git a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h index ea22bbdd6..d23134078 100644 --- a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h +++ b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h @@ -28,7 +28,6 @@ #define WebPopupMenuProxyQt_h #include "WebPopupMenuProxy.h" - #include <QtCore/QObject> #include <wtf/OwnPtr.h> diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp new file mode 100644 index 000000000..debef4716 --- /dev/null +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp @@ -0,0 +1,36 @@ +/* + * 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 "WebSoupRequestManagerClient.h" + +#include "WKAPICast.h" + +namespace WebKit { + +bool WebSoupRequestManagerClient::didReceiveURIRequest(WebSoupRequestManagerProxy* soupRequestManager, WebURL* url, uint64_t requestID) +{ + if (!m_client.didReceiveURIRequest) + return false; + + m_client.didReceiveURIRequest(toAPI(soupRequestManager), toAPI(url), requestID, m_client.clientInfo); + return true; +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.h b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.h new file mode 100644 index 000000000..afbba7007 --- /dev/null +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.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 WebSoupRequestManagerClient_h +#define WebSoupRequestManagerClient_h + +#include "APIClient.h" +#include "WKSoupRequestManager.h" + +namespace WebKit { + +class WebSoupRequestManagerProxy; +class WebURL; + +class WebSoupRequestManagerClient : public APIClient<WKSoupRequestManagerClient, kWKSoupRequestManagerClientCurrentVersion> { +public: + bool didReceiveURIRequest(WebSoupRequestManagerProxy*, WebURL*, uint64_t requestID); +}; + +} // namespace WebKit + +#endif // WebSoupRequestManagerClient_h diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp new file mode 100644 index 000000000..20c5c4f86 --- /dev/null +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp @@ -0,0 +1,75 @@ +/* + * 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 "WebSoupRequestManagerProxy.h" + +#include "WebContext.h" +#include "WebData.h" +#include "WebSoupRequestManagerMessages.h" + +namespace WebKit { + +PassRefPtr<WebSoupRequestManagerProxy> WebSoupRequestManagerProxy::create(WebContext* context) +{ + return adoptRef(new WebSoupRequestManagerProxy(context)); +} + +WebSoupRequestManagerProxy::WebSoupRequestManagerProxy(WebContext* context) + : m_webContext(context) +{ +} + +WebSoupRequestManagerProxy::~WebSoupRequestManagerProxy() +{ +} + +void WebSoupRequestManagerProxy::invalidate() +{ +} + +void WebSoupRequestManagerProxy::initializeClient(const WKSoupRequestManagerClient* client) +{ + m_client.initialize(client); +} + +void WebSoupRequestManagerProxy::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) +{ + didReceiveWebSoupRequestManagerProxyMessage(connection, messageID, arguments); +} + +void WebSoupRequestManagerProxy::registerURIScheme(const String& scheme) +{ + ASSERT(m_webContext); + m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebSoupRequestManager::RegisterURIScheme(scheme)); +} + +void WebSoupRequestManagerProxy::handleURIRequest(const WebData* requestData, const String& mimeType, uint64_t requestID) +{ + ASSERT(m_webContext); + m_webContext->sendToAllProcesses(Messages::WebSoupRequestManager::HandleURIRequest(requestData->dataReference(), mimeType, requestID)); +} + +void WebSoupRequestManagerProxy::didReceiveURIRequest(const String& uriString, uint64_t requestID) +{ + if (!m_client.didReceiveURIRequest(this, WebURL::create(uriString).get(), requestID)) + handleURIRequest(WebData::create(0, 0).get(), String(), requestID); +} + +} // namespace WebKit diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h new file mode 100644 index 000000000..2aa3e99f6 --- /dev/null +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h @@ -0,0 +1,72 @@ +/* + * 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 WebSoupRequestManagerProxy_h +#define WebSoupRequestManagerProxy_h + +#include "APIObject.h" +#include "WebSoupRequestManagerClient.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> + +namespace CoreIPC { +class ArgumentDecoder; +class Connection; +class MessageID; +} + +namespace WebKit { + +class WebContext; +class WebData; + +class WebSoupRequestManagerProxy : public APIObject { +public: + static const Type APIType = TypeSoupRequestManager; + + static PassRefPtr<WebSoupRequestManagerProxy> create(WebContext*); + virtual ~WebSoupRequestManagerProxy(); + + void invalidate(); + void clearContext() { m_webContext = 0; } + + void initializeClient(const WKSoupRequestManagerClient*); + + void registerURIScheme(const String& scheme); + void handleURIRequest(const WebData*, const String& mimeType, uint64_t requestID); + + void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + +private: + WebSoupRequestManagerProxy(WebContext*); + + virtual Type type() const { return APIType; } + + void didReceiveURIRequest(const String& uriString, uint64_t requestID); + + void didReceiveWebSoupRequestManagerProxyMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + + WebContext* m_webContext; + WebSoupRequestManagerClient m_client; +}; + +} // namespace WebKit + +#endif // WebSoupRequestManagerProxy_h diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in new file mode 100644 index 000000000..a3d052559 --- /dev/null +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in @@ -0,0 +1,25 @@ +# Copyright (C) 2012 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. + +messages -> WebSoupRequestManagerProxy { + DidReceiveURIRequest(WTF::String uriString, uint64_t requestID); +} diff --git a/Source/WebKit2/UIProcess/win/WebFullScreenManagerProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebFullScreenManagerProxyWin.cpp index fe11c7127..b53e2bd48 100644 --- a/Source/WebKit2/UIProcess/win/WebFullScreenManagerProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebFullScreenManagerProxyWin.cpp @@ -45,6 +45,18 @@ void WebFullScreenManagerProxy::invalidate() m_webView = 0; } +void WebFullScreenManagerProxy::close() +{ + if (!m_webView) + return; + m_webView->fullScreenController()->close(); +} + +bool WebFullScreenManagerProxy::isFullScreen() +{ + return m_webView->fullScreenController()->isFullScreen(); +} + void WebFullScreenManagerProxy::enterFullScreen() { if (!m_webView) diff --git a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp index 0c18c4e83..df4e9854b 100644 --- a/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp +++ b/Source/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp @@ -401,7 +401,7 @@ void WebPopupMenuProxyWin::calculatePositionAndSize(const IntRect& rect) MONITORINFOEX monitorInfo; monitorInfo.cbSize = sizeof(MONITORINFOEX); ::GetMonitorInfo(monitor, &monitorInfo); - FloatRect screen = monitorInfo.rcWork; + FloatRect screen = static_cast<IntRect>(monitorInfo.rcWork); // Check that we don't go off the screen vertically if (popupRect.maxY() > screen.height()) { diff --git a/Source/WebKit2/UIProcess/win/WebView.cpp b/Source/WebKit2/UIProcess/win/WebView.cpp index 4e4e33f1f..f6e75d68a 100644 --- a/Source/WebKit2/UIProcess/win/WebView.cpp +++ b/Source/WebKit2/UIProcess/win/WebView.cpp @@ -1080,7 +1080,7 @@ void WebView::setScrollOffsetOnNextResize(const IntSize& scrollOffset) m_nextResizeScrollOffset = scrollOffset; } -void WebView::didChangeViewportProperties(const WebCore::ViewportArguments&) +void WebView::didChangeViewportProperties(const WebCore::ViewportAttributes&) { } @@ -1738,7 +1738,8 @@ HRESULT STDMETHODCALLTYPE WebView::Drop(IDataObject* pDataObject, DWORD grfKeySt bool createdExtension = maybeCreateSandboxExtensionFromDragData(data, sandboxExtensionHandle); if (createdExtension) m_page->process()->willAcquireUniversalFileReadSandboxExtension(); - m_page->performDrag(&data, String(), sandboxExtensionHandle); + SandboxExtension::HandleArray sandboxExtensionForUpload; + m_page->performDrag(&data, String(), sandboxExtensionHandle, sandboxExtensionForUpload); return S_OK; } diff --git a/Source/WebKit2/UIProcess/win/WebView.h b/Source/WebKit2/UIProcess/win/WebView.h index daa13c17b..dba1593f1 100644 --- a/Source/WebKit2/UIProcess/win/WebView.h +++ b/Source/WebKit2/UIProcess/win/WebView.h @@ -185,7 +185,7 @@ private: virtual void toolTipChanged(const WTF::String&, const WTF::String&); virtual void setCursor(const WebCore::Cursor&); virtual void setCursorHiddenUntilMouseMoves(bool); - virtual void didChangeViewportProperties(const WebCore::ViewportArguments&); + virtual void didChangeViewportProperties(const WebCore::ViewportAttributes&); virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); virtual bool canUndoRedo(WebPageProxy::UndoOrRedo); |