diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/API')
54 files changed, 1890 insertions, 187 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp index a92104dac..9fe8d6ab9 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.cpp @@ -328,6 +328,16 @@ bool WKPreferencesGetDeveloperExtrasEnabled(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->developerExtrasEnabled(); } +void WKPreferencesSetJavaScriptExperimentsEnabled(WKPreferencesRef preferencesRef, bool enabled) +{ + toImpl(preferencesRef)->setJavaScriptExperimentsEnabled(enabled); +} + +bool WKPreferencesGetJavaScriptExperimentsEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->javaScriptExperimentsEnabled(); +} + void WKPreferencesSetTextAreasAreResizable(WKPreferencesRef preferencesRef, bool resizable) { toImpl(preferencesRef)->setTextAreasAreResizable(resizable); @@ -428,6 +438,16 @@ bool WKPreferencesGetCSSRegionsEnabled(WKPreferencesRef preferencesRef) return toImpl(preferencesRef)->cssRegionsEnabled(); } +void WKPreferencesSetCSSGridLayoutEnabled(WKPreferencesRef preferencesRef, bool flag) +{ + toImpl(preferencesRef)->setCSSGridLayoutEnabled(flag); +} + +bool WKPreferencesGetCSSGridLayoutEnabled(WKPreferencesRef preferencesRef) +{ + return toImpl(preferencesRef)->cssGridLayoutEnabled(); +} + void WKPreferencesSetRegionBasedColumnsEnabled(WKPreferencesRef preferencesRef, bool flag) { toImpl(preferencesRef)->setRegionBasedColumnsEnabled(flag); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferences.h b/Source/WebKit2/UIProcess/API/C/WKPreferences.h index 5e885738e..42f94957e 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferences.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferences.h @@ -133,6 +133,10 @@ WK_EXPORT bool WKPreferencesGetPrivateBrowsingEnabled(WKPreferencesRef preferenc WK_EXPORT void WKPreferencesSetDeveloperExtrasEnabled(WKPreferencesRef preferencesRef, bool enabled); WK_EXPORT bool WKPreferencesGetDeveloperExtrasEnabled(WKPreferencesRef preferencesRef); +// Defaults to false. +WK_EXPORT void WKPreferencesSetJavaScriptExperimentsEnabled(WKPreferencesRef preferencesRef, bool enabled); +WK_EXPORT bool WKPreferencesGetJavaScriptExperimentsEnabled(WKPreferencesRef preferencesRef); + // Defaults to true. WK_EXPORT void WKPreferencesSetTextAreasAreResizable(WKPreferencesRef preferencesRef, bool resizable); WK_EXPORT bool WKPreferencesGetTextAreasAreResizable(WKPreferencesRef preferencesRef); diff --git a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h index cbe6b4fd6..6dbc47310 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h +++ b/Source/WebKit2/UIProcess/API/C/WKPreferencesPrivate.h @@ -96,6 +96,10 @@ WK_EXPORT void WKPreferencesSetCSSRegionsEnabled(WKPreferencesRef, bool flag); WK_EXPORT bool WKPreferencesGetCSSRegionsEnabled(WKPreferencesRef); // Defaults to false +WK_EXPORT void WKPreferencesSetCSSGridLayoutEnabled(WKPreferencesRef, bool flag); +WK_EXPORT bool WKPreferencesGetCSSGridLayoutEnabled(WKPreferencesRef); + +// Defaults to false WK_EXPORT void WKPreferencesSetRegionBasedColumnsEnabled(WKPreferencesRef, bool flag); WK_EXPORT bool WKPreferencesGetRegionBasedColumnsEnabled(WKPreferencesRef); diff --git a/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.cpp b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.cpp new file mode 100644 index 000000000..c9d777c4d --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.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 "WKInspectorClientGtk.h" + +#include "WKAPICast.h" +#include "WebInspectorProxy.h" + +using namespace WebKit; + +void WKInspectorSetInspectorClientGtk(WKInspectorRef inspectorRef, const WKInspectorClientGtk* wkClient) +{ + toImpl(inspectorRef)->initializeInspectorClientGtk(wkClient); +} diff --git a/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h new file mode 100644 index 000000000..865e19ae3 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h @@ -0,0 +1,61 @@ +/* + * 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 WKInspectorClientGtk_h +#define WKInspectorClientGtk_h + +#include <WebKit2/WKBase.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef bool (*WKInspectorClientGtkInspectorCallback)(WKInspectorRef inspector, const void* clientInfo); +typedef void (*WKInspectorClientGtkInspectorDidCloseCallback)(WKInspectorRef inspector, const void* clientInfo); +typedef void (*WKInspectorClientGtkInspectedURLChangedCallback)(WKInspectorRef inspector, WKStringRef url, const void* clientInfo); +typedef void (*WKInspectorClientGtkDidChangeAttachedHeightCallback)(WKInspectorRef inspector, unsigned height, const void* clientInfo); + +struct WKInspectorClientGtk { + int version; + const void* clientInfo; + WKInspectorClientGtkInspectorCallback openWindow; + WKInspectorClientGtkInspectorDidCloseCallback didClose; + WKInspectorClientGtkInspectorCallback bringToFront; + WKInspectorClientGtkInspectedURLChangedCallback inspectedURLChanged; + WKInspectorClientGtkInspectorCallback attach; + WKInspectorClientGtkInspectorCallback detach; + WKInspectorClientGtkDidChangeAttachedHeightCallback didChangeAttachedHeight; +}; +typedef struct WKInspectorClientGtk WKInspectorClientGtk; + +enum { kWKInspectorClientGtkCurrentVersion = 0 }; + +WK_EXPORT void WKInspectorSetInspectorClientGtk(WKInspectorRef inspectorRef, const WKInspectorClientGtk* client); + +#ifdef __cplusplus +} +#endif + +#endif /* WKInspectorClientGtk_h */ diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp index 1caca868e..ebeb92034 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitBackForwardList.cpp @@ -254,7 +254,8 @@ GList* webkit_back_forward_list_get_back_list(WebKitBackForwardList* backForward g_return_val_if_fail(WEBKIT_IS_BACK_FORWARD_LIST(backForwardList), 0); guint limit = WKBackForwardListGetBackListCount(backForwardList->priv->wkList); - return webkitBackForwardListCreateList(backForwardList, WKBackForwardListCopyBackListWithLimit(backForwardList->priv->wkList, limit)); + WKRetainPtr<WKArrayRef> wkList(AdoptWK, WKBackForwardListCopyBackListWithLimit(backForwardList->priv->wkList, limit)); + return webkitBackForwardListCreateList(backForwardList, wkList.get()); } /** @@ -269,7 +270,8 @@ GList* webkit_back_forward_list_get_back_list_with_limit(WebKitBackForwardList* { g_return_val_if_fail(WEBKIT_IS_BACK_FORWARD_LIST(backForwardList), 0); - return webkitBackForwardListCreateList(backForwardList, WKBackForwardListCopyBackListWithLimit(backForwardList->priv->wkList, limit)); + WKRetainPtr<WKArrayRef> wkList(AdoptWK, WKBackForwardListCopyBackListWithLimit(backForwardList->priv->wkList, limit)); + return webkitBackForwardListCreateList(backForwardList, wkList.get()); } /** @@ -284,7 +286,8 @@ GList* webkit_back_forward_list_get_forward_list(WebKitBackForwardList* backForw g_return_val_if_fail(WEBKIT_IS_BACK_FORWARD_LIST(backForwardList), 0); guint limit = WKBackForwardListGetForwardListCount(backForwardList->priv->wkList); - return webkitBackForwardListCreateList(backForwardList, WKBackForwardListCopyForwardListWithLimit(backForwardList->priv->wkList, limit)); + WKRetainPtr<WKArrayRef> wkList(AdoptWK, WKBackForwardListCopyForwardListWithLimit(backForwardList->priv->wkList, limit)); + return webkitBackForwardListCreateList(backForwardList, wkList.get()); } /** @@ -299,5 +302,6 @@ GList* webkit_back_forward_list_get_forward_list_with_limit(WebKitBackForwardLis { g_return_val_if_fail(WEBKIT_IS_BACK_FORWARD_LIST(backForwardList), 0); - return webkitBackForwardListCreateList(backForwardList, WKBackForwardListCopyForwardListWithLimit(backForwardList->priv->wkList, limit)); + WKRetainPtr<WKArrayRef> wkList(AdoptWK, WKBackForwardListCopyForwardListWithLimit(backForwardList->priv->wkList, limit)); + return webkitBackForwardListCreateList(backForwardList, wkList.get()); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp index b993d2e83..7d8a10e1f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp @@ -117,16 +117,28 @@ void webkit_cookie_manager_set_accept_policy(WebKitCookieManager* manager, WebKi WKCookieManagerSetHTTPCookieAcceptPolicy(manager->priv->wkCookieManager.get(), policy); } +struct GetAcceptPolicyAsyncData { + WKHTTPCookieAcceptPolicy policy; + GRefPtr<GCancellable> cancellable; +}; +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetAcceptPolicyAsyncData) + 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); + GetAcceptPolicyAsyncData* data = static_cast<GetAcceptPolicyAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get())); + GError* error = 0; + if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error)) + g_simple_async_result_take_error(result.get(), error); + else + data->policy = policy; g_simple_async_result_complete(result.get()); } /** * webkit_cookie_manager_get_accept_policy: * @cookie_manager: a #WebKitCookieManager + * @cancellable: (allow-none): a #GCancellable or %NULL to ignore * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied * @user_data: (closure): the data to pass to callback function * @@ -135,12 +147,16 @@ static void webkitCookieManagerGetAcceptPolicyCallback(WKHTTPCookieAcceptPolicy * 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) +void webkit_cookie_manager_get_accept_policy(WebKitCookieManager* manager, GCancellable* cancellable, 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)); + GetAcceptPolicyAsyncData* data = createGetAcceptPolicyAsyncData(); + data->cancellable = cancellable; + g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyGetAcceptPolicyAsyncData)); + WKCookieManagerGetHTTPCookieAcceptPolicy(manager->priv->wkCookieManager.get(), result, webkitCookieManagerGetAcceptPolicyCallback); } @@ -165,28 +181,41 @@ WebKitCookieAcceptPolicy webkit_cookie_manager_get_accept_policy_finish(WebKitCo 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))); + GetAcceptPolicyAsyncData* data = static_cast<GetAcceptPolicyAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return static_cast<WebKitCookieAcceptPolicy>(data->policy); } +struct GetDomainsWithCookiesAsyncData { + GRefPtr<GPtrArray> domains; + GRefPtr<GCancellable> cancellable; +}; +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetDomainsWithCookiesAsyncData) + 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())); + GetDomainsWithCookiesAsyncData* data = static_cast<GetDomainsWithCookiesAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get())); + GError* error = 0; + if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error)) + g_simple_async_result_take_error(result.get(), error); + else { + data->domains = adoptGRef(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(data->domains.get(), g_strdup(domain.utf8().data())); + } + g_ptr_array_add(data->domains.get(), 0); } - 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 + * @cancellable: (allow-none): a #GCancellable or %NULL to ignore * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied * @user_data: (closure): the data to pass to callback function * @@ -195,12 +224,15 @@ static void webkitCookieManagerGetDomainsWithCookiesCallback(WKArrayRef wkDomain * 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) +void webkit_cookie_manager_get_domains_with_cookies(WebKitCookieManager* manager, GCancellable* cancellable, 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)); + GetDomainsWithCookiesAsyncData* data = createGetDomainsWithCookiesAsyncData(); + data->cancellable = cancellable; + g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyGetDomainsWithCookiesAsyncData)); WKCookieManagerGetHostnamesWithCookies(manager->priv->wkCookieManager.get(), result, webkitCookieManagerGetDomainsWithCookiesCallback); } @@ -228,8 +260,8 @@ gchar** webkit_cookie_manager_get_domains_with_cookies_finish(WebKitCookieManage 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)); + GetDomainsWithCookiesAsyncData* data = static_cast<GetDomainsWithCookiesAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return reinterpret_cast<char**>(g_ptr_array_free(data->domains.leakRef(), FALSE)); } /** diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h index 791a61d82..2472d96a2 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.h @@ -74,6 +74,7 @@ webkit_cookie_manager_set_accept_policy (WebKitCookieManager * WEBKIT_API void webkit_cookie_manager_get_accept_policy (WebKitCookieManager *cookie_manager, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -84,6 +85,7 @@ webkit_cookie_manager_get_accept_policy_finish (WebKitCookieManager * WEBKIT_API void webkit_cookie_manager_get_domains_with_cookies (WebKitCookieManager *cookie_manager, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h index 4b7e9ad49..b7c537015 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h @@ -30,6 +30,8 @@ #include <WebKit2/WKDownload.h> #include <WebKit2/WKFindOptions.h> #include <WebKit2/WKFullScreenClientGtk.h> +#include <WebKit2/WKInspector.h> +#include <WebKit2/WKInspectorClientGtk.h> #include <WebKit2/WKRetainPtr.h> #include <WebKit2/WKSerializedScriptValue.h> #include <WebKit2/WKString.h> @@ -44,6 +46,19 @@ #define COMPILE_ASSERT_MATCHING_ENUM(webkitName, webcoreName) \ COMPILE_ASSERT(int(webkitName) == int(webcoreName), mismatchingEnums) +#define WEBKIT_DEFINE_ASYNC_DATA_STRUCT(structName) \ +static structName* create##structName() \ +{ \ + structName* data = g_slice_new0(structName); \ + new (data) structName(); \ + return data; \ +} \ +static void destroy##structName(structName* data) \ +{ \ + data->~structName(); \ + g_slice_free(structName, data); \ +} + unsigned wkEventModifiersToGdkModifiers(WKEventModifiers); #endif // WebKitPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index cd04eb12b..02e82b020 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -108,7 +108,8 @@ enum { PROP_ZOOM_TEXT_ONLY, PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD, PROP_MEDIA_PLAYBACK_REQUIRES_USER_GESTURE, - PROP_MEDIA_PLAYBACK_ALLOWS_INLINE + PROP_MEDIA_PLAYBACK_ALLOWS_INLINE, + PROP_DRAW_COMPOSITING_INDICATORS }; static void webKitSettingsSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec) @@ -227,6 +228,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu case PROP_MEDIA_PLAYBACK_ALLOWS_INLINE: webkit_settings_set_media_playback_allows_inline(settings, g_value_get_boolean(value)); break; + case PROP_DRAW_COMPOSITING_INDICATORS: + webkit_settings_set_draw_compositing_indicators(settings, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -349,6 +353,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val case PROP_MEDIA_PLAYBACK_ALLOWS_INLINE: g_value_set_boolean(value, webkit_settings_get_media_playback_allows_inline(settings)); break; + case PROP_DRAW_COMPOSITING_INDICATORS: + g_value_set_boolean(value, webkit_settings_get_draw_compositing_indicators(settings)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); break; @@ -908,6 +915,21 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass) TRUE, readWriteConstructParamFlags)); + /** + * WebKitSettings:draw-compositing-indicators: + * + * Whether to draw compositing borders and repaint counters on layers drawn + * with accelerated compositing. This is useful for debugging issues related + * to web content that is composited with the GPU. + */ + g_object_class_install_property(gObjectClass, + PROP_DRAW_COMPOSITING_INDICATORS, + g_param_spec_boolean("draw-compositing-indicators", + _("Draw compositing indicators"), + _("Whether to draw compositing borders and repaint counters"), + FALSE, + readWriteConstructParamFlags)); + g_type_class_add_private(klass, sizeof(WebKitSettingsPrivate)); } @@ -2313,3 +2335,39 @@ gboolean webkit_settings_get_media_playback_allows_inline(WebKitSettings* settin return WKPreferencesGetMediaPlaybackAllowsInline(settings->priv->preferences.get()); } + +/** + * webkit_settings_set_draw_compositing_indicators: + * @settings: a #WebKitSettings + * @enabled: Value to be set + * + * Set the #WebKitSettings:draw-compositing-indicators property. + */ +void webkit_settings_set_draw_compositing_indicators(WebKitSettings* settings, gboolean enabled) +{ + g_return_if_fail(WEBKIT_IS_SETTINGS(settings)); + + WebKitSettingsPrivate* priv = settings->priv; + if (WKPreferencesGetCompositingBordersVisible(priv->preferences.get()) == enabled + && WKPreferencesGetCompositingRepaintCountersVisible(priv->preferences.get()) == enabled) + return; + + WKPreferencesSetCompositingBordersVisible(priv->preferences.get(), enabled); + WKPreferencesSetCompositingRepaintCountersVisible(priv->preferences.get(), enabled); + g_object_notify(G_OBJECT(settings), "draw-compositing-indicators"); +} + +/** + * webkit_settings_get_draw_compositing_indicators: + * @settings: a #WebKitSettings + * + * Get the #WebKitSettings:draw-compositing-indicators property. + * + * Returns: %TRUE If compositing borders are drawn or %FALSE otherwise. + */ +gboolean webkit_settings_get_draw_compositing_indicators(WebKitSettings* settings) +{ + g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE); + return WKPreferencesGetCompositingBordersVisible(settings->priv->preferences.get()) + && WKPreferencesGetCompositingRepaintCountersVisible(settings->priv->preferences.get()); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h index fda7089d0..53ebda299 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h @@ -334,6 +334,12 @@ webkit_settings_get_media_playback_allows_inline (WebKitSettings * WEBKIT_API void webkit_settings_set_media_playback_allows_inline (WebKitSettings *settings, gboolean enabled); +WEBKIT_API gboolean +webkit_settings_get_draw_compositing_indicators (WebKitSettings *settings); + +WEBKIT_API void +webkit_settings_set_draw_compositing_indicators (WebKitSettings *settings, + gboolean enabled); G_END_DECLS #endif /* WebKitSettings_h */ diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 5ec64d9d5..681c0d12b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -256,19 +256,7 @@ void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* conte struct GetPluginsAsyncData { Vector<PluginModuleInfo> plugins; }; - -static GetPluginsAsyncData* getPluginsAsyncDataCreate() -{ - GetPluginsAsyncData* data = g_slice_new(GetPluginsAsyncData); - new (data) GetPluginsAsyncData(); - return data; -} - -static void getPluginsAsyncDataDestroy(GetPluginsAsyncData* data) -{ - data->~GetPluginsAsyncData(); - g_slice_free(GetPluginsAsyncData, data); -} +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetPluginsAsyncData) static void webkitWebContextGetPluginThread(GSimpleAsyncResult* result, GObject* object, GCancellable*) { @@ -294,8 +282,8 @@ void webkit_web_context_get_plugins(WebKitWebContext* context, GCancellable* can GRefPtr<GSimpleAsyncResult> result = adoptGRef(g_simple_async_result_new(G_OBJECT(context), callback, userData, reinterpret_cast<gpointer>(webkit_web_context_get_plugins))); - g_simple_async_result_set_op_res_gpointer(result.get(), getPluginsAsyncDataCreate(), - reinterpret_cast<GDestroyNotify>(getPluginsAsyncDataDestroy)); + g_simple_async_result_set_op_res_gpointer(result.get(), createGetPluginsAsyncData(), + reinterpret_cast<GDestroyNotify>(destroyGetPluginsAsyncData)); g_simple_async_result_run_in_thread(result.get(), webkitWebContextGetPluginThread, G_PRIORITY_DEFAULT, cancellable); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp new file mode 100644 index 000000000..25023cf94 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp @@ -0,0 +1,445 @@ +/* + * 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 "WebKitWebInspector.h" + +#include "WebInspectorProxy.h" +#include "WebKitMarshal.h" +#include "WebKitWebInspectorPrivate.h" +#include <glib/gi18n-lib.h> +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +using namespace WebKit; + +enum { + OPEN_WINDOW, + BRING_TO_FRONT, + CLOSED, + ATTACH, + DETACH, + + LAST_SIGNAL +}; + +enum { + PROP_0, + + PROP_INSPECTED_URI, + PROP_ATTACHED_HEIGHT +}; + +struct _WebKitWebInspectorPrivate { + WKRetainPtr<WKInspectorRef> wkInspector; + CString inspectedURI; + unsigned attachedHeight; +}; + +static guint signals[LAST_SIGNAL] = { 0, }; + +G_DEFINE_TYPE(WebKitWebInspector, webkit_web_inspector, G_TYPE_OBJECT) + +static void webkitWebInspectorGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) +{ + WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(object); + + switch (propId) { + case PROP_INSPECTED_URI: + g_value_set_string(value, webkit_web_inspector_get_inspected_uri(inspector)); + break; + case PROP_ATTACHED_HEIGHT: + g_value_set_uint(value, webkit_web_inspector_get_attached_height(inspector)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); + } +} + +static void webkitWebInspectorFinalize(GObject* object) +{ + WebKitWebInspectorPrivate* priv = WEBKIT_WEB_INSPECTOR(object)->priv; + WKInspectorSetInspectorClientGtk(priv->wkInspector.get(), 0); + priv->~WebKitWebInspectorPrivate(); + G_OBJECT_CLASS(webkit_web_inspector_parent_class)->finalize(object); +} + +static void webkit_web_inspector_init(WebKitWebInspector* inspector) +{ + WebKitWebInspectorPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(inspector, WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorPrivate); + inspector->priv = priv; + new (priv) WebKitWebInspectorPrivate(); +} + +static void webkit_web_inspector_class_init(WebKitWebInspectorClass* findClass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass); + gObjectClass->finalize = webkitWebInspectorFinalize; + gObjectClass->get_property = webkitWebInspectorGetProperty; + + g_type_class_add_private(findClass, sizeof(WebKitWebInspectorPrivate)); + + /** + * WebKitWebInspector:inspected-uri: + * + * The URI that is currently being inspected. + */ + g_object_class_install_property(gObjectClass, + PROP_INSPECTED_URI, + g_param_spec_string("inspected-uri", + _("Inspected URI"), + _("The URI that is currently being inspected"), + 0, + WEBKIT_PARAM_READABLE)); + /** + * WebKitWebInspector:attached-height: + * + * The height that the inspector view should have when it is attached. + */ + g_object_class_install_property(gObjectClass, + PROP_ATTACHED_HEIGHT, + g_param_spec_uint("attached-height", + _("Attached Height"), + _("The height that the inspector view should have when it is attached"), + 0, G_MAXUINT, 0, + WEBKIT_PARAM_READABLE)); + + /** + * WebKitWebInspector::open-window: + * @inspector: the #WebKitWebInspector on which the signal is emitted + * + * Emitted when the inspector is requested to open in a separate window. + * If this signal is not handled, a #GtkWindow with the inspector will be + * created and shown, so you only need to handle this signal if you want + * to use your own window. + * This signal is emitted after #WebKitWebInspector::detach to show + * the inspector in a separate window after being detached. + * + * To prevent the inspector from being shown you can connect to this + * signal and simply return %TRUE + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[OPEN_WINDOW] = + g_signal_new("open-window", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitWebInspector::bring-to-front: + * @inspector: the #WebKitWebInspector on which the signal is emitted + * + * Emitted when the inspector should be shown. + * + * If the inspector is not attached the inspector window should be shown + * on top of any other windows. + * If the inspector is attached the inspector view should be made visible. + * For example, if the inspector view is attached using a tab in a browser + * window, the browser window should be raised and the tab containing the + * inspector view should be the active one. + * In both cases, if this signal is not handled, the default implementation + * calls gtk_window_present() on the current toplevel #GtkWindow of the + * inspector view. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[BRING_TO_FRONT] = + g_signal_new("bring-to-front", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitWebInspector::closed: + * @inspector: the #WebKitWebInspector on which the signal is emitted + * + * Emitted when the inspector page is closed. If you are using your own + * inspector window, you should connect to this signal and destroy your + * window. + */ + signals[CLOSED] = + g_signal_new("closed", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, 0, 0, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * WebKitWebInspector::attach: + * @inspector: the #WebKitWebInspector on which the signal is emitted + * + * Emitted when the inspector is requested to be attached to the window + * where the inspected web view is. + * If this signal is not handled the inspector view will be automatically + * attached to the inspected view, so you only need to handle this signal + * if you want to attach the inspector view yourself (for example, to add + * the inspector view to a browser tab). + * + * To prevent the inspector vew from being attached you can connect to this + * signal and simply return %TRUE. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[ATTACH] = + g_signal_new("attach", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /** + * WebKitWebInspector::detach: + * @inspector: the #WebKitWebInspector on which the signal is emitted + * + * Emitted when the inspector is requested to be detached from the window + * it is currently attached to. The inspector is detached when the inspector page + * is about to be closed, and this signal is emitted right before + * #WebKitWebInspector::closed, or when the user clicks on the detach button + * in the inspector view to show the inspector in a separate window. In this case + * the signal #WebKitWebInspector::open-window is emitted after this one. + * + * To prevent the inspector vew from being detached you can connect to this + * signal and simply return %TRUE. + * + * Returns: %TRUE to stop other handlers from being invoked for the event. + * %FALSE to propagate the event further. + */ + signals[DETACH] = + g_signal_new("detach", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, 0, + webkit_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); +} + +static bool openWindow(WKInspectorRef, const void* clientInfo) +{ + gboolean returnValue; + g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[OPEN_WINDOW], 0, &returnValue); + return returnValue; +} + +static void didClose(WKInspectorRef, const void* clientInfo) +{ + g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[CLOSED], 0); +} + +static bool bringToFront(WKInspectorRef, const void* clientInfo) +{ + gboolean returnValue; + g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[BRING_TO_FRONT], 0, &returnValue); + return returnValue; +} + +static void inspectedURLChanged(WKInspectorRef, WKStringRef url, const void* clientInfo) +{ + WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(clientInfo); + CString uri = toImpl(url)->string().utf8(); + if (uri == inspector->priv->inspectedURI) + return; + inspector->priv->inspectedURI = uri; + g_object_notify(G_OBJECT(inspector), "inspected-uri"); +} + +static bool attach(WKInspectorRef, const void* clientInfo) +{ + gboolean returnValue; + g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[ATTACH], 0, &returnValue); + return returnValue; +} + +static bool detach(WKInspectorRef inspector, const void* clientInfo) +{ + gboolean returnValue; + g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[DETACH], 0, &returnValue); + return returnValue; +} + +static void didChangeAttachedHeight(WKInspectorRef, unsigned height, const void* clientInfo) +{ + WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(clientInfo); + if (inspector->priv->attachedHeight == height) + return; + inspector->priv->attachedHeight = height; + g_object_notify(G_OBJECT(inspector), "attached-height"); +} + +WebKitWebInspector* webkitWebInspectorCreate(WKInspectorRef wkInspector) +{ + WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(g_object_new(WEBKIT_TYPE_WEB_INSPECTOR, NULL)); + inspector->priv->wkInspector = wkInspector; + + WKInspectorClientGtk wkInspectorClientGtk = { + kWKInspectorClientGtkCurrentVersion, + inspector, // clientInfo + openWindow, + didClose, + bringToFront, + inspectedURLChanged, + attach, + detach, + didChangeAttachedHeight + }; + WKInspectorSetInspectorClientGtk(wkInspector, &wkInspectorClientGtk); + + return inspector; +} + +/** + * webkit_web_inspector_get_web_view: + * @inspector: a #WebKitWebInspector + * + * Get the #WebKitWebViewBase used to display the inspector. + * This might be %NULL if the inspector hasn't been loaded yet, + * or it has been closed. + * + * Returns: (transfer none): the #WebKitWebViewBase used to display the inspector or %NULL + */ +WebKitWebViewBase* webkit_web_inspector_get_web_view(WebKitWebInspector* inspector) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), 0); + + return WEBKIT_WEB_VIEW_BASE(toImpl(inspector->priv->wkInspector.get())->inspectorView()); +} + +/** + * webkit_web_inspector_get_inspected_uri: + * @inspector: a #WebKitWebInspector + * + * Get the URI that is currently being inspected. This can be %NULL if + * nothing has been loaded yet in the inspected view, if the inspector + * has been closed or when inspected view was loaded from a HTML string + * instead of a URI. + * + * Returns: the URI that is currently being inspected or %NULL + */ +const char* webkit_web_inspector_get_inspected_uri(WebKitWebInspector* inspector) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), 0); + + return inspector->priv->inspectedURI.data(); +} + +/** + * webkit_web_inspector_is_attached: + * @inspector: a #WebKitWebInspector + * + * Whether the @inspector view is currently attached to the same window that contains + * the inspected view. + * + * Returns: %TRUE if @inspector is currently attached or %FALSE otherwise + */ +gboolean webkit_web_inspector_is_attached(WebKitWebInspector* inspector) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), FALSE); + + return WKInspectorIsAttached(inspector->priv->wkInspector.get()); +} + +/** + * webkit_web_inspector_attach: + * @inspector: a #WebKitWebInspector + * + * Request @inspector to be attached. The signal #WebKitWebInspector::attach + * will be emitted. If the inspector is already attached it does nothing. + */ +void webkit_web_inspector_attach(WebKitWebInspector* inspector) +{ + g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector)); + + if (WKInspectorIsAttached(inspector->priv->wkInspector.get())) + return; + WKInspectorAttach(inspector->priv->wkInspector.get()); +} + +/** + * webkit_web_inspector_detach: + * @inspector: a #WebKitWebInspector + * + * Request @inspector to be detached. The signal #WebKitWebInspector::detach + * will be emitted. If the inspector is already detached it does nothing. + */ +void webkit_web_inspector_detach(WebKitWebInspector* inspector) +{ + g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector)); + + if (!WKInspectorIsAttached(inspector->priv->wkInspector.get())) + return; + WKInspectorDetach(inspector->priv->wkInspector.get()); +} + +/** + * webkit_web_inspector_show: + * @inspector: a #WebKitWebInspector + * + * Request @inspector to be shown. + */ +void webkit_web_inspector_show(WebKitWebInspector* inspector) +{ + g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector)); + + WKInspectorShow(inspector->priv->wkInspector.get()); +} + +/** + * webkit_web_inspector_close: + * @inspector: a #WebKitWebInspector + * + * Request @inspector to be closed. + */ +void webkit_web_inspector_close(WebKitWebInspector* inspector) +{ + g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector)); + + WKInspectorClose(inspector->priv->wkInspector.get()); +} + +/** + * webkit_web_inspector_get_attached_height: + * @inspector: a #WebKitWebInspector + * + * Get the height that the inspector view should have when + * it's attached. If the inspector view is not attached this + * returns 0. + * + * Returns: the height of the inspector view when attached + */ +guint webkit_web_inspector_get_attached_height(WebKitWebInspector* inspector) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), 0); + + if (!WKInspectorIsAttached(inspector->priv->wkInspector.get())) + return 0; + return inspector->priv->attachedHeight; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h new file mode 100644 index 000000000..10c281094 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h @@ -0,0 +1,83 @@ +/* + * 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 WebKitWebInspector_h +#define WebKitWebInspector_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> +#include <webkit2/WebKitWebViewBase.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_INSPECTOR (webkit_web_inspector_get_type()) +#define WEBKIT_WEB_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspector)) +#define WEBKIT_IS_WEB_INSPECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_INSPECTOR)) +#define WEBKIT_WEB_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorClass)) +#define WEBKIT_IS_WEB_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_WEB_INSPECTOR)) +#define WEBKIT_WEB_INSPECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorClass)) + +typedef struct _WebKitWebInspector WebKitWebInspector; +typedef struct _WebKitWebInspectorClass WebKitWebInspectorClass; +typedef struct _WebKitWebInspectorPrivate WebKitWebInspectorPrivate; + +struct _WebKitWebInspector { + GObject parent; + + WebKitWebInspectorPrivate *priv; +}; + +struct _WebKitWebInspectorClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_web_inspector_get_type (void); + +WEBKIT_API WebKitWebViewBase * +webkit_web_inspector_get_web_view (WebKitWebInspector *inspector); + +WEBKIT_API const char * +webkit_web_inspector_get_inspected_uri (WebKitWebInspector *inspector); + +WEBKIT_API gboolean +webkit_web_inspector_is_attached (WebKitWebInspector *inspector); + +WEBKIT_API void +webkit_web_inspector_attach (WebKitWebInspector *inspector); + +WEBKIT_API void +webkit_web_inspector_detach (WebKitWebInspector *inspector); + +WEBKIT_API void +webkit_web_inspector_show (WebKitWebInspector *inspector); + +WEBKIT_API void +webkit_web_inspector_close (WebKitWebInspector *inspector); + +WEBKIT_API guint +webkit_web_inspector_get_attached_height (WebKitWebInspector *inspector); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.h new file mode 100644 index 000000000..703472137 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.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 WebKitWebInspectorPrivate_h +#define WebKitWebInspectorPrivate_h + +#include "WebKitPrivate.h" +#include "WebKitWebInspector.h" + +WebKitWebInspector* webkitWebInspectorCreate(WKInspectorRef); + +#endif // WebKitWebInspectorPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp index 6bd51fa08..7fbe28a0a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp @@ -301,16 +301,28 @@ WebKitURIResponse* webkit_web_resource_get_response(WebKitWebResource* resource) return resource->priv->response.get(); } -static void resourceDataCallback(WKDataRef data, WKErrorRef, void* context) +struct ResourceGetDataAsyncData { + WKDataRef wkData; + GRefPtr<GCancellable> cancellable; +}; +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ResourceGetDataAsyncData) + +static void resourceDataCallback(WKDataRef wkData, 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); + ResourceGetDataAsyncData* data = static_cast<ResourceGetDataAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get())); + GError* error = 0; + if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error)) + g_simple_async_result_take_error(result.get(), error); + else + data->wkData = wkData; g_simple_async_result_complete(result.get()); } /** * webkit_web_resource_get_data: * @resource: a #WebKitWebResource + * @cancellable: (allow-none): a #GCancellable or %NULL to ignore * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied * @user_data: (closure): the data to pass to callback function * @@ -319,12 +331,15 @@ static void resourceDataCallback(WKDataRef data, WKErrorRef, void* context) * 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) +void webkit_web_resource_get_data(WebKitWebResource* resource, GCancellable* cancellable, 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)); + ResourceGetDataAsyncData* data = createResourceGetDataAsyncData(); + data->cancellable = cancellable; + g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyResourceGetDataAsyncData)); if (resource->priv->isMainResource) WKFrameGetMainResourceData(resource->priv->wkFrame.get(), resourceDataCallback, result); else { @@ -356,8 +371,8 @@ guchar* webkit_web_resource_get_data_finish(WebKitWebResource* resource, GAsyncR 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)); + ResourceGetDataAsyncData* data = static_cast<ResourceGetDataAsyncData*>(g_simple_async_result_get_op_res_gpointer(simple)); if (length) - *length = WKDataGetSize(wkData); - return static_cast<guchar*>(g_memdup(WKDataGetBytes(wkData), WKDataGetSize(wkData))); + *length = WKDataGetSize(data->wkData); + return static_cast<guchar*>(g_memdup(WKDataGetBytes(data->wkData), WKDataGetSize(data->wkData))); } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h index 34af76e2b..1cfada0fb 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h @@ -63,6 +63,7 @@ webkit_web_resource_get_response (WebKitWebResource *resource); WEBKIT_API void webkit_web_resource_get_data (WebKitWebResource *resource, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp index 56b21df49..65dab6ec2 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp @@ -37,6 +37,7 @@ #include "WebKitSettingsPrivate.h" #include "WebKitUIClient.h" #include "WebKitWebContextPrivate.h" +#include "WebKitWebInspectorPrivate.h" #include "WebKitWebResourcePrivate.h" #include "WebKitWebViewBasePrivate.h" #include "WebKitWebViewPrivate.h" @@ -120,6 +121,8 @@ struct _WebKitWebViewPrivate { GRefPtr<WebKitWebResource> mainResource; LoadingResourcesMap loadingResourcesMap; ResourcesMap subresourcesMap; + + GRefPtr<WebKitWebInspector> inspector; }; static guint signals[LAST_SIGNAL] = { 0, }; @@ -1618,10 +1621,21 @@ gdouble webkit_web_view_get_zoom_level(WebKitWebView* webView) return zoomTextOnly ? WKPageGetTextZoomFactor(wkPage) : WKPageGetPageZoomFactor(wkPage); } +struct ValidateEditingCommandAsyncData { + bool isEnabled; + GRefPtr<GCancellable> cancellable; +}; +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ValidateEditingCommandAsyncData) + static void didValidateCommand(WKStringRef command, bool isEnabled, int32_t state, WKErrorRef, void* context) { GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); - g_simple_async_result_set_op_res_gboolean(result.get(), isEnabled); + ValidateEditingCommandAsyncData* data = static_cast<ValidateEditingCommandAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get())); + GError* error = 0; + if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error)) + g_simple_async_result_take_error(result.get(), error); + else + data->isEnabled = isEnabled; g_simple_async_result_complete(result.get()); } @@ -1629,6 +1643,7 @@ static void didValidateCommand(WKStringRef command, bool isEnabled, int32_t stat * webkit_web_view_can_execute_editing_command: * @web_view: a #WebKitWebView * @command: the command to check + * @cancellable: (allow-none): a #GCancellable or %NULL to ignore * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied * @user_data: (closure): the data to pass to callback function * @@ -1637,13 +1652,17 @@ static void didValidateCommand(WKStringRef command, bool isEnabled, int32_t stat * When the operation is finished, @callback will be called. You can then call * webkit_web_view_can_execute_editing_command_finish() to get the result of the operation. */ -void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const char* command, GAsyncReadyCallback callback, gpointer userData) +void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const char* command, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(command); GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData, reinterpret_cast<gpointer>(webkit_web_view_can_execute_editing_command)); + ValidateEditingCommandAsyncData* data = createValidateEditingCommandAsyncData(); + data->cancellable = cancellable; + g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyValidateEditingCommandAsyncData)); + WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command)); WKPageValidateCommand(toAPI(page), wkCommand.get(), result, didValidateCommand); @@ -1669,7 +1688,9 @@ gboolean webkit_web_view_can_execute_editing_command_finish(WebKitWebView* webVi if (g_simple_async_result_propagate_error(simple, error)) return FALSE; - return g_simple_async_result_get_op_res_gboolean(simple); + + ValidateEditingCommandAsyncData* data = static_cast<ValidateEditingCommandAsyncData*>(g_simple_async_result_get_op_res_gpointer(simple)); + return data->isEnabled; } /** @@ -1730,15 +1751,29 @@ JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* return webView->priv->javascriptGlobalContext; } +struct RunJavaScriptAsyncData { + ~RunJavaScriptAsyncData() + { + if (scriptResult) + webkit_javascript_result_unref(scriptResult); + } + + WebKitJavascriptResult* scriptResult; + GRefPtr<GCancellable> cancellable; +}; +WEBKIT_DEFINE_ASYNC_DATA_STRUCT(RunJavaScriptAsyncData) + static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSerializedScriptValue, WKErrorRef, void* context) { GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context)); - if (wkSerializedScriptValue) { + RunJavaScriptAsyncData* data = static_cast<RunJavaScriptAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get())); + GError* error = 0; + if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error)) + g_simple_async_result_take_error(result.get(), error); + else if (wkSerializedScriptValue) { GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get())))); - WebKitJavascriptResult* scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue); - g_simple_async_result_set_op_res_gpointer(result.get(), scriptResult, reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref)); + data->scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue); } 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); } @@ -1749,6 +1784,7 @@ static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSeri * webkit_web_view_run_javascript: * @web_view: a #WebKitWebView * @script: the script to run + * @cancellable: (allow-none): a #GCancellable or %NULL to ignore * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished * @user_data: (closure): the data to pass to callback function * @@ -1757,7 +1793,7 @@ static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSeri * 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) +void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) { g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); g_return_if_fail(script); @@ -1766,6 +1802,9 @@ void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, 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)); + RunJavaScriptAsyncData* data = createRunJavaScriptAsyncData(); + data->cancellable = cancellable; + g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyRunJavaScriptAsyncData)); WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback); } @@ -1844,8 +1883,8 @@ WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* web 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; + RunJavaScriptAsyncData* data = static_cast<RunJavaScriptAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + return data->scriptResult ? webkit_javascript_result_ref(data->scriptResult) : 0; } /** @@ -1886,3 +1925,23 @@ GList* webkit_web_view_get_subresources(WebKitWebView* webView) return g_list_reverse(subresources); } + +/** + * webkit_web_view_get_inspector: + * @web_view: a #WebKitWebView + * + * Get the #WebKitWebInspector associated to @web_view + * + * Returns: (transfer none): the #WebKitWebInspector of @web_view + */ +WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0); + + if (!webView->priv->inspector) { + WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); + webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(toAPI(page->inspector()))); + } + + return webView->priv->inspector.get(); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h index c56205b96..4f5fe1869 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h @@ -40,6 +40,7 @@ #include <webkit2/WebKitSettings.h> #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitWebContext.h> +#include <webkit2/WebKitWebInspector.h> #include <webkit2/WebKitWebResource.h> #include <webkit2/WebKitWebViewBase.h> #include <webkit2/WebKitWindowProperties.h> @@ -263,6 +264,7 @@ webkit_web_view_get_zoom_level (WebKitWebView *w WEBKIT_API void webkit_web_view_can_execute_editing_command (WebKitWebView *web_view, const gchar *command, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -284,6 +286,7 @@ webkit_web_view_get_javascript_global_context (WebKitWebView *w WEBKIT_API void webkit_web_view_run_javascript (WebKitWebView *web_view, const gchar *script, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WEBKIT_API WebKitJavascriptResult * @@ -296,6 +299,10 @@ webkit_web_view_get_main_resource (WebKitWebView *w WEBKIT_API GList * webkit_web_view_get_subresources (WebKitWebView *web_view); + +WEBKIT_API WebKitWebInspector * +webkit_web_view_get_inspector (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 b2cdde564..4faa75fb0 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp @@ -36,6 +36,7 @@ #include "WebContext.h" #include "WebEventFactory.h" #include "WebFullScreenClientGtk.h" +#include "WebInspectorProxy.h" #include "WebKitPrivate.h" #include "WebKitWebViewBaseAccessible.h" #include "WebKitWebViewBasePrivate.h" @@ -87,10 +88,15 @@ struct _WebKitWebViewBasePrivate { bool fullScreenModeActive; WebFullScreenClientGtk fullScreenClient; #endif + GtkWidget* inspectorView; + unsigned inspectorViewHeight; }; G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER) +// Keep this in sync with the value minimumAttachedHeight in WebInspectorProxy. +static const unsigned gMinimumAttachedInspectorHeight = 250; + static void webkitWebViewBaseNotifyResizerSizeForWindow(WebKitWebViewBase* webViewBase, GtkWindow* window) { gboolean resizerVisible; @@ -170,9 +176,16 @@ static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* wi WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container); WebKitWebViewBasePrivate* priv = webView->priv; - GtkAllocation childAllocation; - gtk_widget_get_allocation(widget, &childAllocation); - priv->children.set(widget, childAllocation); + if (WEBKIT_IS_WEB_VIEW_BASE(widget) + && WebInspectorProxy::isInspectorPage(WEBKIT_WEB_VIEW_BASE(widget)->priv->pageProxy.get())) { + ASSERT(priv->inspectorView); + priv->inspectorView = widget; + priv->inspectorViewHeight = gMinimumAttachedInspectorHeight; + } else { + GtkAllocation childAllocation; + gtk_widget_get_allocation(widget, &childAllocation); + priv->children.set(widget, childAllocation); + } gtk_widget_set_parent(widget, GTK_WIDGET(container)); } @@ -183,11 +196,16 @@ static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* 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 (priv->inspectorView == widget) { + priv->inspectorView = 0; + priv->inspectorViewHeight = 0; + } else { + ASSERT(priv->children.contains(widget)); + priv->children.remove(widget); + } if (wasVisible && gtk_widget_get_visible(widgetContainer)) gtk_widget_queue_resize(widgetContainer); } @@ -201,6 +219,9 @@ static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean i WebKitWebViewChildrenMap::const_iterator end = children.end(); for (WebKitWebViewChildrenMap::const_iterator current = children.begin(); current != end; ++current) (*callback)(current->first, callbackData); + + if (includeInternals && priv->inspectorView) + (*callback)(priv->inspectorView, callbackData); } void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect) @@ -282,9 +303,19 @@ static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase { gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase); + IntRect viewRect(allocation->x, allocation->y, allocation->width, allocation->height); WebKitWebViewBasePrivate* priv = webViewBase->priv; + if (priv->inspectorView) { + GtkAllocation childAllocation = viewRect; + childAllocation.y = allocation->height - priv->inspectorViewHeight; + childAllocation.height = priv->inspectorViewHeight; + gtk_widget_size_allocate(priv->inspectorView, &childAllocation); + + viewRect.setHeight(allocation->height - priv->inspectorViewHeight); + } + if (priv->pageProxy->drawingArea()) - priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize()); + priv->pageProxy->drawingArea()->setSize(viewRect.size(), IntSize()); GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(webViewBase)); if (widgetIsOnscreenToplevelWindow(toplevel)) @@ -404,7 +435,7 @@ static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventBut return TRUE; priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent), priv->clickCounter.clickCountForGdkButtonEvent(widget, buttonEvent))); - return FALSE; + return TRUE; } static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventButton* event) @@ -415,7 +446,7 @@ static gboolean webkitWebViewBaseButtonReleaseEvent(GtkWidget* widget, GdkEventB gtk_widget_grab_focus(widget); priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */)); - return FALSE; + return TRUE; } static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* event) @@ -425,7 +456,7 @@ static gboolean webkitWebViewBaseScrollEvent(GtkWidget* widget, GdkEventScroll* priv->pageProxy->handleWheelEvent(NativeWebWheelEvent(reinterpret_cast<GdkEvent*>(event))); - return FALSE; + return TRUE; } static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMotion* event) @@ -435,7 +466,7 @@ static gboolean webkitWebViewBaseMotionNotifyEvent(GtkWidget* widget, GdkEventMo priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(event), 0 /* currentClickCount */)); - return FALSE; + return TRUE; } static gboolean webkitWebViewBaseQueryTooltip(GtkWidget* widget, gint x, gint y, gboolean keyboardMode, GtkTooltip* tooltip) @@ -718,3 +749,13 @@ void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase* webkitWebVie { webkitWebViewBase->priv->fullScreenClient.initialize(wkClient); } + +void webkitWebViewBaseSetInspectorViewHeight(WebKitWebViewBase* webkitWebViewBase, unsigned height) +{ + if (!webkitWebViewBase->priv->inspectorView) + return; + if (webkitWebViewBase->priv->inspectorViewHeight == height) + return; + webkitWebViewBase->priv->inspectorViewHeight = height; + gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webkitWebViewBase)); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h index cd4c1a1b5..5e191971c 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h @@ -45,5 +45,6 @@ void webkitWebViewBaseChildMoveResize(WebKitWebViewBase*, GtkWidget*, const WebC void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase*); void webkitWebViewBaseExitFullScreen(WebKitWebViewBase*); void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase*, const WKFullScreenClientGtk*); +void webkitWebViewBaseSetInspectorViewHeight(WebKitWebViewBase*, unsigned height); #endif // WebKitWebViewBasePrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index 63db05f77..b6b9aa0b1 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -32,6 +32,7 @@ <xi:include href="xml/WebKitFindController.xml"/> <xi:include href="xml/WebKitCookieManager.xml"/> <xi:include href="xml/WebKitPlugin.xml"/> + <xi:include href="xml/WebKitWebInspector.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 884177b8b..05bdeeb51 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -91,6 +91,7 @@ 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_inspector webkit_web_view_get_javascript_global_context webkit_web_view_run_javascript webkit_web_view_run_javascript_finish @@ -258,6 +259,8 @@ webkit_settings_get_media_playback_requires_user_gesture webkit_settings_set_media_playback_requires_user_gesture webkit_settings_get_media_playback_allows_inline webkit_settings_set_media_playback_allows_inline +webkit_settings_get_draw_compositing_indicators +webkit_settings_set_draw_compositing_indicators <SUBSECTION Standard> WebKitSettingsClass @@ -636,3 +639,29 @@ webkit_plugin_get_type webkit_mime_info_get_type WebKitPluginPrivate </SECTION> + +<SECTION> +<FILE>WebKitWebInspector</FILE> +WebKitWebInspector +webkit_web_inspector_get_web_view +webkit_web_inspector_get_inspected_uri +webkit_web_inspector_is_attached +webkit_web_inspector_attach +webkit_web_inspector_detach +webkit_web_inspector_show +webkit_web_inspector_close +webkit_web_inspector_get_attached_height + +<SUBSECTION Standard> +WebKitWebInspectorClass +WEBKIT_TYPE_WEB_INSPECTOR +WEBKIT_WEB_INSPECTOR +WEBKIT_IS_WEB_INSPECTOR +WEBKIT_WEB_INSPECTOR_CLASS +WEBKIT_IS_WEB_INSPECTOR_CLASS +WEBKIT_WEB_INSPECTOR_GET_CLASS + +<SUBSECTION Private> +webkit_web_inspector_get_type +WebKitWebInspectorPrivate +</SECTION> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types index cdf9edd73..92b6fb400 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types @@ -17,3 +17,4 @@ webkit_web_resource_get_type webkit_cookie_manager_get_type webkit_plugin_get_type webkit_mime_info_get_type +webkit_web_inspector_get_type diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index 870d68a5b..8fa0cd8d8 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -4,6 +4,7 @@ TEST_PROGS += \ Programs/WebKit2APITests/TestBackForwardList \ Programs/WebKit2APITests/TestCookieManager \ Programs/WebKit2APITests/TestDownloads \ + Programs/WebKit2APITests/TestInspector \ Programs/WebKit2APITests/TestLoaderClient \ Programs/WebKit2APITests/TestPrinting \ Programs/WebKit2APITests/TestResources \ @@ -151,4 +152,12 @@ Programs_WebKit2APITests_TestCookieManager_CPPFLAGS = $(webkit2_tests_cppflags) Programs_WebKit2APITests_TestCookieManager_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestCookieManager_LDFLAGS = $(webkit2_tests_ldflags) +Programs_WebKit2APITests_TestInspector_SOURCES = \ + Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp +Programs_WebKit2APITests_TestInspector_CPPFLAGS = \ + -DWEBKIT_INSPECTOR_PATH=\"${shell pwd}/${top_builddir}/resources/inspector\" \ + $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestInspector_LDADD = $(webkit2_tests_ldadd) +Programs_WebKit2APITests_TestInspector_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 index 6d2ecf528..1ddfd82bf 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestCookieManager.cpp @@ -74,7 +74,7 @@ public: WebKitCookieAcceptPolicy getAcceptPolicy() { m_acceptPolicy = WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY; - webkit_cookie_manager_get_accept_policy(m_cookieManager, getAcceptPolicyReadyCallback, this); + webkit_cookie_manager_get_accept_policy(m_cookieManager, 0, getAcceptPolicyReadyCallback, this); g_main_loop_run(m_mainLoop); return m_acceptPolicy; @@ -100,7 +100,7 @@ public: { g_strfreev(m_domains); m_domains = 0; - webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, getDomainsReadyCallback, this); + webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, 0, getDomainsReadyCallback, this); g_main_loop_run(m_mainLoop); return m_domains; diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp new file mode 100644 index 000000000..9b023f3ed --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp @@ -0,0 +1,357 @@ +/* + * 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 "WebViewTest.h" +#include <wtf/gobject/GRefPtr.h> + +static const unsigned gMinimumAttachedInspectorHeight = 250; + +class InspectorTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(InspectorTest); + + enum InspectorEvents { + OpenWindow, + BringToFront, + Closed, + Attach, + Detach + }; + + static gboolean openWindowCallback(WebKitWebInspector*, InspectorTest* test) + { + return test->openWindow(); + } + + static gboolean bringToFrontCallback(WebKitWebInspector*, InspectorTest* test) + { + return test->bringToFront(); + } + + static void closedCallback(WebKitWebInspector*, InspectorTest* test) + { + return test->closed(); + } + + static gboolean attachCallback(WebKitWebInspector*, InspectorTest* test) + { + return test->attach(); + } + + static gboolean detachCallback(WebKitWebInspector*, InspectorTest* test) + { + return test->detach(); + } + + static const unsigned gMinimumAttachedInspectorHeight = 250; + + InspectorTest() + : WebViewTest() + , m_inspector(webkit_web_view_get_inspector(m_webView)) + , m_quitOnBringToFront(false) + { + webkit_settings_set_enable_developer_extras(webkit_web_view_get_settings(m_webView), TRUE); + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_inspector)); + g_signal_connect(m_inspector, "open-window", G_CALLBACK(openWindowCallback), this); + g_signal_connect(m_inspector, "bring-to-front", G_CALLBACK(bringToFrontCallback), this); + g_signal_connect(m_inspector, "closed", G_CALLBACK(closedCallback), this); + g_signal_connect(m_inspector, "attach", G_CALLBACK(attachCallback), this); + g_signal_connect(m_inspector, "detach", G_CALLBACK(detachCallback), this); + } + + ~InspectorTest() + { + g_signal_handlers_disconnect_matched(m_inspector, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + } + + virtual bool openWindow() + { + m_events.append(OpenWindow); + g_main_loop_quit(m_mainLoop); + return TRUE; + } + + virtual bool bringToFront() + { + m_events.append(BringToFront); + if (m_quitOnBringToFront) + g_main_loop_quit(m_mainLoop); + return FALSE; + } + + virtual void closed() + { + m_events.append(Closed); + g_main_loop_quit(m_mainLoop); + } + + virtual bool attach() + { + m_events.append(Attach); + return TRUE; + } + + virtual bool detach() + { + m_events.append(Detach); + return TRUE; + } + + void showAndWaitUntilFinished(bool quitOnBringToFront) + { + m_quitOnBringToFront = quitOnBringToFront; + webkit_web_inspector_show(m_inspector); + g_main_loop_run(m_mainLoop); + m_quitOnBringToFront = false; + } + + void resizeViewAndAttach() + { + // Resize the view to make room for the inspector. + resizeView(300, (gMinimumAttachedInspectorHeight + 1) * 4 / 3); + webkit_web_inspector_attach(m_inspector); + } + + static gboolean detachIdle(InspectorTest* test) + { + webkit_web_inspector_detach(test->m_inspector); + return FALSE; + } + + void detachAndWaitUntilWindowOpened() + { + g_idle_add(reinterpret_cast<GSourceFunc>(detachIdle), this); + g_main_loop_run(m_mainLoop); + } + + void closeAndWaitUntilClosed() + { + webkit_web_inspector_close(m_inspector); + g_main_loop_run(m_mainLoop); + } + + WebKitWebInspector* m_inspector; + bool m_quitOnBringToFront; + Vector<InspectorEvents> m_events; +}; + +static void testInspectorDefault(InspectorTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); + test->resizeView(200, 200); + test->loadHtml("<html><body><p>WebKitGTK+ Inspector test</p></body></html>", 0); + test->waitUntilLoadFinished(); + + test->showAndWaitUntilFinished(false); + // We don't add the view to a container, so consume the weak ref with GRefPtr. + GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(test->m_inspector); + g_assert(inspectorView.get()); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inspectorView.get())); + g_assert(!webkit_web_inspector_is_attached(test->m_inspector)); + g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), ==, 0); + Vector<InspectorTest::InspectorEvents>& events = test->m_events; + g_assert_cmpint(events.size(), ==, 2); + g_assert_cmpint(events[0], ==, InspectorTest::BringToFront); + g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow); + test->m_events.clear(); + + test->showAndWaitUntilFinished(true); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 1); + g_assert_cmpint(events[0], ==, InspectorTest::BringToFront); + test->m_events.clear(); + + test->resizeViewAndAttach(); + g_assert(webkit_web_inspector_is_attached(test->m_inspector)); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 1); + g_assert_cmpint(events[0], ==, InspectorTest::Attach); + test->m_events.clear(); + + test->detachAndWaitUntilWindowOpened(); + g_assert(!webkit_web_inspector_is_attached(test->m_inspector)); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 2); + g_assert_cmpint(events[0], ==, InspectorTest::Detach); + g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow); + test->m_events.clear(); + + test->closeAndWaitUntilClosed(); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 1); + g_assert_cmpint(events[0], ==, InspectorTest::Closed); + test->m_events.clear(); +} + +class CustomInspectorTest: public InspectorTest { +public: + MAKE_GLIB_TEST_FIXTURE(CustomInspectorTest); + + CustomInspectorTest() + : InspectorTest() + , m_inspectorWindow(0) + { + } + + ~CustomInspectorTest() + { + if (m_inspectorWindow) + gtk_widget_destroy(m_inspectorWindow); + } + + bool openWindow() + { + g_assert(!m_inspectorWindow); + m_inspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); + WebKitWebViewBase* inspectorView = webkit_web_inspector_get_web_view(m_inspector); + g_assert(inspectorView); + gtk_container_add(GTK_CONTAINER(m_inspectorWindow), GTK_WIDGET(inspectorView)); + gtk_widget_show_all(m_inspectorWindow); + + return InspectorTest::openWindow(); + } + + void closed() + { + if (m_inspectorWindow) { + gtk_widget_destroy(m_inspectorWindow); + m_inspectorWindow = 0; + } + + return InspectorTest::closed(); + } + + bool attach() + { + GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(m_inspector); + if (m_inspectorWindow) { + gtk_container_remove(GTK_CONTAINER(m_inspectorWindow), GTK_WIDGET(inspectorView.get())); + gtk_widget_destroy(m_inspectorWindow); + m_inspectorWindow = 0; + } + + GtkWidget* pane; + if (gtk_bin_get_child(GTK_BIN(m_parentWindow)) == GTK_WIDGET(m_webView)) { + GRefPtr<WebKitWebView> inspectedView = m_webView; + gtk_container_remove(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView)); + pane = gtk_paned_new(GTK_ORIENTATION_VERTICAL); + gtk_paned_add1(GTK_PANED(pane), GTK_WIDGET(m_webView)); + gtk_container_add(GTK_CONTAINER(m_parentWindow), pane); + gtk_widget_show_all(pane); + } else + pane = gtk_bin_get_child(GTK_BIN(m_parentWindow)); + gtk_paned_add2(GTK_PANED(pane), GTK_WIDGET(inspectorView.get())); + + return InspectorTest::attach(); + } + + bool detach() + { + GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(m_inspector); + GtkWidget* pane = gtk_bin_get_child(GTK_BIN(m_parentWindow)); + g_assert(GTK_IS_PANED(pane)); + gtk_container_remove(GTK_CONTAINER(pane), GTK_WIDGET(inspectorView.get())); + return InspectorTest::detach(); + } + + void destroyWindowAndWaitUntilClosed() + { + g_assert(m_inspectorWindow); + gtk_widget_destroy(m_inspectorWindow); + m_inspectorWindow = 0; + g_main_loop_run(m_mainLoop); + } + + GtkWidget* m_inspectorWindow; +}; + +static void testInspectorManualAttachDetach(CustomInspectorTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); + test->resizeView(200, 200); + test->loadHtml("<html><body><p>WebKitGTK+ Inspector test</p></body></html>", 0); + test->waitUntilLoadFinished(); + + test->showAndWaitUntilFinished(false); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webkit_web_inspector_get_web_view(test->m_inspector))); + g_assert(!webkit_web_inspector_is_attached(test->m_inspector)); + Vector<InspectorTest::InspectorEvents>& events = test->m_events; + g_assert_cmpint(events.size(), ==, 2); + g_assert_cmpint(events[0], ==, InspectorTest::BringToFront); + g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow); + test->m_events.clear(); + + test->resizeViewAndAttach(); + g_assert(webkit_web_inspector_is_attached(test->m_inspector)); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 1); + g_assert_cmpint(events[0], ==, InspectorTest::Attach); + test->m_events.clear(); + + test->detachAndWaitUntilWindowOpened(); + g_assert(!webkit_web_inspector_is_attached(test->m_inspector)); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 2); + g_assert_cmpint(events[0], ==, InspectorTest::Detach); + g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow); + test->m_events.clear(); + + test->resizeViewAndAttach(); + g_assert(webkit_web_inspector_is_attached(test->m_inspector)); + test->m_events.clear(); + test->closeAndWaitUntilClosed(); + events = test->m_events; + g_assert_cmpint(events.size(), ==, 2); + g_assert_cmpint(events[0], ==, InspectorTest::Detach); + g_assert_cmpint(events[1], ==, InspectorTest::Closed); + test->m_events.clear(); +} + +static void testInspectorCustomContainerDestroyed(CustomInspectorTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); + test->resizeView(200, 200); + test->loadHtml("<html><body><p>WebKitGTK+ Inspector test</p></body></html>", 0); + test->waitUntilLoadFinished(); + + test->showAndWaitUntilFinished(false); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webkit_web_inspector_get_web_view(test->m_inspector))); + g_assert(!webkit_web_inspector_is_attached(test->m_inspector)); + + test->m_events.clear(); + test->destroyWindowAndWaitUntilClosed(); + Vector<InspectorTest::InspectorEvents>& events = test->m_events; + g_assert_cmpint(events.size(), ==, 1); + g_assert_cmpint(events[0], ==, InspectorTest::Closed); + test->m_events.clear(); +} + +void beforeAll() +{ + g_setenv("WEBKIT_INSPECTOR_PATH", WEBKIT_INSPECTOR_PATH, FALSE); + InspectorTest::add("WebKitWebInspector", "default", testInspectorDefault); + CustomInspectorTest::add("WebKitWebInspector", "manual-attach-detach", testInspectorManualAttachDetach); + CustomInspectorTest::add("WebKitWebInspector", "custom-container-destroyed", testInspectorCustomContainerDestroyed); +} + +void afterAll() +{ +} diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp index e08cfb9c9..39841756d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestResources.cpp @@ -150,7 +150,7 @@ public: void checkResourceData(WebKitWebResource* resource) { m_resourceDataSize = 0; - webkit_web_resource_get_data(resource, resourceGetDataCallback, this); + webkit_web_resource_get_data(resource, 0, resourceGetDataCallback, this); g_main_loop_run(m_mainLoop); const char* uri = webkit_web_resource_get_uri(resource); diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp index ad03444ae..4616d105f 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp @@ -219,6 +219,11 @@ static void testWebKitSettings(Test*, gconstpointer) webkit_settings_set_media_playback_allows_inline(settings, FALSE); g_assert(!webkit_settings_get_media_playback_allows_inline(settings)); + // By default, debug indicators are disabled. + g_assert(!webkit_settings_get_draw_compositing_indicators(settings)); + webkit_settings_set_draw_compositing_indicators(settings, TRUE); + g_assert(webkit_settings_get_draw_compositing_indicators(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 d65e8a641..e4c60bebc 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp @@ -675,7 +675,7 @@ public: void requestFullScreenAndWaitUntilEnteredFullScreen() { m_event = None; - webkit_web_view_run_javascript(m_webView, "document.documentElement.webkitRequestFullScreen();", 0, 0); + webkit_web_view_run_javascript(m_webView, "document.documentElement.webkitRequestFullScreen();", 0, 0, 0); g_main_loop_run(m_mainLoop); } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp index 644584a3e..97ebe5b27 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebViewEditor.cpp @@ -47,7 +47,7 @@ public: bool canExecuteEditingCommand(const char* command) { m_canExecuteEditingCommand = false; - webkit_web_view_can_execute_editing_command(m_webView, command, reinterpret_cast<GAsyncReadyCallback>(canExecuteEditingCommandReadyCallback), this); + webkit_web_view_can_execute_editing_command(m_webView, command, 0, reinterpret_cast<GAsyncReadyCallback>(canExecuteEditingCommandReadyCallback), this); g_main_loop_run(m_mainLoop); return m_canExecuteEditingCommand; } diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp index 7a9e49bc6..e355f786d 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp @@ -162,10 +162,10 @@ static gboolean parentWindowMapped(GtkWidget* widget, GdkEvent*, WebViewTest* te return FALSE; } -void WebViewTest::showInWindowAndWaitUntilMapped() +void WebViewTest::showInWindowAndWaitUntilMapped(GtkWindowType windowType) { g_assert(!m_parentWindow); - m_parentWindow = gtk_window_new(GTK_WINDOW_POPUP); + m_parentWindow = gtk_window_new(windowType); gtk_container_add(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView)); gtk_widget_show(GTK_WIDGET(m_webView)); @@ -174,6 +174,17 @@ void WebViewTest::showInWindowAndWaitUntilMapped() g_main_loop_run(m_mainLoop); } +void WebViewTest::resizeView(int width, int height) +{ + GtkAllocation allocation; + gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation); + if (width != -1) + allocation.width = width; + if (height != -1) + allocation.height = height; + gtk_widget_size_allocate(GTK_WIDGET(m_webView), &allocation); +} + void WebViewTest::mouseMoveTo(int x, int y, unsigned int mouseModifiers) { g_assert(m_parentWindow); @@ -268,7 +279,7 @@ WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const cha 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); + webkit_web_view_run_javascript(m_webView, javascript, 0, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this); g_main_loop_run(m_mainLoop); return m_javascriptResult; diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h index 92e123630..ff6a8c737 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h +++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h @@ -44,7 +44,8 @@ public: void waitUntilLoadFinished(); void waitUntilTitleChangedTo(const char* expectedTitle); void waitUntilTitleChanged(); - void showInWindowAndWaitUntilMapped(); + void showInWindowAndWaitUntilMapped(GtkWindowType = GTK_WINDOW_POPUP); + void resizeView(int width, int height); void mouseMoveTo(int x, int y, unsigned int mouseModifiers = 0); void clickMouseButton(int x, int y, unsigned int button = 1, unsigned int mouseModifiers = 0); diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index 7699c4966..23dbd9903 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -43,6 +43,7 @@ #include <webkit2/WebKitURIRequest.h> #include <webkit2/WebKitURIResponse.h> #include <webkit2/WebKitWebContext.h> +#include <webkit2/WebKitWebInspector.h> #include <webkit2/WebKitWebResource.h> #include <webkit2/WebKitWebView.h> #include <webkit2/WebKitWebViewBase.h> diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index 8cd3027a3..f03b9a899 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -1598,6 +1598,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde return resultRect; } +#if ENABLE(DRAG_SUPPORT) - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation { NSPoint windowImageLoc = [[self window] convertScreenToBase:aPoint]; @@ -1699,7 +1700,7 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb 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++) { @@ -1724,7 +1725,7 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb SandboxExtension::HandleArray sandboxExtensionForUpload; createSandboxExtensionsForFileUpload([draggingInfo draggingPasteboard], sandboxExtensionForUpload); - + _data->_page->performDrag(&dragData, [[draggingInfo draggingPasteboard] name], sandboxExtensionHandle, sandboxExtensionForUpload); return YES; @@ -1739,6 +1740,7 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb return self; return nil; } +#endif // ENABLE(DRAG_SUPPORT) - (BOOL)_windowResizeMouseLocationIsInVisibleScrollerThumb:(NSPoint)loc { @@ -2511,8 +2513,20 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (void)_updateAcceleratedCompositingMode:(const WebKit::LayerTreeContext&)layerTreeContext { - [self _exitAcceleratedCompositingMode]; - [self _enterAcceleratedCompositingMode:layerTreeContext]; + if (_data->_layerHostingView) { + // Wrap the call to setSublayers: in a CATransaction with actions disabled to + // keep CA from cross-fading between the two sublayer arrays. + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID); + [[_data->_layerHostingView.get() layer] setSublayers:[NSArray arrayWithObject:renderLayer]]; + + [CATransaction commit]; + } else { + [self _exitAcceleratedCompositingMode]; + [self _enterAcceleratedCompositingMode:layerTreeContext]; + } } - (void)_setAccessibilityWebProcessToken:(NSData *)data diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp index e02ccc9b2..178e2dade 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp @@ -140,18 +140,41 @@ QTransform QQuickWebPage::transformFromItem() const QTransform QQuickWebPage::transformToItem() const { - QPointF pos = d->viewportItem->pageItemPos(); - return QTransform(d->contentsScale, 0, 0, 0, d->contentsScale, 0, pos.x(), pos.y(), 1); + qreal xPos = x(); + qreal yPos = y(); + + if (d->viewportItem->experimental()->flickableViewportEnabled()) { + // 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. + xPos += d->viewportItem->contentItem()->x(); + yPos += d->viewportItem->contentItem()->y(); + } + + return QTransform(d->contentsScale, 0, 0, 0, d->contentsScale, 0, xPos, yPos, 1); } 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())); + drawingArea->layerTreeHostProxy()->setContentsSize(contentsSize); + + q->setSize(scaledSize); + + if (viewportItem->experimental()->flickableViewportEnabled()) { + // Make sure that the content is sized to the page if the user did not + // add other flickable items. If that is not the case, the user needs to + // disable the default content item size property on the WebView and + // bind the contentWidth and contentHeight accordingly, in accordance + // accordance with normal Flickable behaviour. + if (viewportItem->experimental()->useDefaultContentItemSize()) { + viewportItem->setContentWidth(scaledSize.width()); + viewportItem->setContentHeight(scaledSize.height()); + } + } } QQuickWebPagePrivate::~QQuickWebPagePrivate() diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp index 935842146..9d77171cc 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp @@ -324,31 +324,33 @@ bool QQuickWebViewPrivate::transparentBackground() const return webPageProxy->drawsTransparentBackground(); } -QPointF QQuickWebViewPrivate::pageItemPos() -{ - ASSERT(pageView); - return pageView->pos(); -} - /*! \qmlsignal WebView::loadingChanged(WebLoadRequest request) */ -void QQuickWebViewPrivate::provisionalLoadDidStart(const QUrl& url) +void QQuickWebViewPrivate::provisionalLoadDidStart(const WTF::String& url) { Q_Q(QQuickWebView); - QWebLoadRequest loadRequest(url, QQuickWebView::LoadStartedStatus); + q->emitUrlChangeIfNeeded(); + + QWebLoadRequest loadRequest(QString(url), QQuickWebView::LoadStartedStatus); emit q->loadingChanged(&loadRequest); } +void QQuickWebViewPrivate::didReceiveServerRedirectForProvisionalLoad(const WTF::String&) +{ + Q_Q(QQuickWebView); + + q->emitUrlChangeIfNeeded(); +} + void QQuickWebViewPrivate::loadDidCommit() { Q_Q(QQuickWebView); ASSERT(q->loading()); emit q->navigationHistoryChanged(); - emit q->urlChanged(); emit q->titleChanged(); } @@ -356,8 +358,8 @@ void QQuickWebViewPrivate::didSameDocumentNavigation() { Q_Q(QQuickWebView); + q->emitUrlChangeIfNeeded(); emit q->navigationHistoryChanged(); - emit q->urlChanged(); } void QQuickWebViewPrivate::titleDidChange() @@ -419,6 +421,7 @@ void QQuickWebViewPrivate::setNeedsDisplay() void QQuickWebViewPrivate::_q_onIconChangedForPageURL(const QUrl& pageURL, const QUrl& iconURL) { Q_Q(QQuickWebView); + if (q->url() != pageURL) return; @@ -644,6 +647,9 @@ void QQuickWebViewPrivate::setIcon(const QUrl& iconURL) if (m_iconURL == iconURL) return; + if (!webPageProxy->mainFrame()) + return; + String oldPageURL = QUrl::fromPercentEncoding(m_iconURL.encodedFragment()); String newPageURL = webPageProxy->mainFrame()->url(); @@ -798,34 +804,6 @@ void QQuickWebViewFlickablePrivate::initialize(WKContextRef contextRef, WKPageGr webPageProxy->setUseFixedLayout(true); } -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 = q->contentItem()->x() + pageView->x(); - qreal yPos = q->contentItem()->y() + pageView->y(); - return QPointF(xPos, yPos); -} - -void QQuickWebViewFlickablePrivate::updateContentsSize(const QSizeF& size) -{ - 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 - // 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 (!m_useDefaultContentItemSize) - return; - - q->setContentWidth(size.width()); - q->setContentHeight(size.height()); -} - void QQuickWebViewFlickablePrivate::onComponentComplete() { Q_Q(QQuickWebView); @@ -835,7 +813,7 @@ void QQuickWebViewFlickablePrivate::onComponentComplete() 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(contentViewportChanged(QPointF)), q, SLOT(_q_contentViewportChanged(QPointF))); + QObject::connect(interactionEngine.data(), SIGNAL(informVisibleContentChange(QPointF)), q, SLOT(_q_onInformVisibleContentChange(QPointF))); _q_resume(); @@ -868,7 +846,7 @@ void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::V // 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); + interactionEngine->setItemRectVisible(interactionEngine->nearestValidBounds()); } void QQuickWebViewFlickablePrivate::updateViewportSize() @@ -887,10 +865,10 @@ void QQuickWebViewFlickablePrivate::updateViewportSize() // it can resize the content accordingly. webPageProxy->setViewportSize(viewportSize); - _q_contentViewportChanged(QPointF()); + _q_onInformVisibleContentChange(QPointF()); } -void QQuickWebViewFlickablePrivate::_q_contentViewportChanged(const QPointF& trajectoryVector) +void QQuickWebViewFlickablePrivate::_q_onInformVisibleContentChange(const QPointF& trajectoryVector) { Q_Q(QQuickWebView); @@ -925,7 +903,7 @@ void QQuickWebViewFlickablePrivate::_q_resume() pageIsSuspended = false; webPageProxy->resumeActiveDOMObjectsAndAnimations(); - _q_contentViewportChanged(QPointF()); + _q_onInformVisibleContentChange(QPointF()); } void QQuickWebViewFlickablePrivate::pageDidRequestScroll(const QPoint& pos) @@ -942,15 +920,26 @@ void QQuickWebViewFlickablePrivate::didChangeContentsSize(const QSize& newSize) float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(attributes, viewportSize, newSize); + bool scaleCommitNotified = false; + if (!qFuzzyCompare(minimumScale, attributes.minimumScale)) { interactionEngine->setCSSScaleBounds(minimumScale, attributes.maximumScale); emit q->experimental()->test()->viewportChanged(); - if (!interactionEngine->hadUserInteraction() && !pageIsSuspended) + if (!interactionEngine->hadUserInteraction() && !pageIsSuspended) { + // Emits contentsScaleCommitted(); + scaleCommitNotified = true; interactionEngine->setCSSScale(minimumScale); + } } + + // Emit for testing purposes, so that it can be verified that + // we didn't do scale adjustment. + if (!scaleCommitNotified) + emit q->experimental()->test()->contentsScaleCommitted(); } + /*! \qmlsignal WebView::onNavigationRequested(WebNavigationRequest request) @@ -1452,6 +1441,19 @@ void QQuickWebView::stop() void QQuickWebView::reload() { Q_D(QQuickWebView); + + WebFrameProxy* mainFrame = d->webPageProxy->mainFrame(); + if (mainFrame && !mainFrame->unreachableURL().isEmpty() && mainFrame->url() != blankURL()) { + // We are aware of the unreachable url on the UI process side, but since we haven't + // loaded alternative/subsitute data for it (an error page eg.) WebCore doesn't know + // about the unreachable url yet. If we just do a reload at this point WebCore will try to + // reload the currently committed url instead of the unrachable url. To work around this + // we override the reload here by doing a manual load. + d->webPageProxy->loadURL(mainFrame->unreachableURL()); + // FIXME: We should make WebCore aware of the unreachable url regardless of substitute-loads + return; + } + const bool reloadFromOrigin = true; d->webPageProxy->reload(reloadFromOrigin); } @@ -1459,10 +1461,11 @@ void QQuickWebView::reload() QUrl QQuickWebView::url() const { Q_D(const QQuickWebView); - RefPtr<WebFrameProxy> mainFrame = d->webPageProxy->mainFrame(); - if (!mainFrame) - return QUrl(); - return QUrl(QString(mainFrame->url())); + + // FIXME: Enable once we are sure this should not trigger + // Q_ASSERT(d->m_currentUrl == d->webPageProxy->activeURL()); + + return QUrl(d->m_currentUrl); } void QQuickWebView::setUrl(const QUrl& url) @@ -1473,6 +1476,19 @@ void QQuickWebView::setUrl(const QUrl& url) return; d->webPageProxy->loadURL(url.toString()); + emitUrlChangeIfNeeded(); +} + +// Make sure we don't emit urlChanged unless it actually changed +void QQuickWebView::emitUrlChangeIfNeeded() +{ + Q_D(QQuickWebView); + + WTF::String activeUrl = d->webPageProxy->activeURL(); + if (activeUrl != d->m_currentUrl) { + d->m_currentUrl = activeUrl; + emit urlChanged(); + } } QUrl QQuickWebView::icon() const @@ -1708,6 +1724,7 @@ void QQuickWebView::mouseDoubleClickEvent(QMouseEvent* event) { Q_D(QQuickWebView); + forceActiveFocus(); // If a MouseButtonDblClick was received then we got a MouseButtonPress before // handleMousePressEvent will take care of double clicks. d->pageView->eventHandler()->handleMousePressEvent(event); @@ -1819,24 +1836,19 @@ void QQuickWebView::handleFlickableMouseRelease(const QPointF& position, qint64 External objects such as stylesheets or images referenced in the HTML document are located relative to \a baseUrl. + If an \a unreachableUrl is passed it is used as the url for the loaded + content. This is typically used to display error pages for a failed + load. + \sa WebView::url */ -void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl) -{ - Q_D(QQuickWebView); - d->webPageProxy->loadHTMLString(html, baseUrl.toString()); -} - -QPointF QQuickWebView::pageItemPos() -{ - Q_D(QQuickWebView); - return d->pageItemPos(); -} - -void QQuickWebView::updateContentsSize(const QSizeF& size) +void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl, const QUrl& unreachableUrl) { Q_D(QQuickWebView); - d->updateContentsSize(size); + if (unreachableUrl.isValid()) + d->webPageProxy->loadAlternateHTMLString(html, baseUrl.toString(), unreachableUrl.toString()); + else + d->webPageProxy->loadHTMLString(html, baseUrl.toString()); } qreal QQuickWebView::zoomFactor() const diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h index 773f735a9..f33c6e654 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h @@ -141,10 +141,6 @@ public: static void platformInitialize(); // Only needed by WTR. - // Internal API used by WebPage. - void updateContentsSize(const QSizeF&); - QPointF pageItemPos(); - // Private C++-only API. qreal zoomFactor() const; void setZoomFactor(qreal); @@ -154,7 +150,7 @@ public: void setAllowAnyHTTPSCertificateForLocalHost(bool allow); public Q_SLOTS: - void loadHtml(const QString& html, const QUrl& baseUrl = QUrl()); + void loadHtml(const QString& html, const QUrl& baseUrl = QUrl(), const QUrl& unreachableUrl = QUrl()); void goBack(); void goForward(); @@ -207,9 +203,11 @@ private: QQuickWebView(WKContextRef, WKPageGroupRef, QQuickItem* parent = 0); WKPageRef pageRef() const; + void emitUrlChangeIfNeeded(); + Q_PRIVATE_SLOT(d_func(), void _q_suspend()); Q_PRIVATE_SLOT(d_func(), void _q_resume()); - Q_PRIVATE_SLOT(d_func(), void _q_contentViewportChanged(const QPointF&)); + Q_PRIVATE_SLOT(d_func(), void _q_onInformVisibleContentChange(const QPointF&)); Q_PRIVATE_SLOT(d_func(), void _q_onVisibleChanged()); Q_PRIVATE_SLOT(d_func(), void _q_onUrlChanged()); diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h index ebd06e3ea..572a7f226 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h @@ -74,10 +74,8 @@ public: virtual void enableMouseEvents() { } virtual void disableMouseEvents() { } - virtual QPointF pageItemPos(); - virtual void updateContentsSize(const QSizeF&) { } - - virtual void provisionalLoadDidStart(const QUrl& url); + virtual void provisionalLoadDidStart(const WTF::String& url); + virtual void didReceiveServerRedirectForProvisionalLoad(const WTF::String& url); virtual void loadDidCommit(); virtual void didSameDocumentNavigation(); virtual void titleDidChange(); @@ -97,7 +95,7 @@ public: virtual void _q_suspend() { } virtual void _q_resume() { } - virtual void _q_contentViewportChanged(const QPointF& trajectory) { }; + virtual void _q_onInformVisibleContentChange(const QPointF& trajectory) { }; virtual qreal zoomFactor() const { return 1; } virtual void setZoomFactor(qreal) { } @@ -201,6 +199,7 @@ protected: bool m_allowAnyHTTPSCertificateForLocalHost; QUrl m_iconURL; int m_loadProgress; + WTF::String m_currentUrl; }; class QQuickWebViewLegacyPrivate : public QQuickWebViewPrivate { @@ -226,16 +225,13 @@ public: virtual void onComponentComplete(); - virtual QPointF pageItemPos(); - virtual void updateContentsSize(const QSizeF&); - 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_contentViewportChanged(const QPointF& trajectory); + virtual void _q_onInformVisibleContentChange(const QPointF& trajectory); virtual void pageDidRequestScroll(const QPoint& pos); virtual void didChangeContentsSize(const QSize& newSize); diff --git a/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp b/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp index 8311528b5..529df01eb 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp @@ -38,7 +38,20 @@ QWebKitTest::~QWebKitTest() { } -bool QWebKitTest::touchDoubleTap(QObject* item, qreal x, qreal y, int delay) +static QTouchEvent::TouchPoint touchPoint(qreal x, qreal y) +{ + QPointF localPos(x, y); + + QTouchEvent::TouchPoint point; + point.setLastPos(localPos); + QRectF touchRect(0, 0, 40, 40); + touchRect.moveCenter(localPos); + point.setRect(touchRect); + + return point; +} + +bool QWebKitTest::touchTap(QObject* item, qreal x, qreal y, int delay) { if (!qobject_cast<QQuickWebView*>(item)) { // FIXME: We only support the actual web view for now. @@ -48,16 +61,23 @@ bool QWebKitTest::touchDoubleTap(QObject* item, qreal x, qreal y, int delay) // FIXME: implement delay using QTest::qWait() or similar. Q_UNUSED(delay); + m_webViewPrivate->pageView->eventHandler()->handleSingleTapEvent(touchPoint(x, y)); - QPointF localPos(x, y); + return true; +} - QTouchEvent::TouchPoint point; - point.setLastPos(localPos); - QRectF touchRect(0, 0, 40, 40); - touchRect.moveCenter(localPos); - point.setRect(touchRect); +bool QWebKitTest::touchDoubleTap(QObject* item, qreal x, qreal y, int delay) +{ + if (!qobject_cast<QQuickWebView*>(item)) { + // FIXME: We only support the actual web view for now. + qWarning("Touch event \"DoubleTap\" not accepted by receiving item"); + return false; + } + + // FIXME: implement delay using QTest::qWait() or similar. + Q_UNUSED(delay); - m_webViewPrivate->pageView->eventHandler()->handleDoubleTapEvent(point); + m_webViewPrivate->pageView->eventHandler()->handleDoubleTapEvent(touchPoint(x, y)); return true; } @@ -108,5 +128,5 @@ QVariant QWebKitTest::isScalable() const QVariant QWebKitTest::layoutSize() const { - return QSizeF(m_webViewPrivate->attributes.layoutSize.width(), m_webViewPrivate->attributes.layoutSize.height()); + return QSizeF(m_webViewPrivate->attributes.layoutSize); } diff --git a/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h b/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h index f7c7180c1..613486409 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h @@ -53,6 +53,7 @@ signals: void viewportChanged(); public slots: + bool touchTap(QObject* item, qreal x, qreal y, int delay = -1); bool touchDoubleTap(QObject* item, qreal x, qreal y, int delay = -1); public: diff --git a/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp b/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp index 0d0bb6902..3d2a95a6c 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/inspectorserver/tst_inspectorserver.cpp @@ -30,8 +30,8 @@ #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); +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 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 39e6b54cf..6c0cb4b62 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp +++ b/Source/WebKit2/UIProcess/API/qt/tests/publicapi/tst_publicapi.cpp @@ -70,6 +70,7 @@ static QStringList expectedAPI = QStringList() << "QQuickWebView.iconChanged() --> void" << "QQuickWebView.linkHovered(QUrl,QString) --> void" << "QQuickWebView.navigationRequested(QWebNavigationRequest*) --> void" + << "QQuickWebView.loadHtml(QString,QUrl,QUrl) --> void" << "QQuickWebView.loadHtml(QString,QUrl) --> void" << "QQuickWebView.loadHtml(QString) --> void" << "QQuickWebView.goBack() --> void" diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_itemSelector.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_itemSelector.qml index 18763bfef..d3d7786a3 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_itemSelector.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior/tst_itemSelector.qml @@ -107,5 +107,13 @@ TestWebView { tryCompare(webView, "selectorLoaded", true) compare(webView.title, "No new selection was made") } + + function test_selectWithSize() { + webView.url = Qt.resolvedUrl("../common/selectwithsize.html") + verify(webView.waitForLoadSucceeded()) + titleSpy.clear() + + test_selectFirstThenAcceptDirectly() + } } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml index 904f60feb..b2a860e73 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml @@ -46,15 +46,6 @@ Item { property variant test: webView.experimental.test - // Delayed windowShown to workaround problems with Qt5 in debug mode. - when: false - Timer { - running: parent.windowShown - repeat: false - interval: 1 - onTriggered: parent.when = true - } - function init() { resultSpy.clear() scaleSpy.clear() @@ -92,15 +83,15 @@ Item { webView.url = webView.content verify(webView.waitForLoadSucceeded()) - compare("480x720", documentSize()) + compare(documentSize(), "480x720") - compare(1.0, test.contentsScale) + compare(test.contentsScale, 1.0) var rect = elementRect("target"); var newScale = webView.width / (rect.width + 2 * 10) // inflated by 10px doubleTapAtPoint(rect.left + rect.height / 2, rect.top + rect.width / 2) - compare(newScale, test.contentsScale) + compare(test.contentsScale, newScale) } } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_evaluateJavaScript.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_evaluateJavaScript.qml index a3083144d..720b4cd04 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_evaluateJavaScript.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_evaluateJavaScript.qml @@ -10,8 +10,6 @@ Item { property variant lastMessage property variant lastResult - signal resultReceived - experimental.preferences.navigatorQtObjectEnabled: true experimental.onMessageReceived: { lastMessage = message @@ -27,7 +25,7 @@ Item { SignalSpy { id: resultSpy target: webView - signalName: "resultReceived" + signalName: "lastResultChanged" } TestCase { @@ -59,7 +57,7 @@ Item { } function test_propertyObjectWithChild() { - messageSpy.clear() + resultSpy.clear() webView.url = "about:blank" verify(webView.waitForLoadSucceeded()) @@ -75,7 +73,6 @@ Item { function(result) { webView.lastResult = result - webView.resultReceived() }); resultSpy.wait() @@ -83,5 +80,111 @@ Item { compare(JSON.stringify(webView.lastResult), '{"child":{"level":2},"level":"1"}') } + + function test_booleanValue() { + resultSpy.clear() + webView.url = "about:blank" + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() { return true })()", + + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + verify(typeof webView.lastResult === "boolean") + compare(webView.lastResult, true) + } + + function test_stringValue() { + resultSpy.clear() + webView.url = "about:blank" + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() { return 'dongs' })()", + + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + verify(typeof webView.lastResult === "string") + compare(webView.lastResult, "dongs") + } + + function test_integerValue() { + resultSpy.clear() + webView.url = "about:blank" + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() { return 1337 })()", + + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + verify(typeof webView.lastResult === "number") + compare(webView.lastResult, 1337) + } + + function test_floatValue() { + resultSpy.clear() + webView.url = "about:blank" + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() { return 13.37 })()", + + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + verify(typeof webView.lastResult === "number") + compare(webView.lastResult, 13.37) + } + + function test_queryTitle() { + resultSpy.clear() + var testUrl = Qt.resolvedUrl("../common/evaluatejavascript.html") + webView.url = testUrl + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() {" + + " return document.title" + + "})()", + + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + compare(webView.lastResult, "Evaluate JavaScript") + } + + function test_queryById() { + resultSpy.clear() + var testUrl = Qt.resolvedUrl("../common/evaluatejavascript.html") + webView.url = testUrl + verify(webView.waitForLoadSucceeded()) + + webView.experimental.evaluateJavaScript( + "(function() {" + + " return document.getElementById('text').innerHTML" + + "})()", + + function(result) { + webView.lastResult = result + }) + + resultSpy.wait() + compare(webView.lastResult, "Hello from the WebProcess :-)") + } } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_favIconLoad.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_favIconLoad.qml index 20d538fbf..8210040e8 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_favIconLoad.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_favIconLoad.qml @@ -35,7 +35,8 @@ TestWebView { compare(spy.count, 0) var url = Qt.resolvedUrl("../common/favicon.html") webView.url = url - spy.wait() + verify(webView.waitForLoadSucceeded()) + expectFail("", "https://bugs.webkit.org/show_bug.cgi?id=87133") compare(spy.count, 1) compare(favicon.width, 48) compare(favicon.height, 48) @@ -45,10 +46,12 @@ TestWebView { compare(spy.count, 0) var url = Qt.resolvedUrl("../common/favicon2.html?favicon=load should work with#whitespace!") webView.url = url - spy.wait() + verify(webView.waitForLoadSucceeded()) + expectFail("", "https://bugs.webkit.org/show_bug.cgi?id=87133") compare(spy.count, 1) compare(favicon.width, 16) compare(favicon.height, 16) + } } } diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml new file mode 100644 index 000000000..febd948b8 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_fitToView.qml @@ -0,0 +1,99 @@ +import QtQuick 2.0 +import QtTest 1.0 +import QtWebKit 3.0 +import QtWebKit.experimental 1.0 +import Test 1.0 +import "../common" + +Item { + TestWebView { + id: webView + width: 480 + height: 720 + + property variant result + + experimental.test.onContentsScaleCommitted: scaleChanged() + + property variant content: "data:text/html," + + "<head>" + + " <meta name='viewport' content='width=device-width'>" + + "</head>" + + "<body style='margin: 0px'>" + + " <div id='target' style='display:none; width:960px; height:1440px;'></div>" + + "</body>" + + signal resultReceived + signal scaleChanged + } + + SignalSpy { + id: resultSpy + target: webView + signalName: "resultReceived" + } + + SignalSpy { + id: scaleSpy + target: webView + signalName: "scaleChanged" + } + + TestCase { + name: "FitToView" + + property variant test: webView.experimental.test + + function init() { + resultSpy.clear() + scaleSpy.clear() + } + + function run(signalSpy, script) { + signalSpy.clear(); + var result; + webView.experimental.evaluateJavaScript( + script, function(value) { webView.resultReceived(); result = value }); + signalSpy.wait(); + return result; + } + + function documentSize() { + return run(resultSpy, "document.width + 'x' + document.height"); + } + + function setDisplay(id, value) { + // When changing to/from 'none' to 'block', this will result in a + // contentsScaleCommitted scale, even if it results in the same + // scale, making it possible to check whether user interaction + // blocks fit-to-view or not. + run(scaleSpy, "document.getElementById('" + id + "').style.display = '" + value + "';"); + } + + function test_basic() { + webView.url = webView.content + verify(webView.waitForLoadSucceeded()) + + compare(documentSize(), "480x720") + compare(test.contentsScale, 1.0) + + setDisplay("target", "block") + compare(documentSize(), "960x1440") + compare(test.contentsScale, 0.5) + + // Add user interaction. + test.touchTap(webView, 10, 10) + + // We are no longer within valid bounds after this change + // so we have to change our scale back to 1.0. + setDisplay("target", "none") + compare(documentSize(), "480x720") + compare(test.contentsScale, 1.0) + + // We had user interaction, size should change but not scale. + setDisplay("target", "block") + compare(documentSize(), "960x1440") + compare(test.contentsScale, 1.0) + } + } +} 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 7ab69bd15..f77c7f87a 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 @@ -10,6 +10,8 @@ TestWebView { property int numLoadStarted: 0 property int numLoadSucceeded: 0 + focus: true + onLoadProgressChanged: { if (watchProgress && webView.loadProgress != 100) { watchProgress = false @@ -27,6 +29,8 @@ TestWebView { TestCase { id: test name: "WebViewLoadUrl" + when: windowShown + function test_loadIgnoreEmptyUrl() { var url = Qt.resolvedUrl("../common/test1.html") @@ -58,5 +62,63 @@ TestWebView { verify(!watchProgress) compare(webView.url, url) } + + function test_urlProperty() { + var url = Qt.resolvedUrl("../common/test1.html") + + webView.url = url + compare(webView.url, url) + verify(webView.waitForLoadSucceeded()) + compare(webView.url, url) + + var bogusSite = "http://www.somesitethatdoesnotexist.abc/" + webView.url = bogusSite + compare(webView.url, bogusSite) + verify(webView.waitForLoadFailed()) + compare(webView.url, bogusSite) + + webView.url = "about:blank" // Reset from previous test + verify(webView.waitForLoadSucceeded()) + + var handleLoadFailed = function(loadRequest) { + if (loadRequest.status == WebView.LoadFailedStatus) { + compare(webView.url, bogusSite) + compare(loadRequest.url, bogusSite) + webView.loadHtml("load failed", bogusSite, bogusSite) + } + } + webView.loadingChanged.connect(handleLoadFailed) + webView.url = bogusSite + compare(webView.url, bogusSite) + verify(webView.waitForLoadSucceeded()) + compare(webView.url, bogusSite) + webView.loadingChanged.disconnect(handleLoadFailed) + + var dataUrl = "data:text/html,foo" + webView.url = dataUrl + compare(webView.url, dataUrl) + + var redirectUrl = Qt.resolvedUrl("../common/redirect.html") + webView.url = redirectUrl + compare(webView.url, redirectUrl) + verify(webView.waitForLoadSucceeded()) + compare(webView.url, redirectUrl) + verify(webView.waitForLoadSucceeded()) + compare(webView.url, url) + + var linkUrl = Qt.resolvedUrl("../common/link.html") + webView.url = linkUrl + compare(webView.url, linkUrl) + verify(webView.waitForLoadSucceeded()) + compare(webView.url, linkUrl) + webView.loadingChanged.connect(function(loadRequest) { + compare(webView.url, loadRequest.url) + compare(webView.url, url) + }) + webView.forceActiveFocus() + keyPress(Qt.Key_Return) // Link is focused + verify(webView.waitForLoadSucceeded()) + compare(webView.url, 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 16ff35c52..71fa3eb9b 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 @@ -195,6 +195,10 @@ Item { compare(webView2.title, "New Title") } + function unquote(text) { + return text[0] === "'" ? text.slice(1, -1) : text + } + function test_standardFontFamilyChanged() { var url = Qt.resolvedUrl("../common/font-preferences.html?standard#font-family") webView.url = url @@ -203,7 +207,7 @@ Item { titleSpy.clear() titleSpy.wait() - compare(webView.title, defaultStandardFontFamily) + compare(unquote(webView.title), defaultStandardFontFamily) webView.experimental.preferences.standardFontFamily = "foobar" standardFontFamilySpy.wait() diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/evaluatejavascript.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/evaluatejavascript.html new file mode 100644 index 000000000..023e9ab7f --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/evaluatejavascript.html @@ -0,0 +1,10 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8"> + <title>Evaluate JavaScript</title> + </head> + <body> + <div id="text">Hello from the WebProcess :-)</div> + </body> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/link.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/link.html new file mode 100644 index 000000000..e791b7de4 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/link.html @@ -0,0 +1,6 @@ +<!doctype html> +<html> +<body onload="document.links['foo'].focus();"> +<a name="foo" href="test1.html">Link</a> +</body> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/redirect.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/redirect.html new file mode 100644 index 000000000..914e5e35a --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/redirect.html @@ -0,0 +1,8 @@ +<!doctype html> +<html> +<head> +<meta http-equiv="refresh" content="2; url=test1.html" +</head> +<body> +</body> +</html> diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/selectwithsize.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/selectwithsize.html new file mode 100644 index 000000000..f514c46cc --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/selectwithsize.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<head> +<title>No new selection was made</title> +<script> +function updateTitle(selectElement) { + var index = selectElement.selectedIndex; + document.title = selectElement.options[index].value; +} +</script> +</head> +<body> +<select size=2 onchange="updateTitle(this)"> +<option value="__open__" >Open</option> +<option value="__closed__" >Closed</option> +<option value="__all__" >All</option> +</select> +</html> |