diff options
Diffstat (limited to 'Source/WebKit2/UIProcess')
58 files changed, 1396 insertions, 399 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.cpp b/Source/WebKit2/UIProcess/API/C/WKContext.cpp index 8890e801e..9f6dbbc37 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.cpp +++ b/Source/WebKit2/UIProcess/API/C/WKContext.cpp @@ -265,6 +265,10 @@ void WKContextGarbageCollectJavaScriptObjects(WKContextRef contextRef) toImpl(contextRef)->garbageCollectJavaScriptObjects(); } +void WKContextSetJavaScriptGarbageCollectorTimerEnabled(WKContextRef contextRef, bool enable) +{ + toImpl(contextRef)->setJavaScriptGarbageCollectorTimerEnabled(enable); +} // Deprecated functions. void _WKContextSetAdditionalPluginsDirectory(WKContextRef context, WKStringRef pluginsDirectory) { diff --git a/Source/WebKit2/UIProcess/API/C/WKContext.h b/Source/WebKit2/UIProcess/API/C/WKContext.h index f0ae59456..f4299daff 100644 --- a/Source/WebKit2/UIProcess/API/C/WKContext.h +++ b/Source/WebKit2/UIProcess/API/C/WKContext.h @@ -156,6 +156,7 @@ typedef void (*WKContextGetStatisticsFunction)(WKDictionaryRef statistics, WKErr WK_EXPORT void WKContextGetStatistics(WKContextRef context, void* functionContext, WKContextGetStatisticsFunction function); WK_EXPORT void WKContextGarbageCollectJavaScriptObjects(WKContextRef context); +WK_EXPORT void WKContextSetJavaScriptGarbageCollectorTimerEnabled(WKContextRef context, bool enable); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/C/WKPage.h b/Source/WebKit2/UIProcess/API/C/WKPage.h index aeefee796..47c076f8c 100644 --- a/Source/WebKit2/UIProcess/API/C/WKPage.h +++ b/Source/WebKit2/UIProcess/API/C/WKPage.h @@ -72,7 +72,7 @@ typedef void (*WKPageDidChangeBackForwardListCallback)(WKPageRef page, WKBackFor typedef bool (*WKPageShouldGoToBackForwardListItemCallback)(WKPageRef page, WKBackForwardListItemRef item, const void *clientInfo); typedef void (*WKPageDidNewFirstVisuallyNonEmptyLayoutCallback)(WKPageRef page, WKTypeRef userData, const void *clientInfo); typedef void (*WKPageWillGoToBackForwardListItemCallback)(WKPageRef page, WKBackForwardListItemRef item, WKTypeRef userData, const void *clientInfo); -typedef void (*WKPagePluginDidFailCallback)(WKPageRef page, WKErrorCode errorCode, WKStringRef mimeType, const void* clientInfo); +typedef void (*WKPagePluginDidFailCallback)(WKPageRef page, WKErrorCode errorCode, WKStringRef mimeType, WKStringRef pluginIdentifier, WKStringRef pluginVersion, const void* clientInfo); // Deprecated typedef void (*WKPageDidFailToInitializePluginCallback_deprecatedForUseWithV0)(WKPageRef page, WKStringRef mimeType, const void* clientInfo); diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp index 187d7fd9c..1cbf76554 100644 --- a/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp +++ b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.cpp @@ -43,10 +43,15 @@ void WKSoupRequestManagerSetClient(WKSoupRequestManagerRef soupRequestManagerRef void WKSoupRequestManagerRegisterURIScheme(WKSoupRequestManagerRef soupRequestManagerRef, WKStringRef schemeRef) { - toImpl(soupRequestManagerRef)->registerURIScheme(toImpl(schemeRef)->string()); + toImpl(soupRequestManagerRef)->registerURIScheme(toWTFString(schemeRef)); } -void WKSoupRequestManagerHandleURIRequest(WKSoupRequestManagerRef soupRequestManagerRef, WKDataRef data, WKStringRef mimeTypeRef, uint64_t requestID) +void WKSoupRequestManagerDidHandleURIRequest(WKSoupRequestManagerRef soupRequestManagerRef, WKDataRef data, uint64_t contentLength, WKStringRef mimeTypeRef, uint64_t requestID) { - toImpl(soupRequestManagerRef)->handleURIRequest(toImpl(data), toImpl(mimeTypeRef)->string(), requestID); + toImpl(soupRequestManagerRef)->didHandleURIRequest(toImpl(data), contentLength, toWTFString(mimeTypeRef), requestID); +} + +void WKSoupRequestManagerDidReceiveURIRequestData(WKSoupRequestManagerRef soupRequestManagerRef, WKDataRef data, uint64_t requestID) +{ + toImpl(soupRequestManagerRef)->didReceiveURIRequestData(toImpl(data), requestID); } diff --git a/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h index 74b4fa005..273eb7cc2 100644 --- a/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h +++ b/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h @@ -48,7 +48,8 @@ WK_EXPORT WKTypeID WKSoupRequestManagerGetTypeID(); WK_EXPORT void WKSoupRequestManagerSetClient(WKSoupRequestManagerRef, const WKSoupRequestManagerClient* client); WK_EXPORT void WKSoupRequestManagerRegisterURIScheme(WKSoupRequestManagerRef, WKStringRef schemeRef); -WK_EXPORT void WKSoupRequestManagerHandleURIRequest(WKSoupRequestManagerRef, WKDataRef, WKStringRef mimeTypeRef, uint64_t requestID); +WK_EXPORT void WKSoupRequestManagerDidHandleURIRequest(WKSoupRequestManagerRef, WKDataRef, uint64_t contentLength, WKStringRef mimeTypeRef, uint64_t requestID); +WK_EXPORT void WKSoupRequestManagerDidReceiveURIRequestData(WKSoupRequestManagerRef, WKDataRef, uint64_t requestID); #ifdef __cplusplus } diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfo.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfo.cpp new file mode 100644 index 000000000..2282ede37 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfo.cpp @@ -0,0 +1,145 @@ +/* + * 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 "WebKitMimeInfo.h" + +#include "WebKitMimeInfoPrivate.h" +#include <wtf/gobject/GRefPtr.h> +#include <wtf/text/CString.h> + +struct _WebKitMimeInfo { + _WebKitMimeInfo(const WebCore::MimeClassInfo& mimeInfo) + : mimeInfo(mimeInfo) + { + } + + WebCore::MimeClassInfo mimeInfo; + CString mimeType; + CString description; + GRefPtr<GPtrArray> extensions; + + int referenceCount; +}; + +G_DEFINE_BOXED_TYPE(WebKitMimeInfo, webkit_mime_info, webkit_mime_info_ref, webkit_mime_info_unref) + +WebKitMimeInfo* webkitMimeInfoCreate(const WebCore::MimeClassInfo& mimeInfo) +{ + WebKitMimeInfo* info = g_slice_new(WebKitMimeInfo); + new (info) WebKitMimeInfo(mimeInfo); + return info; +} + +/** + * webkit_mime_info_ref: + * @info: a #WebKitMimeInfo + * + * Atomically increments the reference count of @info by one. This + * function is MT-safe and may be called from any thread. + * + * Returns: The passed in #WebKitMimeInfo + */ +WebKitMimeInfo* webkit_mime_info_ref(WebKitMimeInfo* info) +{ + g_atomic_int_inc(&info->referenceCount); + return info; +} + +/** + * webkit_mime_info_unref: + * @info: a #WebKitMimeInfo + * + * Atomically decrements the reference count of @info by one. If the + * reference count drops to 0, all memory allocated by the #WebKitMimeInfo is + * released. This function is MT-safe and may be called from any + * thread. + */ +void webkit_mime_info_unref(WebKitMimeInfo* info) +{ + if (g_atomic_int_dec_and_test(&info->referenceCount)) { + info->~WebKitMimeInfo(); + g_slice_free(WebKitMimeInfo, info); + } +} + +/** + * webkit_mime_info_get_mime_type: + * @info: a #WebKitMimeInfo + * + * Returns: the MIME type of @info + */ +const char* webkit_mime_info_get_mime_type(WebKitMimeInfo* info) +{ + if (!info->mimeType.isNull()) + return info->mimeType.data(); + + if (info->mimeInfo.type.isEmpty()) + return 0; + + info->mimeType = info->mimeInfo.type.utf8(); + return info->mimeType.data(); +} + +/** + * webkit_mime_info_get_description: + * @info: a #WebKitMimeInfo + * + * Returns: the description of the MIME type of @info + */ +const char* webkit_mime_info_get_description(WebKitMimeInfo* info) +{ + if (!info->description.isNull()) + return info->description.data(); + + if (info->mimeInfo.desc.isEmpty()) + return 0; + + info->description = info->mimeInfo.desc.utf8(); + return info->description.data(); +} + +/** + * webkit_mime_info_get_extensions: + * @info: a #WebKitMimeInfo + * + * Get the list of file extensions associated to the + * MIME type of @info + * + * Returns: (array zero-terminated=1) (transfer none): a + * %NULL-terminated array of strings + */ +const char* const* webkit_mime_info_get_extensions(WebKitMimeInfo* info) +{ + if (info->extensions) + return reinterpret_cast<gchar**>(info->extensions->pdata); + + if (info->mimeInfo.extensions.isEmpty()) + return 0; + + info->extensions = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + for (size_t i = 0; i < info->mimeInfo.extensions.size(); ++i) { + if (info->mimeInfo.extensions[i].isEmpty()) + continue; + g_ptr_array_add(info->extensions.get(), g_strdup(info->mimeInfo.extensions[i].utf8().data())); + } + g_ptr_array_add(info->extensions.get(), 0); + + return reinterpret_cast<gchar**>(info->extensions->pdata); +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfo.h b/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfo.h new file mode 100644 index 000000000..7ec8e69c5 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfo.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitMimeInfo_h +#define WebKitMimeInfo_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_MIME_INFO (webkit_mime_info_get_type()) + +typedef struct _WebKitMimeInfo WebKitMimeInfo; + + +WEBKIT_API GType +webkit_mime_info_get_type (void); + +WEBKIT_API WebKitMimeInfo * +webkit_mime_info_ref (WebKitMimeInfo *info); + +WEBKIT_API void +webkit_mime_info_unref (WebKitMimeInfo *info); + +WEBKIT_API const gchar * +webkit_mime_info_get_mime_type (WebKitMimeInfo *info); + +WEBKIT_API const gchar * +webkit_mime_info_get_description (WebKitMimeInfo *info); + +WEBKIT_API const gchar * const * +webkit_mime_info_get_extensions (WebKitMimeInfo *info); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfoPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfoPrivate.h new file mode 100644 index 000000000..0ccc007b3 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitMimeInfoPrivate.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitMimeInfoPrivate_h +#define WebKitMimeInfoPrivate_h + +#include "WebKitMimeInfo.h" +#include "WebKitPrivate.h" +#include <WebCore/PluginData.h> + +WebKitMimeInfo* webkitMimeInfoCreate(const WebCore::MimeClassInfo&); + +#endif // WebKitMimeInfoPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPlugin.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitPlugin.cpp new file mode 100644 index 000000000..aff651aed --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPlugin.cpp @@ -0,0 +1,151 @@ +/* + * 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 "WebKitPlugin.h" + +#include "WebKitMimeInfoPrivate.h" +#include "WebKitPluginPrivate.h" +#include <wtf/text/CString.h> + +using namespace WebKit; + +struct _WebKitPluginPrivate { + PluginModuleInfo pluginInfo; + CString name; + CString description; + CString path; + GList* mimeInfoList; +}; + +G_DEFINE_TYPE(WebKitPlugin, webkit_plugin, G_TYPE_OBJECT) + +static void webkitPluginFinalize(GObject* object) +{ + WebKitPluginPrivate* priv = WEBKIT_PLUGIN(object)->priv; + g_list_free_full(priv->mimeInfoList, reinterpret_cast<GDestroyNotify>(webkit_mime_info_unref)); + priv->~WebKitPluginPrivate(); + G_OBJECT_CLASS(webkit_plugin_parent_class)->finalize(object); +} + +static void webkit_plugin_init(WebKitPlugin* plugin) +{ + WebKitPluginPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(plugin, WEBKIT_TYPE_PLUGIN, WebKitPluginPrivate); + plugin->priv = priv; + new (priv) WebKitPluginPrivate(); +} + +static void webkit_plugin_class_init(WebKitPluginClass* pluginClass) +{ + GObjectClass* gObjectClass = G_OBJECT_CLASS(pluginClass); + gObjectClass->finalize = webkitPluginFinalize; + + g_type_class_add_private(pluginClass, sizeof(WebKitPluginPrivate)); +} + +WebKitPlugin* webkitPluginCreate(const PluginModuleInfo& pluginInfo) +{ + WebKitPlugin* plugin = WEBKIT_PLUGIN(g_object_new(WEBKIT_TYPE_PLUGIN, NULL)); + plugin->priv->pluginInfo = pluginInfo; + return plugin; +} + +/** + * webkit_plugin_get_name: + * @plugin: a #WebKitPlugin + * + * Returns: the name of the plugin. + */ +const char* webkit_plugin_get_name(WebKitPlugin* plugin) +{ + g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0); + + if (!plugin->priv->name.isNull()) + return plugin->priv->name.data(); + + if (plugin->priv->pluginInfo.info.name.isEmpty()) + return 0; + + plugin->priv->name = plugin->priv->pluginInfo.info.name.utf8(); + return plugin->priv->name.data(); +} + +/** + * webkit_plugin_get_description: + * @plugin: a #WebKitPlugin + * + * Returns: the description of the plugin. + */ +const char* webkit_plugin_get_description(WebKitPlugin* plugin) +{ + g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0); + + if (!plugin->priv->description.isNull()) + plugin->priv->description.data(); + + if (plugin->priv->pluginInfo.info.desc.isEmpty()) + return 0; + + plugin->priv->description = plugin->priv->pluginInfo.info.desc.utf8(); + return plugin->priv->description.data(); +} + +/** + * webkit_plugin_get_path: + * @plugin: a #WebKitPlugin + * + * Returns: the absolute path where the plugin is installed. + */ +const char* webkit_plugin_get_path(WebKitPlugin* plugin) +{ + g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0); + + if (!plugin->priv->path.isNull()) + return plugin->priv->path.data(); + + if (plugin->priv->pluginInfo.path.isEmpty()) + return 0; + + plugin->priv->path = plugin->priv->pluginInfo.path.utf8(); + return plugin->priv->path.data(); +} + +/** + * webkit_plugin_get_mime_info_list: + * @plugin: a #WebKitPlugin + * + * Get information about MIME types handled by the plugin, + * as a list of #WebKitMimeInfo. + * + * Returns: (element-type WebKitMimeInfo) (transfer none): a #GList of #WebKitMimeInfo. + */ +GList* webkit_plugin_get_mime_info_list(WebKitPlugin* plugin) +{ + g_return_val_if_fail(WEBKIT_IS_PLUGIN(plugin), 0); + + if (plugin->priv->mimeInfoList) + return plugin->priv->mimeInfoList; + + if (plugin->priv->pluginInfo.info.mimes.isEmpty()) + return 0; + + for (size_t i = 0; i < plugin->priv->pluginInfo.info.mimes.size(); ++i) + plugin->priv->mimeInfoList = g_list_prepend(plugin->priv->mimeInfoList, webkitMimeInfoCreate(plugin->priv->pluginInfo.info.mimes[i])); + return plugin->priv->mimeInfoList; +} diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPlugin.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPlugin.h new file mode 100644 index 000000000..8928348cc --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPlugin.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) +#error "Only <webkit2/webkit2.h> can be included directly." +#endif + +#ifndef WebKitPlugin_h +#define WebKitPlugin_h + +#include <glib-object.h> +#include <webkit2/WebKitDefines.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_PLUGIN (webkit_plugin_get_type()) +#define WEBKIT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_PLUGIN, WebKitPlugin)) +#define WEBKIT_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_PLUGIN)) +#define WEBKIT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_PLUGIN, WebKitPluginClass)) +#define WEBKIT_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_PLUGIN)) +#define WEBKIT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_PLUGIN, WebKitPluginClass)) + +typedef struct _WebKitPlugin WebKitPlugin; +typedef struct _WebKitPluginClass WebKitPluginClass; +typedef struct _WebKitPluginPrivate WebKitPluginPrivate; + +struct _WebKitPlugin { + GObject parent; + + WebKitPluginPrivate *priv; +}; + +struct _WebKitPluginClass { + GObjectClass parent_class; +}; + +WEBKIT_API GType +webkit_plugin_get_type (void); + +WEBKIT_API const gchar * +webkit_plugin_get_name (WebKitPlugin *plugin); + +WEBKIT_API const gchar * +webkit_plugin_get_description (WebKitPlugin *plugin); + +WEBKIT_API const gchar * +webkit_plugin_get_path (WebKitPlugin *plugin); + +WEBKIT_API GList * +webkit_plugin_get_mime_info_list (WebKitPlugin *plugin); + +G_END_DECLS + +#endif diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPluginPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPluginPrivate.h new file mode 100644 index 000000000..3fe2ac0bf --- /dev/null +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPluginPrivate.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WebKitPluginPrivate_h +#define WebKitPluginPrivate_h + +#include "PluginModuleInfo.h" +#include "WebKitPlugin.h" +#include "WebKitPrivate.h" + +WebKitPlugin* webkitPluginCreate(const WebKit::PluginModuleInfo&); + +#endif // WebKitPluginPrivate_h diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp index 5c027044b..cd04eb12b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp @@ -919,28 +919,28 @@ static void webkit_settings_init(WebKitSettings* settings) priv->preferences = adoptWK(WKPreferencesCreate()); - WKRetainPtr<WKStringRef> defaultFontFamilyRef = WKPreferencesCopyStandardFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> defaultFontFamilyRef = adoptWK(WKPreferencesCopyStandardFontFamily(priv->preferences.get())); priv->defaultFontFamily = WebKit::toImpl(defaultFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> monospaceFontFamilyRef = WKPreferencesCopyFixedFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> monospaceFontFamilyRef = adoptWK(WKPreferencesCopyFixedFontFamily(priv->preferences.get())); priv->monospaceFontFamily = WebKit::toImpl(monospaceFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> serifFontFamilyRef = WKPreferencesCopySerifFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> serifFontFamilyRef = adoptWK(WKPreferencesCopySerifFontFamily(priv->preferences.get())); priv->serifFontFamily = WebKit::toImpl(serifFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> sansSerifFontFamilyRef = WKPreferencesCopySansSerifFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> sansSerifFontFamilyRef = adoptWK(WKPreferencesCopySansSerifFontFamily(priv->preferences.get())); priv->sansSerifFontFamily = WebKit::toImpl(sansSerifFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> cursiveFontFamilyRef = WKPreferencesCopyCursiveFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> cursiveFontFamilyRef = adoptWK(WKPreferencesCopyCursiveFontFamily(priv->preferences.get())); priv->cursiveFontFamily = WebKit::toImpl(cursiveFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> fantasyFontFamilyRef = WKPreferencesCopyFantasyFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> fantasyFontFamilyRef = adoptWK(WKPreferencesCopyFantasyFontFamily(priv->preferences.get())); priv->fantasyFontFamily = WebKit::toImpl(fantasyFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> pictographFontFamilyRef = WKPreferencesCopyPictographFontFamily(priv->preferences.get()); + WKRetainPtr<WKStringRef> pictographFontFamilyRef = adoptWK(WKPreferencesCopyPictographFontFamily(priv->preferences.get())); priv->pictographFontFamily = WebKit::toImpl(pictographFontFamilyRef.get())->string().utf8(); - WKRetainPtr<WKStringRef> defaultCharsetRef = WKPreferencesCopyDefaultTextEncodingName(priv->preferences.get()); + WKRetainPtr<WKStringRef> defaultCharsetRef = adoptWK(WKPreferencesCopyDefaultTextEncodingName(priv->preferences.get())); priv->defaultCharset = WebKit::toImpl(defaultCharsetRef.get())->string().utf8(); } @@ -1511,7 +1511,7 @@ void webkit_settings_set_serif_font_family(WebKitSettings* settings, const gchar if (!g_strcmp0(priv->serifFontFamily.data(), serifFontFamily)) return; - WKRetainPtr<WKStringRef> serifFontFamilyRef = WKStringCreateWithUTF8CString(serifFontFamily); + WKRetainPtr<WKStringRef> serifFontFamilyRef = adoptWK(WKStringCreateWithUTF8CString(serifFontFamily)); WKPreferencesSetSerifFontFamily(priv->preferences.get(), serifFontFamilyRef.get()); priv->serifFontFamily = WebKit::toImpl(serifFontFamilyRef.get())->string().utf8(); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 0b68c086d..5ec64d9d5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -24,8 +24,10 @@ #include "WebKitCookieManagerPrivate.h" #include "WebKitDownloadClient.h" #include "WebKitDownloadPrivate.h" +#include "WebKitPluginPrivate.h" #include "WebKitPrivate.h" #include "WebKitWebContextPrivate.h" +#include <WebCore/FileSystem.h> #include <wtf/HashMap.h> #include <wtf/gobject/GRefPtr.h> #include <wtf/text/CString.h> @@ -236,6 +238,97 @@ WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* con return priv->cookieManager.get(); } +/** + * webkit_web_context_set_additional_plugins_directory: + * @context: a #WebKitWebContext + * @directory: the directory to add + * + * Set an additional directory where WebKit will look for plugins. + */ +void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* context, const char* directory) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + g_return_if_fail(directory); + + toImpl(context->priv->context.get())->setAdditionalPluginsDirectory(WebCore::filenameToString(directory)); +} + +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); +} + +static void webkitWebContextGetPluginThread(GSimpleAsyncResult* result, GObject* object, GCancellable*) +{ + GetPluginsAsyncData* data = static_cast<GetPluginsAsyncData*>(g_simple_async_result_get_op_res_gpointer(result)); + data->plugins = toImpl(WEBKIT_WEB_CONTEXT(object)->priv->context.get())->pluginInfoStore().plugins(); +} + +/** + * webkit_web_context_get_plugins: + * @context: a #WebKitWebContext + * @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 + * + * Asynchronously get the list of installed plugins. + * + * When the operation is finished, @callback will be called. You can then call + * webkit_web_context_get_plugins_finish() to get the result of the operation. + */ +void webkit_web_context_get_plugins(WebKitWebContext* context, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + + 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_run_in_thread(result.get(), webkitWebContextGetPluginThread, G_PRIORITY_DEFAULT, cancellable); +} + +/** + * webkit_web_context_get_plugins_finish: + * @context: a #WebKitWebContext + * @result: a #GAsyncResult + * @error: return location for error or %NULL to ignore + * + * Finish an asynchronous operation started with webkit_web_context_get_plugins. + * + * Returns: (element-type WebKitPlugin) (transfer full): a #GList of #WebKitPlugin. You must free the #GList with + * g_list_free() and unref the #WebKitPlugin<!-- -->s with g_object_unref() when you're done with them. + */ +GList* webkit_web_context_get_plugins_finish(WebKitWebContext* context, GAsyncResult* result, GError** error) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0); + + GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result); + g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_context_get_plugins); + + if (g_simple_async_result_propagate_error(simpleResult, error)) + return 0; + + GetPluginsAsyncData* data = static_cast<GetPluginsAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult)); + GList* plugins = 0; + for (size_t i = 0; i < data->plugins.size(); ++i) + plugins = g_list_prepend(plugins, webkitPluginCreate(data->plugins[i])); + + return plugins; +} + WebKitDownload* webkitWebContextGetOrCreateDownload(WKDownloadRef wkDownload) { GRefPtr<WebKitDownload> download = downloadsMap().get(wkDownload); diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h index 45b6e6c1d..02ef73d43 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h @@ -80,23 +80,38 @@ struct _WebKitWebContextClass { }; WEBKIT_API GType -webkit_web_context_get_type (void); +webkit_web_context_get_type (void); WEBKIT_API WebKitWebContext * -webkit_web_context_get_default (void); +webkit_web_context_get_default (void); WEBKIT_API void -webkit_web_context_set_cache_model (WebKitWebContext *context, - WebKitCacheModel cache_model); +webkit_web_context_set_cache_model (WebKitWebContext *context, + WebKitCacheModel cache_model); WEBKIT_API WebKitCacheModel -webkit_web_context_get_cache_model (WebKitWebContext *context); +webkit_web_context_get_cache_model (WebKitWebContext *context); WEBKIT_API WebKitDownload * -webkit_web_context_download_uri (WebKitWebContext *context, - const gchar *uri); +webkit_web_context_download_uri (WebKitWebContext *context, + const gchar *uri); WEBKIT_API WebKitCookieManager * -webkit_web_context_get_cookie_manager (WebKitWebContext *context); +webkit_web_context_get_cookie_manager (WebKitWebContext *context); + +WEBKIT_API void +webkit_web_context_set_additional_plugins_directory (WebKitWebContext *context, + const gchar *directory); + +WEBKIT_API void +webkit_web_context_get_plugins (WebKitWebContext *context, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +WEBKIT_API GList * +webkit_web_context_get_plugins_finish (WebKitWebContext *context, + GAsyncResult *result, + GError **error); G_END_DECLS diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml index 821127f3d..63db05f77 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml @@ -31,6 +31,7 @@ <xi:include href="xml/WebKitFileChooserRequest.xml"/> <xi:include href="xml/WebKitFindController.xml"/> <xi:include href="xml/WebKitCookieManager.xml"/> + <xi:include href="xml/WebKitPlugin.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 f5e15d9b2..884177b8b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt @@ -29,6 +29,9 @@ webkit_web_context_get_cache_model webkit_web_context_set_cache_model webkit_web_context_download_uri webkit_web_context_get_cookie_manager +webkit_web_context_set_additional_plugins_directory +webkit_web_context_get_plugins +webkit_web_context_get_plugins_finish <SUBSECTION Standard> WebKitWebContextClass @@ -601,3 +604,35 @@ WEBKIT_COOKIE_MANAGER_GET_CLASS WebKitCookieManagerPrivate webkit_cookie_manager_get_type </SECTION> + +<SECTION> +<FILE>WebKitPlugin</FILE> +WebKitPlugin +webkit_plugin_get_name +webkit_plugin_get_description +webkit_plugin_get_path +webkit_plugin_get_mime_info_list + +<SUBSECTION WebKitMimeInfo> +WebKitMimeInfo +webkit_mime_info_ref +webkit_mime_info_unref +webkit_mime_info_get_mime_type +webkit_mime_info_get_description +webkit_mime_info_get_extensions + +<SUBSECTION Standard> +WebKitPluginClass +WEBKIT_TYPE_PLUGIN +WEBKIT_PLUGIN +WEBKIT_IS_PLUGIN +WEBKIT_PLUGIN_CLASS +WEBKIT_IS_PLUGIN_CLASS +WEBKIT_PLUGIN_GET_CLASS +WEBKIT_TYPE_MIME_INFO + +<SUBSECTION Private> +webkit_plugin_get_type +webkit_mime_info_get_type +WebKitPluginPrivate +</SECTION> diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types index 1ca821b47..cdf9edd73 100644 --- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types +++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types @@ -15,3 +15,5 @@ webkit_script_dialog_get_type webkit_javascript_result_get_type webkit_web_resource_get_type webkit_cookie_manager_get_type +webkit_plugin_get_type +webkit_mime_info_get_type diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am index b389f4954..870d68a5b 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am +++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am @@ -65,7 +65,9 @@ Libraries_libWebKit2APITestCore_la_CPPFLAGS = $(webkit2_tests_cppflags) Programs_WebKit2APITests_TestWebKitWebContext_SOURCES = \ Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp -Programs_WebKit2APITests_TestWebKitWebContext_CPPFLAGS = $(webkit2_tests_cppflags) +Programs_WebKit2APITests_TestWebKitWebContext_CPPFLAGS = \ + -DWEBKIT_TEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \ + $(webkit2_tests_cppflags) Programs_WebKit2APITests_TestWebKitWebContext_LDADD = $(webkit2_tests_ldadd) Programs_WebKit2APITests_TestWebKitWebContext_LDFLAGS = $(webkit2_tests_ldflags) diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp index ad7ce5b8b..216a5c9f5 100644 --- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebContext.cpp @@ -22,6 +22,7 @@ #include "TestMain.h" #include <gtk/gtk.h> #include <webkit2/webkit2.h> +#include <wtf/gobject/GRefPtr.h> static void testWebContextDefault(Test* test, gconstpointer) { @@ -29,9 +30,86 @@ static void testWebContextDefault(Test* test, gconstpointer) g_assert(webkit_web_context_get_default() == webkit_web_context_get_default()); } +class PluginsTest: public Test { +public: + MAKE_GLIB_TEST_FIXTURE(PluginsTest); + + PluginsTest() + : m_context(webkit_web_context_get_default()) + , m_mainLoop(g_main_loop_new(0, TRUE)) + , m_plugins(0) + { + webkit_web_context_set_additional_plugins_directory(m_context, WEBKIT_TEST_PLUGIN_DIR); + } + + ~PluginsTest() + { + g_main_loop_unref(m_mainLoop); + g_list_free_full(m_plugins, g_object_unref); + } + + static void getPluginsAsyncReadyCallback(GObject*, GAsyncResult* result, PluginsTest* test) + { + test->m_plugins = webkit_web_context_get_plugins_finish(test->m_context, result, 0); + g_main_loop_quit(test->m_mainLoop); + } + + GList* getPlugins() + { + g_list_free_full(m_plugins, g_object_unref); + webkit_web_context_get_plugins(m_context, 0, reinterpret_cast<GAsyncReadyCallback>(getPluginsAsyncReadyCallback), this); + g_main_loop_run(m_mainLoop); + return m_plugins; + } + + WebKitWebContext* m_context; + GMainLoop* m_mainLoop; + GList* m_plugins; +}; + +static void testWebContextGetPlugins(PluginsTest* test, gconstpointer) +{ + GList* plugins = test->getPlugins(); + g_assert(plugins); + + GRefPtr<WebKitPlugin> testPlugin; + for (GList* item = plugins; item; item = g_list_next(item)) { + WebKitPlugin* plugin = WEBKIT_PLUGIN(item->data); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(plugin)); + if (!g_strcmp0(webkit_plugin_get_name(plugin), "WebKit Test PlugIn")) { + testPlugin = plugin; + break; + } + } + g_assert(WEBKIT_IS_PLUGIN(testPlugin.get())); + + GOwnPtr<char> pluginPath(g_build_filename(WEBKIT_TEST_PLUGIN_DIR, "libtestnetscapeplugin.so", NULL)); + g_assert_cmpstr(webkit_plugin_get_path(testPlugin.get()), ==, pluginPath.get()); + g_assert_cmpstr(webkit_plugin_get_description(testPlugin.get()), ==, "Simple Netscape® plug-in that handles test content for WebKit"); + GList* mimeInfoList = webkit_plugin_get_mime_info_list(testPlugin.get()); + g_assert(mimeInfoList); + g_assert_cmpuint(g_list_length(mimeInfoList), ==, 2); + + WebKitMimeInfo* mimeInfo = static_cast<WebKitMimeInfo*>(mimeInfoList->data); + g_assert_cmpstr(webkit_mime_info_get_mime_type(mimeInfo), ==, "image/png"); + g_assert_cmpstr(webkit_mime_info_get_description(mimeInfo), ==, "png image"); + const gchar* const* extensions = webkit_mime_info_get_extensions(mimeInfo); + g_assert(extensions); + g_assert_cmpstr(extensions[0], ==, "png"); + + mimeInfoList = g_list_next(mimeInfoList); + mimeInfo = static_cast<WebKitMimeInfo*>(mimeInfoList->data); + g_assert_cmpstr(webkit_mime_info_get_mime_type(mimeInfo), ==, "application/x-webkit-test-netscape"); + g_assert_cmpstr(webkit_mime_info_get_description(mimeInfo), ==, "test netscape content"); + extensions = webkit_mime_info_get_extensions(mimeInfo); + g_assert(extensions); + g_assert_cmpstr(extensions[0], ==, "testnetscape"); +} + void beforeAll() { Test::add("WebKitWebContext", "default-context", testWebContextDefault); + PluginsTest::add("WebKitWebContext", "get-plugins", testWebContextGetPlugins); } void afterAll() diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h index c5460f333..7699c4966 100644 --- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h +++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h @@ -35,6 +35,8 @@ #include <webkit2/WebKitFindController.h> #include <webkit2/WebKitHitTestResult.h> #include <webkit2/WebKitJavascriptResult.h> +#include <webkit2/WebKitMimeInfo.h> +#include <webkit2/WebKitPlugin.h> #include <webkit2/WebKitPrintOperation.h> #include <webkit2/WebKitScriptDialog.h> #include <webkit2/WebKitSettings.h> diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp index 203c72b7e..e02ccc9b2 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebpage.cpp @@ -29,6 +29,7 @@ #include "WebPageProxy.h" #include "qquickwebpage_p_p.h" #include "qquickwebview_p.h" +#include "qwebkittest_p.h" #include <QtQuick/QQuickCanvas> using namespace WebKit; @@ -110,6 +111,7 @@ void QQuickWebPage::setContentsSize(const QSizeF& size) d->contentsSize = size; d->updateSize(); + emit d->viewportItem->experimental()->test()->contentsSizeChanged(); } const QSizeF& QQuickWebPage::contentsSize() const @@ -122,6 +124,7 @@ void QQuickWebPage::setContentsScale(qreal scale) ASSERT(scale > 0); d->contentsScale = scale; d->updateSize(); + emit d->viewportItem->experimental()->test()->contentsScaleCommitted(); } qreal QQuickWebPage::contentsScale() const diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp index 167c50f6a..935842146 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp @@ -39,19 +39,17 @@ #endif #include "WebPageGroup.h" #include "WebPreferences.h" - #include "qquicknetworkreply_p.h" #include "qquicknetworkrequest_p.h" #include "qquickwebpage_p_p.h" #include "qquickwebview_p_p.h" #include "qwebdownloaditem_p_p.h" +#include "qwebkittest_p.h" #include "qwebloadrequest_p.h" #include "qwebnavigationhistory_p.h" #include "qwebnavigationhistory_p_p.h" #include "qwebpreferences_p.h" #include "qwebpreferences_p_p.h" -#include "qwebviewportinfo_p.h" - #include <JavaScriptCore/InitializeThreading.h> #include <JavaScriptCore/JSBase.h> #include <JavaScriptCore/JSRetainPtr.h> @@ -266,6 +264,7 @@ QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport) , m_navigatorQtObjectEnabled(false) , m_renderToOffscreenBuffer(false) , m_dialogActive(false) + , m_allowAnyHTTPSCertificateForLocalHost(false) , m_loadProgress(0) { viewport->setClip(true); @@ -495,47 +494,36 @@ void QQuickWebViewPrivate::_q_onReceivedResponseFromDownload(QWebDownloadItem* d void QQuickWebViewPrivate::runJavaScriptAlert(const QString& alertText) { - if (!alertDialog) - return; - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForAlert(alertDialog, q, alertText)) + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForAlert(alertText)) return; - execDialogRunner(dialogRunner); + dialogRunner.run(); } bool QQuickWebViewPrivate::runJavaScriptConfirm(const QString& message) { - if (!confirmDialog) - return true; - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForConfirm(confirmDialog, q, message)) + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForConfirm(message)) return true; - execDialogRunner(dialogRunner); + dialogRunner.run(); return dialogRunner.wasAccepted(); } QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok) { - if (!promptDialog) { - ok = true; - return defaultValue; - } - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForPrompt(promptDialog, q, message, defaultValue)) { + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForPrompt(message, defaultValue)) { ok = true; return defaultValue; } - execDialogRunner(dialogRunner); + dialogRunner.run(); ok = dialogRunner.wasAccepted(); return dialogRunner.result(); @@ -543,15 +531,12 @@ QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& hostname, const QString& realm, const QString& prefilledUsername, QString& username, QString& password) { - if (!authenticationDialog) - return; - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForAuthentication(authenticationDialog, q, hostname, realm, prefilledUsername)) + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForAuthentication(hostname, realm, prefilledUsername)) return; - execDialogRunner(dialogRunner); + dialogRunner.run(); username = dialogRunner.username(); password = dialogRunner.password(); @@ -559,15 +544,12 @@ void QQuickWebViewPrivate::handleAuthenticationRequiredRequest(const QString& ho void QQuickWebViewPrivate::handleProxyAuthenticationRequiredRequest(const QString& hostname, uint16_t port, const QString& prefilledUsername, QString& username, QString& password) { - if (!proxyAuthenticationDialog) - return; - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForProxyAuthentication(proxyAuthenticationDialog, q, hostname, port, prefilledUsername)) + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForProxyAuthentication(hostname, port, prefilledUsername)) return; - execDialogRunner(dialogRunner); + dialogRunner.run(); username = dialogRunner.username(); password = dialogRunner.password(); @@ -575,43 +557,30 @@ void QQuickWebViewPrivate::handleProxyAuthenticationRequiredRequest(const QStrin bool QQuickWebViewPrivate::handleCertificateVerificationRequest(const QString& hostname) { - if (!certificateVerificationDialog) - return false; - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForCertificateVerification(certificateVerificationDialog, q, hostname)) - return false; - - execDialogRunner(dialogRunner); - return dialogRunner.wasAccepted(); -} + if (m_allowAnyHTTPSCertificateForLocalHost + && (hostname == QStringLiteral("127.0.0.1") || hostname == QStringLiteral("localhost"))) + return true; -void QQuickWebViewPrivate::execDialogRunner(QtDialogRunner& dialogRunner) -{ - setViewInAttachedProperties(dialogRunner.dialog()); + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForCertificateVerification(hostname)) + return false; - disableMouseEvents(); - m_dialogActive = true; + dialogRunner.run(); - dialogRunner.exec(); - m_dialogActive = false; - enableMouseEvents(); + return dialogRunner.wasAccepted(); } void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type) { Q_Q(QQuickWebView); - if (!filePicker) - return; - - QtDialogRunner dialogRunner; - if (!dialogRunner.initForFilePicker(filePicker, q, selectedFileNames, (type == QtWebPageUIClient::MultipleFilesSelection))) + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForFilePicker(selectedFileNames, (type == QtWebPageUIClient::MultipleFilesSelection))) return; - execDialogRunner(dialogRunner); + dialogRunner.run(); if (dialogRunner.wasAccepted()) { QStringList selectedPaths = dialogRunner.filePaths(); @@ -628,20 +597,41 @@ void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, quint64 QQuickWebViewPrivate::exceededDatabaseQuota(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) { - if (!databaseQuotaDialog) - return 0; - Q_Q(QQuickWebView); - QtDialogRunner dialogRunner; - if (!dialogRunner.initForDatabaseQuotaDialog(databaseQuotaDialog, q, databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage)) + QtDialogRunner dialogRunner(q); + if (!dialogRunner.initForDatabaseQuotaDialog(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage)) return 0; - execDialogRunner(dialogRunner); + dialogRunner.run(); return dialogRunner.wasAccepted() ? dialogRunner.databaseQuota() : 0; } -void QQuickWebViewPrivate::setViewInAttachedProperties(QObject* object) +/* The 'WebView' attached property allows items spawned by the webView to + refer back to the originating webView through 'WebView.view', similar + to how ListView.view and GridView.view is exposed to items. */ +QQuickWebViewAttached::QQuickWebViewAttached(QObject* object) + : QObject(object) + , m_view(0) +{ +} + +void QQuickWebViewAttached::setView(QQuickWebView* view) +{ + if (m_view == view) + return; + m_view = view; + emit viewChanged(); +} + +QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object) +{ + return new QQuickWebViewAttached(object); +} + + + +void QQuickWebViewPrivate::addAttachedPropertyTo(QObject* object) { Q_Q(QQuickWebView); QQuickWebViewAttached* attached = static_cast<QQuickWebViewAttached*>(qmlAttachedPropertiesObject<QQuickWebView>(object)); @@ -874,7 +864,7 @@ void QQuickWebViewFlickablePrivate::didChangeViewportProperties(const WebCore::V interactionEngine->setCSSScale(attr.initialScale); this->attributes = attr; - q->experimental()->viewportInfo()->didUpdateViewportConstraints(); + emit q->experimental()->test()->viewportChanged(); // If the web app successively changes the viewport on purpose // it wants to be in control and we should disable animations. @@ -903,8 +893,6 @@ void QQuickWebViewFlickablePrivate::updateViewportSize() void QQuickWebViewFlickablePrivate::_q_contentViewportChanged(const QPointF& trajectoryVector) { Q_Q(QQuickWebView); - // This is only for our QML ViewportInfo debugging API. - q->experimental()->viewportInfo()->didUpdateCurrentScale(); DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); if (!drawingArea) @@ -913,6 +901,8 @@ void QQuickWebViewFlickablePrivate::_q_contentViewportChanged(const QPointF& tra const QRect visibleRect(visibleContentsRect()); float scale = pageView->contentsScale(); + emit q->experimental()->test()->contentsScaleChanged(); + QRectF accurateVisibleRect(q->boundingRect()); accurateVisibleRect.translate(contentPos()); drawingArea->setVisibleContentsRect(visibleRect, scale, trajectoryVector, FloatPoint(accurateVisibleRect.x(), accurateVisibleRect.y())); @@ -948,14 +938,13 @@ void QQuickWebViewFlickablePrivate::didChangeContentsSize(const QSize& newSize) Q_Q(QQuickWebView); QSize viewportSize = q->boundingRect().size().toSize(); - pageView->setContentsSize(newSize); - q->experimental()->viewportInfo()->didUpdateContentsSize(); + pageView->setContentsSize(newSize); // emits contentsSizeChanged() float minimumScale = WebCore::computeMinimumScaleFactorForContentContained(attributes, viewportSize, newSize); if (!qFuzzyCompare(minimumScale, attributes.minimumScale)) { interactionEngine->setCSSScaleBounds(minimumScale, attributes.maximumScale); - q->experimental()->viewportInfo()->didUpdateViewportConstraints(); + emit q->experimental()->test()->viewportChanged(); if (!interactionEngine->hadUserInteraction() && !pageIsSuspended) interactionEngine->setCSSScale(minimumScale); @@ -978,27 +967,12 @@ void QQuickWebViewFlickablePrivate::didChangeContentsSize(const QSize& newSize) \sa WebNavigationRequest */ -QQuickWebViewAttached::QQuickWebViewAttached(QObject* object) - : QObject(object) - , m_view(0) -{ - -} - -void QQuickWebViewAttached::setView(QQuickWebView* view) -{ - if (m_view == view) - return; - m_view = view; - emit viewChanged(); -} - QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView) : QObject(webView) , q_ptr(webView) , d_ptr(webView->d_ptr.data()) , schemeParent(new QObject(this)) - , m_viewportInfo(new QWebViewportInfo(webView->d_ptr.data(), this)) + , m_test(new QWebKitTest(webView->d_ptr.data(), this)) { } @@ -1409,9 +1383,9 @@ void QQuickWebViewExperimental::goBackTo(int index) d_ptr->navigationHistory->d->goBackTo(index); } -QWebViewportInfo* QQuickWebViewExperimental::viewportInfo() +QWebKitTest* QQuickWebViewExperimental::test() { - return m_viewportInfo; + return m_test; } QQuickWebPage* QQuickWebViewExperimental::page() @@ -1633,11 +1607,6 @@ QQuickWebViewExperimental* QQuickWebView::experimental() const return m_experimental; } -QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object) -{ - return new QQuickWebViewAttached(object); -} - /*! \internal */ @@ -1738,6 +1707,7 @@ void QQuickWebView::mouseReleaseEvent(QMouseEvent* event) void QQuickWebView::mouseDoubleClickEvent(QMouseEvent* event) { Q_D(QQuickWebView); + // If a MouseButtonDblClick was received then we got a MouseButtonPress before // handleMousePressEvent will take care of double clicks. d->pageView->eventHandler()->handleMousePressEvent(event); @@ -1893,4 +1863,17 @@ void QQuickWebView::runJavaScriptInMainFrame(const QString &script, QObject *rec d->webPageProxy.get()->runJavaScriptInMainFrame(script, ScriptValueCallback::create(closure, javaScriptCallback)); } +bool QQuickWebView::allowAnyHTTPSCertificateForLocalHost() const +{ + Q_D(const QQuickWebView); + return d->m_allowAnyHTTPSCertificateForLocalHost; +} + +void QQuickWebView::setAllowAnyHTTPSCertificateForLocalHost(bool allow) +{ + Q_D(QQuickWebView); + d->m_allowAnyHTTPSCertificateForLocalHost = allow; +} + + #include "moc_qquickwebview_p.cpp" diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h index 4bdd0fbbd..773f735a9 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h @@ -38,7 +38,7 @@ class QWebDownloadItem; class QWebNavigationHistory; class QWebPreferences; class QWebPermissionRequest; -class QWebViewportInfo; +class QWebKitTest; class QQuickNetworkReply; namespace WTR { @@ -149,6 +149,9 @@ public: qreal zoomFactor() const; void setZoomFactor(qreal); void runJavaScriptInMainFrame(const QString& script, QObject* receiver, const char* method); + // Used to automatically accept the HTTPS certificate in WTR. No other use intended. + bool allowAnyHTTPSCertificateForLocalHost() const; + void setAllowAnyHTTPSCertificateForLocalHost(bool allow); public Q_SLOTS: void loadHtml(const QString& html, const QUrl& baseUrl = QUrl()); @@ -263,7 +266,7 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject { Q_PROPERTY(QQmlComponent* filePicker READ filePicker WRITE setFilePicker NOTIFY filePickerChanged) Q_PROPERTY(QQmlComponent* databaseQuotaDialog READ databaseQuotaDialog WRITE setDatabaseQuotaDialog NOTIFY databaseQuotaDialogChanged) Q_PROPERTY(QWebPreferences* preferences READ preferences CONSTANT FINAL) - Q_PROPERTY(QWebViewportInfo* viewportInfo READ viewportInfo CONSTANT FINAL) + Q_PROPERTY(QWebKitTest* test READ test CONSTANT FINAL) Q_PROPERTY(QQmlListProperty<QQuickUrlSchemeDelegate> urlSchemeDelegates READ schemeDelegates) Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent NOTIFY userAgentChanged) Q_PROPERTY(double devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged) @@ -300,7 +303,7 @@ public: double devicePixelRatio() const; void setDevicePixelRatio(double); - QWebViewportInfo* viewportInfo(); + QWebKitTest* test(); QWebPreferences* preferences() const; QWebNavigationHistory* navigationHistory() const; @@ -357,7 +360,7 @@ private: QQuickWebView* q_ptr; QQuickWebViewPrivate* d_ptr; QObject* schemeParent; - QWebViewportInfo* m_viewportInfo; + QWebKitTest* m_test; friend class WebKit::QtWebPageUIClient; diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h index de62d39bb..ebd06e3ea 100644 --- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h @@ -48,7 +48,7 @@ class WebPageProxy; } class QWebNavigationHistory; -class QWebViewportInfo; +class QWebKitTest; QT_BEGIN_NAMESPACE class QQmlComponent; @@ -56,10 +56,11 @@ QT_END_NAMESPACE class QQuickWebViewPrivate { Q_DECLARE_PUBLIC(QQuickWebView) + friend class WebKit::QtDialogRunner; friend class QQuickWebViewExperimental; friend class QQuickWebPage; friend class QWebPreferencesPrivate; - friend class QWebViewportInfo; + friend class QWebKitTest; public: static QQuickWebViewPrivate* get(QQuickWebView* q) { return q->d_ptr.data(); } @@ -116,11 +117,9 @@ public: bool handleCertificateVerificationRequest(const QString& hostname); void handleProxyAuthenticationRequiredRequest(const QString& hostname, uint16_t port, const QString& prefilledUsername, QString& username, QString& password); - void execDialogRunner(WebKit::QtDialogRunner&); - void setRenderToOffscreenBuffer(bool enable) { m_renderToOffscreenBuffer = enable; } void setTransparentBackground(bool); - void setViewInAttachedProperties(QObject*); + void addAttachedPropertyTo(QObject*); void setIcon(const QUrl&); bool navigatorQtObjectEnabled() const; @@ -199,6 +198,7 @@ protected: bool m_navigatorQtObjectEnabled; bool m_renderToOffscreenBuffer; bool m_dialogActive; + bool m_allowAnyHTTPSCertificateForLocalHost; QUrl m_iconURL; int m_loadProgress; }; diff --git a/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo.cpp b/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp index ea16732f5..8311528b5 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo.cpp +++ b/Source/WebKit2/UIProcess/API/qt/qwebkittest.cpp @@ -19,30 +19,55 @@ */ #include "config.h" -#include "QtViewportInteractionEngine.h" -#include "qwebviewportinfo_p.h" +#include "qwebkittest_p.h" +#include "QtViewportInteractionEngine.h" +#include "QtWebPageEventHandler.h" #include "qquickwebview_p.h" #include "qquickwebview_p_p.h" using namespace WebKit; -QWebViewportInfo::QWebViewportInfo(QQuickWebViewPrivate* webViewPrivate, QObject* parent) +QWebKitTest::QWebKitTest(QQuickWebViewPrivate* webViewPrivate, QObject* parent) : QObject(parent) , m_webViewPrivate(webViewPrivate) { } -QWebViewportInfo::~QWebViewportInfo() +QWebKitTest::~QWebKitTest() +{ +} + +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); + + QPointF localPos(x, y); + + QTouchEvent::TouchPoint point; + point.setLastPos(localPos); + QRectF touchRect(0, 0, 40, 40); + touchRect.moveCenter(localPos); + point.setRect(touchRect); + + m_webViewPrivate->pageView->eventHandler()->handleDoubleTapEvent(point); + + return true; } -QSize QWebViewportInfo::contentsSize() const +QSize QWebKitTest::contentsSize() const { return QSize(m_webViewPrivate->pageView->contentsSize().toSize()); } -QVariant QWebViewportInfo::currentScale() const +QVariant QWebKitTest::contentsScale() const { if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) return interactionEngine->currentCSSScale(); @@ -50,17 +75,17 @@ QVariant QWebViewportInfo::currentScale() const return m_webViewPrivate->attributes.initialScale; } -QVariant QWebViewportInfo::devicePixelRatio() const +QVariant QWebKitTest::devicePixelRatio() const { return m_webViewPrivate->attributes.devicePixelRatio; } -QVariant QWebViewportInfo::initialScale() const +QVariant QWebKitTest::initialScale() const { return m_webViewPrivate->attributes.initialScale; } -QVariant QWebViewportInfo::minimumScale() const +QVariant QWebKitTest::minimumScale() const { if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) return interactionEngine->m_minimumScale; @@ -68,7 +93,7 @@ QVariant QWebViewportInfo::minimumScale() const return m_webViewPrivate->attributes.minimumScale; } -QVariant QWebViewportInfo::maximumScale() const +QVariant QWebKitTest::maximumScale() const { if (QtViewportInteractionEngine* interactionEngine = m_webViewPrivate->viewportInteractionEngine()) return interactionEngine->m_maximumScale; @@ -76,28 +101,12 @@ QVariant QWebViewportInfo::maximumScale() const return m_webViewPrivate->attributes.maximumScale; } -QVariant QWebViewportInfo::isScalable() const +QVariant QWebKitTest::isScalable() const { return !!m_webViewPrivate->attributes.userScalable; } -QVariant QWebViewportInfo::layoutSize() const +QVariant QWebKitTest::layoutSize() const { return QSizeF(m_webViewPrivate->attributes.layoutSize.width(), m_webViewPrivate->attributes.layoutSize.height()); } - -void QWebViewportInfo::didUpdateContentsSize() -{ - emit contentsSizeUpdated(); -} - -void QWebViewportInfo::didUpdateCurrentScale() -{ - emit currentScaleUpdated(); -} - -void QWebViewportInfo::didUpdateViewportConstraints() -{ - emit viewportConstraintsUpdated(); - emit currentScaleUpdated(); -} diff --git a/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo_p.h b/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h index d3060bbe6..f7c7180c1 100644 --- a/Source/WebKit2/UIProcess/API/qt/qwebviewportinfo_p.h +++ b/Source/WebKit2/UIProcess/API/qt/qwebkittest_p.h @@ -18,8 +18,8 @@ * */ -#ifndef qwebviewportinfo_p_h -#define qwebviewportinfo_p_h +#ifndef qwebkittest_p_h +#define qwebkittest_p_h #include "qwebkitglobal.h" @@ -28,31 +28,40 @@ #include <QtCore/QSize> #include <QtCore/QVariant> #include <QtQml/QtQml> +#include <QtQuick/qquickitem.h> class QQuickWebViewPrivate; -class QWEBKIT_EXPORT QWebViewportInfo : public QObject { +class QWEBKIT_EXPORT QWebKitTest : public QObject { Q_OBJECT - Q_PROPERTY(QSize contentsSize READ contentsSize NOTIFY contentsSizeUpdated) - Q_PROPERTY(QVariant currentScale READ currentScale NOTIFY currentScaleUpdated) - Q_PROPERTY(QVariant devicePixelRatio READ devicePixelRatio NOTIFY viewportConstraintsUpdated) - Q_PROPERTY(QVariant initialScale READ initialScale NOTIFY viewportConstraintsUpdated) - Q_PROPERTY(QVariant isScalable READ isScalable NOTIFY viewportConstraintsUpdated) - Q_PROPERTY(QVariant maximumScale READ maximumScale NOTIFY viewportConstraintsUpdated) - Q_PROPERTY(QVariant minimumScale READ minimumScale NOTIFY viewportConstraintsUpdated) - Q_PROPERTY(QVariant layoutSize READ layoutSize NOTIFY viewportConstraintsUpdated) + + Q_PROPERTY(QSize contentsSize READ contentsSize NOTIFY contentsSizeChanged) + + Q_PROPERTY(QVariant contentsScale READ contentsScale NOTIFY contentsScaleChanged) + + Q_PROPERTY(QVariant devicePixelRatio READ devicePixelRatio NOTIFY viewportChanged) + Q_PROPERTY(QVariant initialScale READ initialScale NOTIFY viewportChanged) + Q_PROPERTY(QVariant isScalable READ isScalable NOTIFY viewportChanged) + Q_PROPERTY(QVariant maximumScale READ maximumScale NOTIFY viewportChanged) + Q_PROPERTY(QVariant minimumScale READ minimumScale NOTIFY viewportChanged) + Q_PROPERTY(QVariant layoutSize READ layoutSize NOTIFY viewportChanged) signals: - void contentsSizeUpdated(); - void currentScaleUpdated(); - void viewportConstraintsUpdated(); + void contentsSizeChanged(); + void contentsScaleChanged(); + void contentsScaleCommitted(); + void viewportChanged(); + +public slots: + bool touchDoubleTap(QObject* item, qreal x, qreal y, int delay = -1); public: - QWebViewportInfo(QQuickWebViewPrivate* webviewPrivate, QObject* parent = 0); - virtual ~QWebViewportInfo(); + QWebKitTest(QQuickWebViewPrivate* webviewPrivate, QObject* parent = 0); + virtual ~QWebKitTest(); QSize contentsSize() const; - QVariant currentScale() const; + QVariant contentsScale() const; + QVariant devicePixelRatio() const; QVariant initialScale() const; QVariant isScalable() const; @@ -60,12 +69,8 @@ public: QVariant maximumScale() const; QVariant minimumScale() const; - void didUpdateContentsSize(); - void didUpdateCurrentScale(); - void didUpdateViewportConstraints(); - private: QQuickWebViewPrivate* m_webViewPrivate; }; -#endif // qwebviewportinfo_p +#endif // qwebkittest_p diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro index 59a3ca5b4..11733ce48 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/DesktopBehavior.pro @@ -15,10 +15,5 @@ DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$PWD$${QMAKE_DIR_SEP}DesktopBehavior\\\" DEFINES += IMPORT_DIR=\"\\\"$${ROOT_BUILD_DIR}$${QMAKE_DIR_SEP}imports\\\"\" OTHER_FILES += \ - DesktopBehavior/DesktopWebView.qml \ - DesktopBehavior/tst_linkHovered.qml \ - DesktopBehavior/tst_loadHtml.qml \ - DesktopBehavior/tst_messaging.qml \ - DesktopBehavior/tst_navigationRequested.qml \ - DesktopBehavior/tst_singleFileupload.qml \ - DesktopBehavior/tst_multiFileupload.qml + DesktopBehavior/* \ + common/* diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView.pro b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView.pro index 57307f07a..5cc6f35f5 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView.pro +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView.pro @@ -14,18 +14,5 @@ DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$PWD$${QMAKE_DIR_SEP}WebView\\\"\" DEFINES += IMPORT_DIR=\"\\\"$${ROOT_BUILD_DIR}$${QMAKE_DIR_SEP}imports\\\"\" OTHER_FILES += \ - WebView/tst_favIconLoad.qml \ - WebView/tst_download.qml \ - WebView/tst_geopermission.qml \ - WebView/tst_itemSelector.qml \ - WebView/tst_javaScriptDialogs.qml \ - WebView/tst_loadFail.qml \ - WebView/tst_loadIgnore.qml \ - WebView/tst_loadHtml.qml \ - WebView/tst_loadProgress.qml \ - WebView/tst_loadProgressSignal.qml \ - WebView/tst_preferences.qml \ - WebView/tst_properties.qml \ - WebView/tst_titleChanged.qml \ - WebView/tst_applicationScheme.qml \ - WebView/tst_origin.qml + WebView/* \ + common/* 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 new file mode 100644 index 000000000..904f60feb --- /dev/null +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_doubleTapToZoom.qml @@ -0,0 +1,106 @@ +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>" + + " <div id='target' " + + " style='position:absolute; left:20; top:20; width:200; height:200;'>" + + " </div>" + + "</body>" + + signal resultReceived + signal scaleChanged + } + + SignalSpy { + id: resultSpy + target: webView + signalName: "resultReceived" + } + + SignalSpy { + id: scaleSpy + target: webView + signalName: "scaleChanged" + } + + TestCase { + name: "DoubleTapToZoom" + + 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() + } + + function documentSize() { + resultSpy.clear(); + var result; + + webView.experimental.evaluateJavaScript( + "window.innerWidth + 'x' + window.innerHeight", + function(size) { webView.resultReceived(); result = size }); + resultSpy.wait(); + return result; + } + + function elementRect(id) { + resultSpy.clear(); + var result; + + webView.experimental.evaluateJavaScript( + "document.getElementById('" + id + "').getBoundingClientRect();", + function(rect) { webView.resultReceived(); result = rect }); + resultSpy.wait(); + return result; + } + + function doubleTapAtPoint(x, y) { + scaleSpy.clear() + test.touchDoubleTap(webView, x, y) + scaleSpy.wait() + } + + function test_basic() { + webView.url = webView.content + verify(webView.waitForLoadSucceeded()) + + compare("480x720", documentSize()) + + compare(1.0, test.contentsScale) + + 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) + } + } +} diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_javaScriptDialogs.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_javaScriptDialogs.qml index 4e15c2344..d77933dba 100644 --- a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_javaScriptDialogs.qml +++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_javaScriptDialogs.qml @@ -12,39 +12,29 @@ TestWebView { property int confirmCount: 0 property int promptCount: 0 - experimental.alertDialog: Item { - Timer { - running: true - interval: 1 - onTriggered: { + experimental { + alertDialog: Item { + Component.onCompleted: { // Testing both attached property and id defined in the Component context. - parent.WebView.view.messageFromAlertDialog = message - webView.modelMessageEqualsMessage = Boolean(model.message == message) + WebView.view.messageFromAlertDialog = message + parent.modelMessageEqualsMessage = Boolean(model.message == message) model.dismiss() } } - } - experimental.confirmDialog: Item { - Timer { - running: true - interval: 1 - onTriggered: { - parent.WebView.view.confirmCount += 1 + confirmDialog: Item { + Component.onCompleted: { + WebView.view.confirmCount += 1 if (message == "ACCEPT") model.accept() else model.reject() } } - } - experimental.promptDialog: Item { - Timer { - running: true - interval: 1 - onTriggered: { - parent.WebView.view.promptCount += 1 + promptDialog: Item { + Component.onCompleted: { + WebView.view.promptCount += 1 if (message == "REJECT") model.reject() else { diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp index 97775c626..37ff06030 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.cpp @@ -69,6 +69,16 @@ typedef ListHashSet<String, 32, CaseFoldingHash> PathHashSet; typedef ListHashSet<String, 32> PathHashSet; #endif +static inline Vector<PluginModuleInfo> deepIsolatedCopyPluginInfoVector(const Vector<PluginModuleInfo>& vector) +{ + // Let the copy begin! + Vector<PluginModuleInfo> copy; + copy.reserveCapacity(vector.size()); + for (unsigned i = 0; i < vector.size(); ++i) + copy.append(vector[i].isolatedCopy()); + return copy; +} + void PluginInfoStore::loadPluginsIfNecessary() { if (m_pluginListIsUpToDate) @@ -94,7 +104,8 @@ void PluginInfoStore::loadPluginsIfNecessary() for (PathHashSet::const_iterator it = uniquePluginPaths.begin(); it != end; ++it) loadPlugin(plugins, *it); - m_plugins.swap(plugins); + m_plugins = deepIsolatedCopyPluginInfoVector(plugins); + m_pluginListIsUpToDate = true; } @@ -113,15 +124,15 @@ void PluginInfoStore::loadPlugin(Vector<PluginModuleInfo>& plugins, const String Vector<PluginModuleInfo> PluginInfoStore::plugins() { + MutexLocker locker(m_pluginsLock); loadPluginsIfNecessary(); - - Vector<PluginModuleInfo> plugins(m_plugins); - - return plugins; + return deepIsolatedCopyPluginInfoVector(m_plugins); } PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) const { + MutexLocker locker(m_pluginsLock); + ASSERT(!mimeType.isNull()); for (size_t i = 0; i < m_plugins.size(); ++i) { @@ -139,6 +150,8 @@ PluginModuleInfo PluginInfoStore::findPluginForMIMEType(const String& mimeType) PluginModuleInfo PluginInfoStore::findPluginForExtension(const String& extension, String& mimeType) const { + MutexLocker locker(m_pluginsLock); + ASSERT(!extension.isNull()); for (size_t i = 0; i < m_plugins.size(); ++i) { @@ -187,7 +200,10 @@ String PluginInfoStore::getMIMETypeForExtension(const String& extension) PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url) { - loadPluginsIfNecessary(); + { + MutexLocker locker(m_pluginsLock); + loadPluginsIfNecessary(); + } // First, check if we can get the plug-in based on its MIME type. if (!mimeType.isNull()) { @@ -219,6 +235,8 @@ PluginModuleInfo PluginInfoStore::findPlugin(String& mimeType, const KURL& url) PluginModuleInfo PluginInfoStore::infoForPluginWithPath(const String& pluginPath) const { + MutexLocker locker(m_pluginsLock); + for (size_t i = 0; i < m_plugins.size(); ++i) { if (m_plugins[i].path == pluginPath) return m_plugins[i]; diff --git a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h index f30303c83..42df69b09 100644 --- a/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h +++ b/Source/WebKit2/UIProcess/Plugins/PluginInfoStore.h @@ -27,6 +27,7 @@ #define PluginInfoStore_h #include "PluginModuleInfo.h" +#include <wtf/ThreadingPrimitives.h> namespace WebCore { class KURL; @@ -87,6 +88,8 @@ private: Vector<String> m_additionalPluginsDirectories; Vector<PluginModuleInfo> m_plugins; bool m_pluginListIsUpToDate; + + mutable Mutex m_pluginsLock; }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp b/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp index 653c72965..fa9339d09 100644 --- a/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp +++ b/Source/WebKit2/UIProcess/Plugins/gtk/PluginProcessProxyGtk.cpp @@ -31,6 +31,7 @@ #include "PluginProcessCreationParameters.h" #include "ProcessExecutablePath.h" #include <WebCore/FileSystem.h> +#include <WebCore/GOwnPtrGtk.h> #include <glib.h> #include <wtf/text/CString.h> #include <wtf/text/WTFString.h> @@ -54,8 +55,8 @@ bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& argv[3] = 0; gint status; - gchar* stdOut; - if (!g_spawn_sync(0, argv, 0, G_SPAWN_STDERR_TO_DEV_NULL, 0, 0, &stdOut, 0, &status, 0)) + GOwnPtr<gchar> stdOut; + if (!g_spawn_sync(0, argv, 0, G_SPAWN_STDERR_TO_DEV_NULL, 0, 0, &stdOut.outPtr(), 0, &status, 0)) return false; if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) return false; @@ -63,7 +64,7 @@ bool PluginProcessProxy::scanPlugin(const String& pluginPath, RawPluginMetaData& const unsigned kNumLinesExpected = 3; String lines[kNumLinesExpected]; unsigned lineIndex = 0; - const UChar* current = reinterpret_cast<const UChar*>(stdOut); + const UChar* current = reinterpret_cast<const UChar*>(stdOut.get()); while (lineIndex < kNumLinesExpected) { const UChar* start = current; while (*current++ != UChar('\n')) { } diff --git a/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm index 7a04b5355..8688cfa79 100644 --- a/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm +++ b/Source/WebKit2/UIProcess/Plugins/mac/PluginInfoStoreMac.mm @@ -73,7 +73,13 @@ Vector<String> PluginInfoStore::individualPluginPaths() bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin) { +#if ENABLE(NETSCAPE_PLUGIN_API) return NetscapePluginModule::getPluginInfo(pluginPath, plugin); +#else + UNUSED_PARAM(pluginPath); + UNUSED_PARAM(plugin); + return false; +#endif } bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin) diff --git a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp index caecf7942..aa44998d1 100644 --- a/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp +++ b/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp @@ -95,7 +95,13 @@ Vector<String> PluginInfoStore::individualPluginPaths() bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin) { +#if ENABLE(NETSCAPE_PLUGIN_API) return NetscapePluginModule::getPluginInfo(pluginPath, plugin); +#else + UNUSED_PARAM(pluginPath); + UNUSED_PARAM(plugin); + return false; +#endif } bool PluginInfoStore::shouldUsePlugin(Vector<PluginModuleInfo>& alreadyLoadedPlugins, const PluginModuleInfo& plugin) diff --git a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp index 78d0562d9..634225eaf 100644 --- a/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp +++ b/Source/WebKit2/UIProcess/Plugins/win/PluginInfoStoreWin.cpp @@ -325,7 +325,13 @@ static uint64_t fileVersion(DWORD leastSignificant, DWORD mostSignificant) bool PluginInfoStore::getPluginInfo(const String& pluginPath, PluginModuleInfo& plugin) { +#if ENABLE(NETSCAPE_PLUGIN_API) return NetscapePluginModule::getPluginInfo(pluginPath, plugin); +#else + UNUSED_PARAM(pluginPath); + UNUSED_PARAM(plugin); + return false; +#endif } static bool isOldWindowsMediaPlayerPlugin(const PluginModuleInfo& plugin) diff --git a/Source/WebKit2/UIProcess/WebContext.cpp b/Source/WebKit2/UIProcess/WebContext.cpp index b6258ece1..6987405be 100644 --- a/Source/WebKit2/UIProcess/WebContext.cpp +++ b/Source/WebKit2/UIProcess/WebContext.cpp @@ -147,6 +147,7 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa , m_initialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicyAlways) #endif , m_processTerminationEnabled(true) + , m_pluginWorkQueue("com.apple.CoreIPC.PluginQueue") { #if !LOG_DISABLED WebKit::initializeLogChannelsIfNecessary(); @@ -165,6 +166,11 @@ WebContext::WebContext(ProcessModel processModel, const String& injectedBundlePa WebContext::~WebContext() { + m_pluginWorkQueue.invalidate(); + + if (m_process && m_process->isValid()) + m_process->connection()->removeQueueClient(this); + ASSERT(contexts().find(this) != notFound); contexts().remove(contexts().find(this)); @@ -354,6 +360,8 @@ void WebContext::processDidFinishLaunching(WebProcessProxy* process) ASSERT_UNUSED(process, process == m_process); m_visitedLinkProvider.processDidFinishLaunching(); + + m_process->connection()->addQueueClient(this); // Sometimes the memorySampler gets initialized after process initialization has happened but before the process has finished launching // so check if it needs to be started here @@ -604,20 +612,39 @@ void WebContext::addVisitedLinkHash(LinkHash linkHash) m_visitedLinkProvider.addVisitedLink(linkHash); } -void WebContext::getPlugins(bool refresh, Vector<PluginInfo>& pluginInfos) +void WebContext::sendDidGetPlugins(uint64_t requestID, const Vector<PluginInfo>& pluginInfos) +{ + ASSERT(isMainThread()); + + Vector<PluginInfo> plugins(pluginInfos); + +#if PLATFORM(MAC) + // Add built-in PDF last, so that it's not used when a real plug-in is installed. + // NOTE: This has to be done on the main thread as it calls localizedString(). + if (!omitPDFSupport()) + plugins.append(BuiltInPDFView::pluginInfo()); +#endif + + process()->send(Messages::WebProcess::DidGetPlugins(requestID, plugins), 0); +} + +void WebContext::handleGetPlugins(uint64_t requestID, bool refresh) { if (refresh) m_pluginInfoStore.refresh(); + Vector<PluginInfo> pluginInfos; + Vector<PluginModuleInfo> plugins = m_pluginInfoStore.plugins(); for (size_t i = 0; i < plugins.size(); ++i) pluginInfos.append(plugins[i].info); -#if PLATFORM(MAC) - // Add built-in PDF last, so that it's not used when a real plug-in is installed. - if (!omitPDFSupport()) - pluginInfos.append(BuiltInPDFView::pluginInfo()); -#endif + RunLoop::main()->dispatch(bind(&WebContext::sendDidGetPlugins, this, requestID, pluginInfos)); +} + +void WebContext::getPlugins(CoreIPC::Connection*, uint64_t requestID, bool refresh) +{ + m_pluginWorkQueue.dispatch(bind(&WebContext::handleGetPlugins, this, requestID, refresh)); } void WebContext::getPluginPath(const String& mimeType, const String& urlString, String& pluginPath, bool& blocked) @@ -929,4 +956,17 @@ void WebContext::garbageCollectJavaScriptObjects() sendToAllProcesses(Messages::WebProcess::GarbageCollectJavaScriptObjects()); } +void WebContext::setJavaScriptGarbageCollectorTimerEnabled(bool flag) +{ + sendToAllProcesses(Messages::WebProcess::SetJavaScriptGarbageCollectorTimerEnabled(flag)); +} + +void WebContext::didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, bool& didHandleMessage) +{ + if (messageID.is<CoreIPC::MessageClassWebContext>()) { + didReceiveWebContextMessageOnConnectionWorkQueue(connection, messageID, arguments, didHandleMessage); + return; + } +} + } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebContext.h b/Source/WebKit2/UIProcess/WebContext.h index f94dc4a28..fa4567ff6 100644 --- a/Source/WebKit2/UIProcess/WebContext.h +++ b/Source/WebKit2/UIProcess/WebContext.h @@ -66,7 +66,7 @@ struct WebProcessCreationParameters; typedef GenericCallback<WKDictionaryRef> DictionaryCallback; -class WebContext : public APIObject { +class WebContext : public APIObject, private CoreIPC::Connection::QueueClient { public: static const Type APIType = TypeContext; @@ -194,6 +194,7 @@ public: void getWebCoreStatistics(PassRefPtr<DictionaryCallback>); void garbageCollectJavaScriptObjects(); + void setJavaScriptGarbageCollectorTimerEnabled(bool flag); #if PLATFORM(MAC) static bool omitPDFSupport(); @@ -216,7 +217,7 @@ private: void didUpdateHistoryTitle(uint64_t pageID, const String& title, const String& url, uint64_t frameID); // Plugins - void getPlugins(bool refresh, Vector<WebCore::PluginInfo>&); + void getPlugins(CoreIPC::Connection*, uint64_t requestID, bool refresh); void getPluginPath(const String& mimeType, const String& urlString, String& pluginPath, bool& blocked); #if !ENABLE(PLUGIN_PROCESS) void didGetSitesWithPluginData(const Vector<String>& sites, uint64_t callbackID); @@ -245,6 +246,9 @@ private: // Implemented in generated WebContextMessageReceiver.cpp void didReceiveWebContextMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); void didReceiveSyncWebContextMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&); + void didReceiveWebContextMessageOnConnectionWorkQueue(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, bool& didHandleMessage); + + virtual void didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, bool& didHandleMessage) OVERRIDE; static void languageChanged(void* context); void languageChanged(); @@ -257,6 +261,9 @@ private: String localStorageDirectory() const; String platformDefaultLocalStorageDirectory() const; + void handleGetPlugins(uint64_t requestID, bool refresh); + void sendDidGetPlugins(uint64_t requestID, const Vector<WebCore::PluginInfo>&); + ProcessModel m_processModel; // FIXME: In the future, this should be one or more WebProcessProxies. @@ -322,6 +329,8 @@ private: bool m_processTerminationEnabled; HashMap<uint64_t, RefPtr<DictionaryCallback> > m_dictionaryCallbacks; + + WorkQueue m_pluginWorkQueue; }; template<typename U> inline bool WebContext::sendToAllProcesses(const U& message) diff --git a/Source/WebKit2/UIProcess/WebContext.messages.in b/Source/WebKit2/UIProcess/WebContext.messages.in index a1397f055..955017293 100644 --- a/Source/WebKit2/UIProcess/WebContext.messages.in +++ b/Source/WebKit2/UIProcess/WebContext.messages.in @@ -32,7 +32,7 @@ messages -> WebContext { AddVisitedLinkHash(uint64_t linkHash) # Plugin messages. - GetPlugins(bool refresh) -> (Vector<WebCore::PluginInfo> plugins) + GetPlugins(uint64_t requestID, bool refresh) DispatchOnConnectionQueue GetPluginPath(WTF::String mimeType, WTF::String urlString) -> (WTF::String pluginPath, bool blocked) #if !ENABLE(PLUGIN_PROCESS) diff --git a/Source/WebKit2/UIProcess/WebIconDatabase.cpp b/Source/WebKit2/UIProcess/WebIconDatabase.cpp index 8016cfbd6..10804f702 100644 --- a/Source/WebKit2/UIProcess/WebIconDatabase.cpp +++ b/Source/WebKit2/UIProcess/WebIconDatabase.cpp @@ -62,7 +62,7 @@ void WebIconDatabase::invalidate() void WebIconDatabase::setDatabasePath(const String& path) { - if (m_iconDatabaseImpl && m_iconDatabaseImpl->isOpen()) { + if (isOpen()) { LOG_ERROR("Icon database already has a path and is already open. We don't currently support changing its path and reopening."); return; } @@ -190,6 +190,11 @@ Image* WebIconDatabase::imageForPageURL(const String& pageURL, const WebCore::In return m_iconDatabaseImpl->synchronousIconForPageURL(pageURL, iconSize); } +bool WebIconDatabase::isOpen() +{ + return m_iconDatabaseImpl && m_iconDatabaseImpl->isOpen(); +} + void WebIconDatabase::removeAllIcons() { m_iconDatabaseImpl->removeAllIcons(); diff --git a/Source/WebKit2/UIProcess/WebIconDatabase.h b/Source/WebKit2/UIProcess/WebIconDatabase.h index b74c21086..7ae3fdce0 100644 --- a/Source/WebKit2/UIProcess/WebIconDatabase.h +++ b/Source/WebKit2/UIProcess/WebIconDatabase.h @@ -78,7 +78,8 @@ public: void getLoadDecisionForIconURL(const String&, uint64_t callbackID); WebCore::Image* imageForPageURL(const String&, const WebCore::IntSize& iconSize = WebCore::IntSize(32, 32)); - + bool isOpen(); + void removeAllIcons(); void checkIntegrityBeforeOpening(); void close(); diff --git a/Source/WebKit2/UIProcess/WebLoaderClient.cpp b/Source/WebKit2/UIProcess/WebLoaderClient.cpp index 5a7f71766..92750124e 100644 --- a/Source/WebKit2/UIProcess/WebLoaderClient.cpp +++ b/Source/WebKit2/UIProcess/WebLoaderClient.cpp @@ -272,15 +272,15 @@ void WebLoaderClient::didFailToInitializePlugin(WebPageProxy* page, const String if (!m_client.pluginDidFail) return; - m_client.pluginDidFail(toAPI(page), kWKErrorCodeCannotLoadPlugIn, toAPI(mimeType.impl()), m_client.clientInfo); + m_client.pluginDidFail(toAPI(page), kWKErrorCodeCannotLoadPlugIn, toAPI(mimeType.impl()), 0, 0, m_client.clientInfo); } -void WebLoaderClient::didBlockInsecurePluginVersion(WebPageProxy* page, const String& mimeType) +void WebLoaderClient::didBlockInsecurePluginVersion(WebPageProxy* page, const String& mimeType, const String& pluginIdentifier, const String& pluginVersion) { if (!m_client.pluginDidFail) return; - m_client.pluginDidFail(toAPI(page), kWKErrorCodeInsecurePlugInVersion, toAPI(mimeType.impl()), m_client.clientInfo); + m_client.pluginDidFail(toAPI(page), kWKErrorCodeInsecurePlugInVersion, toAPI(mimeType.impl()), toAPI(pluginIdentifier.impl()), toAPI(pluginVersion.impl()), m_client.clientInfo); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebLoaderClient.h b/Source/WebKit2/UIProcess/WebLoaderClient.h index a78788d76..8cf687b97 100644 --- a/Source/WebKit2/UIProcess/WebLoaderClient.h +++ b/Source/WebKit2/UIProcess/WebLoaderClient.h @@ -87,7 +87,7 @@ public: void willGoToBackForwardListItem(WebPageProxy*, WebBackForwardListItem*, APIObject*); void didFailToInitializePlugin(WebPageProxy*, const String& mimeType); - void didBlockInsecurePluginVersion(WebPageProxy*, const String& mimeType); + void didBlockInsecurePluginVersion(WebPageProxy*, const String& mimeType, const String& pluginIdentifier, const String& pluginVersion); }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/WebPageProxy.cpp b/Source/WebKit2/UIProcess/WebPageProxy.cpp index ca11b64ca..e11daf16e 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit2/UIProcess/WebPageProxy.cpp @@ -1021,7 +1021,9 @@ static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b) FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks(); #if PLATFORM(MAC) - return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.modifiers(), b.timestamp(), b.directionInvertedFromDevice()); + FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta(); + + return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.directionInvertedFromDevice(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.scrollCount(), mergedUnacceleratedScrollingDelta, b.modifiers(), b.timestamp()); #else return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp()); #endif @@ -3621,9 +3623,20 @@ void WebPageProxy::didFailToInitializePlugin(const String& mimeType) m_loaderClient.didFailToInitializePlugin(this, mimeType); } -void WebPageProxy::didBlockInsecurePluginVersion(const String& mimeType) +void WebPageProxy::didBlockInsecurePluginVersion(const String& mimeType, const String& urlString) { - m_loaderClient.didBlockInsecurePluginVersion(this, mimeType); + String pluginIdentifier; + String pluginVersion; + String newMimeType = mimeType; + +#if PLATFORM(MAC) + PluginModuleInfo plugin = m_process->context()->pluginInfoStore().findPlugin(newMimeType, KURL(KURL(), urlString)); + + pluginIdentifier = plugin.bundleIdentifier; + pluginVersion = plugin.versionString; +#endif + + m_loaderClient.didBlockInsecurePluginVersion(this, newMimeType, pluginIdentifier, pluginVersion); } bool WebPageProxy::willHandleHorizontalScrollEvents() const diff --git a/Source/WebKit2/UIProcess/WebPageProxy.h b/Source/WebKit2/UIProcess/WebPageProxy.h index ef331fc7d..dc9994f1a 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.h +++ b/Source/WebKit2/UIProcess/WebPageProxy.h @@ -745,7 +745,7 @@ private: void didChangeScrollOffsetPinningForMainFrame(bool pinnedToLeftSide, bool pinnedToRightSide); void didChangePageCount(unsigned); void didFailToInitializePlugin(const String& mimeType); - void didBlockInsecurePluginVersion(const String& mimeType); + void didBlockInsecurePluginVersion(const String& mimeType, const String& urlString); void setCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) { m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; } void reattachToWebProcess(); diff --git a/Source/WebKit2/UIProcess/WebPageProxy.messages.in b/Source/WebKit2/UIProcess/WebPageProxy.messages.in index 4c48a3cd8..faec555e1 100644 --- a/Source/WebKit2/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit2/UIProcess/WebPageProxy.messages.in @@ -66,7 +66,7 @@ messages -> WebPageProxy { DidChangeScrollOffsetPinningForMainFrame(bool hasHorizontalScrollbar, bool hasVerticalScrollbar) DidChangePageCount(unsigned pageCount); DidFailToInitializePlugin(WTF::String mimeType) - DidBlockInsecurePluginVersion(WTF::String mimeType) + DidBlockInsecurePluginVersion(WTF::String mimeType, WTF::String urlString) SetCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) #if USE(TILED_BACKING_STORE) diff --git a/Source/WebKit2/UIProcess/WebProcessProxy.h b/Source/WebKit2/UIProcess/WebProcessProxy.h index 0cc1c6168..8e768bfb6 100644 --- a/Source/WebKit2/UIProcess/WebProcessProxy.h +++ b/Source/WebKit2/UIProcess/WebProcessProxy.h @@ -47,7 +47,7 @@ namespace WebCore { namespace WebKit { -#if PLATFORM(MAC) +#if USE(SECURITY_FRAMEWORK) class SecItemRequestData; class SecItemResponseData; #endif @@ -138,7 +138,7 @@ private: void getPluginProcessConnection(const String& pluginPath, PassRefPtr<Messages::WebProcessProxy::GetPluginProcessConnection::DelayedReply>); void pluginSyncMessageSendTimedOut(const String& pluginPath); #endif -#if PLATFORM(MAC) +#if USE(SECURITY_FRAMEWORK) void secItemRequest(CoreIPC::Connection*, uint64_t requestID, const SecItemRequestData&); void secKeychainItemRequest(CoreIPC::Connection*, uint64_t requestID, const SecKeychainItemRequestData&); #endif diff --git a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm index bcdfbc272..5c6c73ce2 100644 --- a/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm +++ b/Source/WebKit2/UIProcess/mac/WebInspectorProxyMac.mm @@ -56,6 +56,7 @@ static const CGFloat windowContentBorderThickness = 55; @interface WKWebInspectorProxyObjCAdapter () - (id)initWithWebInspectorProxy:(WebInspectorProxy*)inspectorProxy; +- (void)close; @end @@ -78,6 +79,11 @@ static const CGFloat windowContentBorderThickness = 55; return self; } +- (void)close +{ + _inspectorProxy = 0; +} + - (void)windowWillClose:(NSNotification *)notification { static_cast<WebInspectorProxy*>(_inspectorProxy)->close(); @@ -85,7 +91,16 @@ static const CGFloat windowContentBorderThickness = 55; - (void)inspectedViewFrameDidChange:(NSNotification *)notification { - static_cast<WebInspectorProxy*>(_inspectorProxy)->inspectedViewFrameDidChange(); + // Resizing the views while inside this notification can lead to bad results when entering + // or exiting full screen. To avoid that we need to perform the work after a delay. We only + // depend on this for enforcing the height constraints, so a small delay isn't terrible. Most + // of the time the views will already have the correct frames because of autoresizing masks. + + dispatch_after(DISPATCH_TIME_NOW, dispatch_get_current_queue(), ^{ + if (!_inspectorProxy) + return; + static_cast<WebInspectorProxy*>(_inspectorProxy)->inspectedViewFrameDidChange(); + }); } @end @@ -143,6 +158,7 @@ void WebInspectorProxy::createInspectorWindow() NSView *contentView = [window contentView]; [m_inspectorView.get() setFrame:[contentView bounds]]; + [m_inspectorView.get() setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [contentView addSubview:m_inspectorView.get()]; // Center the window initially before setting the frame autosave name so that the window will be in a good @@ -173,7 +189,6 @@ WebPageProxy* WebInspectorProxy::platformCreateInspectorPage() ASSERT(m_inspectorView); [m_inspectorView.get() setDrawsBackground:NO]; - [m_inspectorView.get() setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; m_inspectorProxyObjCAdapter.adoptNS([[WKWebInspectorProxyObjCAdapter alloc] initWithWebInspectorProxy:this]); @@ -207,6 +222,7 @@ void WebInspectorProxy::platformDidClose() m_inspectorView = 0; + [m_inspectorProxyObjCAdapter.get() close]; m_inspectorProxyObjCAdapter = 0; } @@ -267,6 +283,8 @@ void WebInspectorProxy::platformAttach() NSRect inspectedViewFrame = [inspectedView frame]; [m_inspectorView.get() setFrame:NSMakeRect(NSMinX(inspectedViewFrame), 0, NSWidth(inspectedViewFrame), inspectorPageGroup()->preferences()->inspectorAttachedHeight())]; + [m_inspectorView.get() setAutoresizingMask:NSViewWidthSizable | NSViewMaxYMargin]; + // Start out hidden if we are not visible yet. When platformOpen is called, hidden will be set to NO. [m_inspectorView.get() setHidden:!m_isVisible]; diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp index 6e41c8b39..3ff4f273a 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.cpp @@ -23,6 +23,7 @@ #include "WKRetainPtr.h" #include "WKStringQt.h" +#include "qquickwebview_p_p.h" #include "qwebpermissionrequest_p.h" #include <QtQml/QQmlComponent> #include <QtQml/QQmlContext> @@ -32,8 +33,9 @@ namespace WebKit { -QtDialogRunner::QtDialogRunner() +QtDialogRunner::QtDialogRunner(QQuickWebView* webView) : QEventLoop() + , m_webView(webView) , m_wasAccepted(false) { } @@ -42,30 +44,62 @@ QtDialogRunner::~QtDialogRunner() { } -class DialogContextObject : public QObject { +// All dialogs need a way to support the state of the +// dialog being done/finished/dismissed. This is handled +// in the dialog base context. +class DialogContextBase : public QObject { + Q_OBJECT + +public: + DialogContextBase() + : QObject() + , m_dismissed(false) + { + } + +public slots: + // Allows clients to call dismiss() directly, while also + // being able to hook up signals to automatically also + // dismiss the dialog since it's a slot. + + void dismiss() + { + m_dismissed = true; + emit dismissed(); + } + +signals: + void dismissed(); + +private: + // We store the dismissed state so that run() can check to see if a + // dialog has already been dismissed before spinning an event loop. + bool m_dismissed; + friend void QtDialogRunner::run(); +}; + +class DialogContextObject : public DialogContextBase { Q_OBJECT Q_PROPERTY(QString message READ message CONSTANT) Q_PROPERTY(QString defaultValue READ defaultValue CONSTANT) public: DialogContextObject(const QString& message, const QString& defaultValue = QString()) - : QObject() + : DialogContextBase() , m_message(message) , m_defaultValue(defaultValue) { + connect(this, SIGNAL(accepted(QString)), SLOT(dismiss())); + connect(this, SIGNAL(rejected()), SLOT(dismiss())); } QString message() const { return m_message; } QString defaultValue() const { return m_defaultValue; } public slots: - void dismiss() { emit dismissed(); } - void accept() { emit accepted(); } - void accept(const QString& result) { emit accepted(result); } + void accept(const QString& result = QString()) { emit accepted(result); } void reject() { emit rejected(); } signals: - void dismissed(); - void accepted(); void accepted(const QString& result); void rejected(); @@ -74,17 +108,19 @@ private: QString m_defaultValue; }; -class BaseAuthenticationContextObject : public QObject { +class BaseAuthenticationContextObject : public DialogContextBase { Q_OBJECT Q_PROPERTY(QString hostname READ hostname CONSTANT) Q_PROPERTY(QString prefilledUsername READ prefilledUsername CONSTANT) public: BaseAuthenticationContextObject(const QString& hostname, const QString& prefilledUsername) - : QObject() + : DialogContextBase() , m_hostname(hostname) , m_prefilledUsername(prefilledUsername) { + connect(this, SIGNAL(accepted(QString, QString)), SLOT(dismiss())); + connect(this, SIGNAL(rejected()), SLOT(dismiss())); } QString hostname() const { return m_hostname; } @@ -137,15 +173,17 @@ private: quint16 m_port; }; -class CertificateVerificationDialogContextObject : public QObject { +class CertificateVerificationDialogContextObject : public DialogContextBase { Q_OBJECT Q_PROPERTY(QString hostname READ hostname CONSTANT) public: CertificateVerificationDialogContextObject(const QString& hostname) - : QObject() + : DialogContextBase() , m_hostname(hostname) { + connect(this, SIGNAL(accepted()), SLOT(dismiss())); + connect(this, SIGNAL(rejected()), SLOT(dismiss())); } QString hostname() const { return m_hostname; } @@ -162,17 +200,19 @@ private: QString m_hostname; }; -class FilePickerContextObject : public QObject { +class FilePickerContextObject : public DialogContextBase { Q_OBJECT Q_PROPERTY(QStringList fileList READ fileList CONSTANT) Q_PROPERTY(bool allowMultipleFiles READ allowMultipleFiles CONSTANT) public: FilePickerContextObject(const QStringList& selectedFiles, bool allowMultiple) - : QObject() + : DialogContextBase() , m_allowMultiple(allowMultiple) , m_fileList(selectedFiles) { + connect(this, SIGNAL(fileSelected(QStringList)), SLOT(dismiss())); + connect(this, SIGNAL(rejected()), SLOT(dismiss())); } QStringList fileList() const { return m_fileList; } @@ -198,7 +238,7 @@ private: QStringList m_fileList; }; -class DatabaseQuotaDialogContextObject : public QObject { +class DatabaseQuotaDialogContextObject : public DialogContextBase { Q_OBJECT Q_PROPERTY(QString databaseName READ databaseName CONSTANT) Q_PROPERTY(QString displayName READ displayName CONSTANT) @@ -210,7 +250,7 @@ class DatabaseQuotaDialogContextObject : public QObject { public: DatabaseQuotaDialogContextObject(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) - : QObject() + : DialogContextBase() , m_databaseName(databaseName) , m_displayName(displayName) , m_currentQuota(currentQuota) @@ -224,6 +264,9 @@ public: m_securityOrigin.setScheme(WKStringCopyQString(scheme.get())); m_securityOrigin.setHost(WKStringCopyQString(host.get())); m_securityOrigin.setPort(static_cast<int>(WKSecurityOriginGetPort(securityOrigin))); + + connect(this, SIGNAL(accepted(quint64)), SLOT(dismiss())); + connect(this, SIGNAL(rejected()), SLOT(dismiss())); } QString databaseName() const { return m_databaseName; } @@ -252,118 +295,136 @@ private: QtWebSecurityOrigin m_securityOrigin; }; -bool QtDialogRunner::initForAlert(QQmlComponent* component, QQuickItem* dialogParent, const QString& message) +void QtDialogRunner::run() { - DialogContextObject* contextObject = new DialogContextObject(message); - if (!createDialog(component, dialogParent, contextObject)) - return false; + DialogContextBase* context = static_cast<DialogContextBase*>(m_dialogContext->contextObject()); - connect(contextObject, SIGNAL(dismissed()), SLOT(quit())); - return true; + // We may have already been dismissed as part of Component.onCompleted() + if (context->m_dismissed) + return; + + connect(context, SIGNAL(dismissed()), SLOT(quit())); + + QQuickWebViewPrivate* webViewPrivate = QQuickWebViewPrivate::get(m_webView); + + // FIXME: Change the way we disable mouse and touch events to use the + // concept of suspending instead (in this case event processing). + webViewPrivate->disableMouseEvents(); + webViewPrivate->m_dialogActive = true; + exec(); // Spin the event loop + webViewPrivate->m_dialogActive = false; + webViewPrivate->enableMouseEvents(); } -bool QtDialogRunner::initForConfirm(QQmlComponent* component, QQuickItem* dialogParent, const QString& message) +bool QtDialogRunner::initForAlert(const QString& message) { + QQmlComponent* component = m_webView->experimental()->alertDialog(); + if (!component) + return false; + DialogContextObject* contextObject = new DialogContextObject(message); - if (!createDialog(component, dialogParent, contextObject)) + + return createDialog(component, contextObject); +} + +bool QtDialogRunner::initForConfirm(const QString& message) +{ + QQmlComponent* component = m_webView->experimental()->confirmDialog(); + if (!component) return false; - connect(contextObject, SIGNAL(accepted()), SLOT(onAccepted())); - connect(contextObject, SIGNAL(accepted()), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + DialogContextObject* contextObject = new DialogContextObject(message); + connect(contextObject, SIGNAL(accepted(QString)), SLOT(onAccepted())); + + return createDialog(component, contextObject); } -bool QtDialogRunner::initForPrompt(QQmlComponent* component, QQuickItem* dialogParent, const QString& message, const QString& defaultValue) +bool QtDialogRunner::initForPrompt(const QString& message, const QString& defaultValue) { - DialogContextObject* contextObject = new DialogContextObject(message, defaultValue); - if (!createDialog(component, dialogParent, contextObject)) + QQmlComponent* component = m_webView->experimental()->promptDialog(); + if (!component) return false; + DialogContextObject* contextObject = new DialogContextObject(message, defaultValue); connect(contextObject, SIGNAL(accepted(QString)), SLOT(onAccepted(QString))); - connect(contextObject, SIGNAL(accepted(QString)), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + + return createDialog(component, contextObject); } -bool QtDialogRunner::initForAuthentication(QQmlComponent* component, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername) +bool QtDialogRunner::initForAuthentication(const QString& hostname, const QString& realm, const QString& prefilledUsername) { - HttpAuthenticationDialogContextObject* contextObject = new HttpAuthenticationDialogContextObject(hostname, realm, prefilledUsername); - if (!createDialog(component, dialogParent, contextObject)) + QQmlComponent* component = m_webView->experimental()->authenticationDialog(); + if (!component) return false; + HttpAuthenticationDialogContextObject* contextObject = new HttpAuthenticationDialogContextObject(hostname, realm, prefilledUsername); connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(onAuthenticationAccepted(QString, QString))); - connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + return createDialog(component, contextObject); } -bool QtDialogRunner::initForProxyAuthentication(QQmlComponent* component, QQuickItem* dialogParent, const QString& hostname, uint16_t port, const QString& prefilledUsername) +bool QtDialogRunner::initForProxyAuthentication(const QString& hostname, uint16_t port, const QString& prefilledUsername) { - ProxyAuthenticationDialogContextObject* contextObject = new ProxyAuthenticationDialogContextObject(hostname, port, prefilledUsername); - if (!createDialog(component, dialogParent, contextObject)) + QQmlComponent* component = m_webView->experimental()->proxyAuthenticationDialog(); + if (!component) return false; + ProxyAuthenticationDialogContextObject* contextObject = new ProxyAuthenticationDialogContextObject(hostname, port, prefilledUsername); connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(onAuthenticationAccepted(QString, QString))); - connect(contextObject, SIGNAL(accepted(QString, QString)), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + return createDialog(component, contextObject); } -bool QtDialogRunner::initForCertificateVerification(QQmlComponent* component, QQuickItem* dialogParent, const QString& hostname) +bool QtDialogRunner::initForCertificateVerification(const QString& hostname) { - CertificateVerificationDialogContextObject* contextObject = new CertificateVerificationDialogContextObject(hostname); - if (!createDialog(component, dialogParent, contextObject)) + QQmlComponent* component = m_webView->experimental()->certificateVerificationDialog(); + if (!component) return false; + CertificateVerificationDialogContextObject* contextObject = new CertificateVerificationDialogContextObject(hostname); connect(contextObject, SIGNAL(accepted()), SLOT(onAccepted())); - connect(contextObject, SIGNAL(accepted()), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + return createDialog(component, contextObject); } -bool QtDialogRunner::initForFilePicker(QQmlComponent* component, QQuickItem* dialogParent, const QStringList& selectedFiles, bool allowMultiple) +bool QtDialogRunner::initForFilePicker(const QStringList& selectedFiles, bool allowMultiple) { - FilePickerContextObject* contextObject = new FilePickerContextObject(selectedFiles, allowMultiple); - if (!createDialog(component, dialogParent, contextObject)) + QQmlComponent* component = m_webView->experimental()->filePicker(); + if (!component) return false; + FilePickerContextObject* contextObject = new FilePickerContextObject(selectedFiles, allowMultiple); connect(contextObject, SIGNAL(fileSelected(QStringList)), SLOT(onFileSelected(QStringList))); - connect(contextObject, SIGNAL(fileSelected(QStringList)), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + return createDialog(component, contextObject); } -bool QtDialogRunner::initForDatabaseQuotaDialog(QQmlComponent* component, QQuickItem* dialogParent, const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) +bool QtDialogRunner::initForDatabaseQuotaDialog(const QString& databaseName, const QString& displayName, WKSecurityOriginRef securityOrigin, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage) { - DatabaseQuotaDialogContextObject* contextObject = new DatabaseQuotaDialogContextObject(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); - if (!createDialog(component, dialogParent, contextObject)) + QQmlComponent* component = m_webView->experimental()->databaseQuotaDialog(); + if (!component) return false; + DatabaseQuotaDialogContextObject* contextObject = new DatabaseQuotaDialogContextObject(databaseName, displayName, securityOrigin, currentQuota, currentOriginUsage, currentDatabaseUsage, expectedUsage); connect(contextObject, SIGNAL(accepted(quint64)), SLOT(onDatabaseQuotaAccepted(quint64))); - connect(contextObject, SIGNAL(accepted(quint64)), SLOT(quit())); - connect(contextObject, SIGNAL(rejected()), SLOT(quit())); - return true; + return createDialog(component, contextObject); } -bool QtDialogRunner::createDialog(QQmlComponent* component, QQuickItem* dialogParent, QObject* contextObject) +bool QtDialogRunner::createDialog(QQmlComponent* component, QObject* contextObject) { QQmlContext* baseContext = component->creationContext(); if (!baseContext) - baseContext = QQmlEngine::contextForObject(dialogParent); + baseContext = QQmlEngine::contextForObject(m_webView); m_dialogContext = adoptPtr(new QQmlContext(baseContext)); - // This makes both "message" and "model.message" work for the dialog, just like QtQuick's ListView delegates. + // This makes both "message" and "model.message" work for the dialog, + // just like QtQuick's ListView delegates. contextObject->setParent(m_dialogContext.get()); m_dialogContext->setContextProperty(QLatin1String("model"), contextObject); m_dialogContext->setContextObject(contextObject); - QObject* object = component->create(m_dialogContext.get()); + QObject* object = component->beginCreate(m_dialogContext.get()); if (!object) { m_dialogContext.clear(); return false; @@ -376,10 +437,48 @@ bool QtDialogRunner::createDialog(QQmlComponent* component, QQuickItem* dialogPa return false; } - m_dialog->setParentItem(dialogParent); + QQuickWebViewPrivate::get(m_webView)->addAttachedPropertyTo(m_dialog.get()); + m_dialog->setParentItem(m_webView); + + // Only fully create the component once we've set both a parent + // and the needed context and attached properties, so that dialogs + // can do useful stuff in their Component.onCompleted() method. + component->completeCreate(); + + // FIXME: As part of completeCreate, the bindings of the item will be + // evaluated, but for some reason doing mapToItem/mapFromItem in a + // binding will not work as expected, even if we at binding evaluation + // time have the parent and all the way up to the root QML item. + // As a workaround you can set whichever property you need in + // Component.onCompleted, even to a binding using Qt.bind(). + return true; } +void QtDialogRunner::onAccepted(const QString& result) +{ + m_wasAccepted = true; + m_result = result; +} + +void QtDialogRunner::onAuthenticationAccepted(const QString& username, const QString& password) +{ + m_username = username; + m_password = password; +} + +void QtDialogRunner::onFileSelected(const QStringList& filePaths) +{ + m_wasAccepted = true; + m_filepaths = filePaths; +} + +void QtDialogRunner::onDatabaseQuotaAccepted(quint64 quota) +{ + m_wasAccepted = true; + m_databaseQuota = quota; +} + } // namespace WebKit #include "QtDialogRunner.moc" diff --git a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h index eb229ec84..c04043d34 100644 --- a/Source/WebKit2/UIProcess/qt/QtDialogRunner.h +++ b/Source/WebKit2/UIProcess/qt/QtDialogRunner.h @@ -22,6 +22,7 @@ #define QtDialogRunner_h #include "WKSecurityOrigin.h" +#include "qquickwebview_p.h" #include <QtCore/QEventLoop> #include <QtCore/QStringList> #include <wtf/OwnPtr.h> @@ -38,17 +39,19 @@ class QtDialogRunner : public QEventLoop { Q_OBJECT public: - QtDialogRunner(); + QtDialogRunner(QQuickWebView*); virtual ~QtDialogRunner(); - bool initForAlert(QQmlComponent*, QQuickItem* dialogParent, const QString& message); - bool initForConfirm(QQmlComponent*, QQuickItem* dialogParent, const QString& message); - bool initForPrompt(QQmlComponent*, QQuickItem* dialogParent, const QString& message, const QString& defaultValue); - bool initForAuthentication(QQmlComponent*, QQuickItem* dialogParent, const QString& hostname, const QString& realm, const QString& prefilledUsername); - bool initForCertificateVerification(QQmlComponent*, QQuickItem*, const QString& hostname); - bool initForProxyAuthentication(QQmlComponent*, QQuickItem*, const QString& hostname, uint16_t port, const QString& prefilledUsername); - bool initForFilePicker(QQmlComponent*, QQuickItem*, const QStringList& selectedFiles, bool allowMultiple); - bool initForDatabaseQuotaDialog(QQmlComponent*, QQuickItem*, const QString& databaseName, const QString& displayName, WKSecurityOriginRef, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage); + bool initForAlert(const QString& message); + bool initForConfirm(const QString& message); + bool initForPrompt(const QString& message, const QString& defaultValue); + bool initForAuthentication(const QString& hostname, const QString& realm, const QString& prefilledUsername); + bool initForCertificateVerification(const QString& hostname); + bool initForProxyAuthentication(const QString& hostname, uint16_t port, const QString& prefilledUsername); + bool initForFilePicker(const QStringList& selectedFiles, bool allowMultiple); + bool initForDatabaseQuotaDialog(const QString& databaseName, const QString& displayName, WKSecurityOriginRef, quint64 currentQuota, quint64 currentOriginUsage, quint64 currentDatabaseUsage, quint64 expectedUsage); + + void run(); QQuickItem* dialog() const { return m_dialog.get(); } @@ -63,33 +66,15 @@ public: QStringList filePaths() const { return m_filepaths; } public slots: - void onAccepted(const QString& result = QString()) - { - m_wasAccepted = true; - m_result = result; - } - - void onAuthenticationAccepted(const QString& username, const QString& password) - { - m_username = username; - m_password = password; - } - - void onFileSelected(const QStringList& filePaths) - { - m_wasAccepted = true; - m_filepaths = filePaths; - } - - void onDatabaseQuotaAccepted(quint64 quota) - { - m_wasAccepted = true; - m_databaseQuota = quota; - } + void onAccepted(const QString& result = QString()); + void onAuthenticationAccepted(const QString& username, const QString& password); + void onFileSelected(const QStringList& filePaths); + void onDatabaseQuotaAccepted(quint64 quota); private: - bool createDialog(QQmlComponent*, QQuickItem* dialogParent, QObject* contextObject); + bool createDialog(QQmlComponent*, QObject* contextObject); + QQuickWebView* m_webView; OwnPtr<QQmlContext> m_dialogContext; OwnPtr<QQuickItem> m_dialog; QString m_result; diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp index 949a5918c..eb3c5a8d2 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp +++ b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.cpp @@ -192,6 +192,13 @@ bool QtViewportInteractionEngine::animateItemRectVisible(const QRectF& itemRect) if (itemRect == currentItemRectVisible) return false; + // FIXME: Investigate why that animation doesn't run when we are unfocused. + if (!m_viewport->isVisible() || !m_viewport->hasFocus()) { + // Apply the end result immediately when we are non-visible. + setItemRectVisible(itemRect); + return true; + } + m_scaleAnimation->setDuration(kScaleAnimationDurationMillis); m_scaleAnimation->setEasingCurve(QEasingCurve::OutCubic); @@ -254,36 +261,6 @@ static inline QPointF boundPosition(const QPointF minPosition, const QPointF& po qBound(minPosition.y(), position.y(), maxPosition.y())); } -void QtViewportInteractionEngine::wheelEvent(QWheelEvent* ev) -{ - if (scrollAnimationActive() || scaleAnimationActive() || pinchGestureActive()) - return; // Ignore. - - - // A normal scroll-tick should have a delta of 120 (1/8) degrees. Convert this to - // local standard scroll step of 3 lines of 20 pixels. - static const int cDefaultQtScrollStep = 20; - static const int wheelScrollLines = 3; - const int wheelTick = wheelScrollLines * cDefaultQtScrollStep; - - int pixelDelta = ev->delta() * (wheelTick / 120.f); - - QPointF newPosition = m_viewport->contentPos(); - - if (ev->orientation() == Qt::Horizontal) - newPosition.rx() -= pixelDelta; - else - newPosition.ry() -= pixelDelta; - - QRectF endPosRange = computePosRangeForItemAtScale(m_content->contentsScale()); - - QPointF currentPosition = m_viewport->contentPos(); - newPosition = boundPosition(endPosRange.topLeft(), newPosition, endPosRange.bottomRight()); - m_viewport->setContentPos(newPosition); - - emit contentViewportChanged(currentPosition - newPosition); -} - void QtViewportInteractionEngine::pagePositionRequest(const QPoint& pagePosition) { // Ignore the request if suspended. Can only happen due to delay in event delivery. diff --git a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h index 8a720f34b..accfc6ad7 100644 --- a/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h +++ b/Source/WebKit2/UIProcess/qt/QtViewportInteractionEngine.h @@ -35,7 +35,7 @@ class QQuickWebView; class QWheelEvent; QT_END_NAMESPACE -class QWebViewportInfo; +class QWebKitTest; namespace WebKit { @@ -65,7 +65,6 @@ public: void setItemRectVisible(const QRectF&); bool animateItemRectVisible(const QRectF&); - void wheelEvent(QWheelEvent*); void pagePositionRequest(const QPoint& pos); void touchBegin(); void touchEnd(); @@ -116,7 +115,7 @@ private Q_SLOTS: private: friend class ViewportUpdateDeferrer; - friend class ::QWebViewportInfo; + friend class ::QWebKitTest; QQuickWebView* const m_viewport; QQuickWebPage* const m_content; diff --git a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp index 30d59c2a4..8239c5d21 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebContext.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebContext.cpp @@ -47,6 +47,7 @@ QtWebContext* QtWebContext::s_defaultContext = 0; static void initInspectorServer() { +#if ENABLE(INSPECTOR_SERVER) QString inspectorEnv = QString::fromUtf8(qgetenv("QTWEBKIT_INSPECTOR_SERVER")); if (!inspectorEnv.isEmpty()) { QString bindAddress = QLatin1String("127.0.0.1"); @@ -73,6 +74,7 @@ static void initInspectorServer() } else qWarning("Couldn't start the inspector server on bind address \"%s\" and port \"%d\". In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface).", qPrintable(bindAddress), port); } +#endif } static void globalInitialization() diff --git a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp index d94b634b3..c769c8b03 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebIconDatabaseClient.cpp @@ -45,7 +45,8 @@ QtWebIconDatabaseClient::QtWebIconDatabaseClient(QtWebContext *qtWebContext) m_contextId = qtWebContext->contextID(); // The setter calls the getter here as it triggers the startup of the icon database. WebContext* context = qtWebContext->context(); - context->setIconDatabasePath(context->iconDatabasePath()); + if (!context->iconDatabase()->isOpen()) + context->setIconDatabasePath(context->iconDatabasePath()); m_iconDatabase = context->iconDatabase(); WKIconDatabaseClient iconDatabaseClient; diff --git a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp index bbfab1a5a..c1ebaac14 100644 --- a/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp +++ b/Source/WebKit2/UIProcess/qt/QtWebPageEventHandler.cpp @@ -154,9 +154,6 @@ void QtWebPageEventHandler::handleWheelEvent(QWheelEvent* ev) { QTransform fromItemTransform = m_webPage->transformFromItem(); m_webPageProxy->handleWheelEvent(NativeWebWheelEvent(ev, fromItemTransform)); - // FIXME: Handle whether the page used the wheel event or not. - if (m_interactionEngine) - m_interactionEngine->wheelEvent(ev); } void QtWebPageEventHandler::handleHoverLeaveEvent(QHoverEvent* ev) diff --git a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp index 9f9100a54..648394b6f 100644 --- a/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp +++ b/Source/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp @@ -283,10 +283,13 @@ void WebPopupMenuProxyQt::createItem(QObject* contextObject) connect(contextObject, SIGNAL(acceptedWithOriginalIndex(int)), SLOT(hidePopupMenu()), Qt::QueuedConnection); connect(contextObject, SIGNAL(rejected()), SLOT(hidePopupMenu()), Qt::QueuedConnection); - QQuickWebViewPrivate::get(m_webView)->setViewInAttachedProperties(m_itemSelector.get()); - component->completeCreate(); - + QQuickWebViewPrivate::get(m_webView)->addAttachedPropertyTo(m_itemSelector.get()); m_itemSelector->setParentItem(m_webView); + + // Only fully create the component once we've set both a parent + // and the needed context and attached properties, so that the + // dialog can do useful stuff in Component.onCompleted(). + component->completeCreate(); } void WebPopupMenuProxyQt::createContext(QQmlComponent* component, QObject* contextObject) diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp index 20c5c4f86..5123346b5 100644 --- a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp @@ -60,16 +60,22 @@ void WebSoupRequestManagerProxy::registerURIScheme(const String& scheme) m_webContext->sendToAllProcessesRelaunchingThemIfNecessary(Messages::WebSoupRequestManager::RegisterURIScheme(scheme)); } -void WebSoupRequestManagerProxy::handleURIRequest(const WebData* requestData, const String& mimeType, uint64_t requestID) +void WebSoupRequestManagerProxy::didHandleURIRequest(const WebData* requestData, uint64_t contentLength, const String& mimeType, uint64_t requestID) { ASSERT(m_webContext); - m_webContext->sendToAllProcesses(Messages::WebSoupRequestManager::HandleURIRequest(requestData->dataReference(), mimeType, requestID)); + m_webContext->sendToAllProcesses(Messages::WebSoupRequestManager::DidHandleURIRequest(requestData->dataReference(), contentLength, mimeType, requestID)); +} + +void WebSoupRequestManagerProxy::didReceiveURIRequestData(const WebData* requestData, uint64_t requestID) +{ + ASSERT(m_webContext); + m_webContext->sendToAllProcesses(Messages::WebSoupRequestManager::DidReceiveURIRequestData(requestData->dataReference(), requestID)); } void WebSoupRequestManagerProxy::didReceiveURIRequest(const String& uriString, uint64_t requestID) { if (!m_client.didReceiveURIRequest(this, WebURL::create(uriString).get(), requestID)) - handleURIRequest(WebData::create(0, 0).get(), String(), requestID); + didHandleURIRequest(WebData::create(0, 0).get(), 0, String(), requestID); } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h index 2aa3e99f6..f43f7ce5c 100644 --- a/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h +++ b/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h @@ -50,7 +50,8 @@ public: void initializeClient(const WKSoupRequestManagerClient*); void registerURIScheme(const String& scheme); - void handleURIRequest(const WebData*, const String& mimeType, uint64_t requestID); + void didHandleURIRequest(const WebData*, uint64_t contentLength, const String& mimeType, uint64_t requestID); + void didReceiveURIRequestData(const WebData*, uint64_t requestID); void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); |
