summaryrefslogtreecommitdiff
path: root/Source/WebKit2/UIProcess/API
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-06-25 13:35:59 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-06-25 13:35:59 +0200
commit79ad030d505ccf79cf10aa9f8189ca3e2f61f6f4 (patch)
tree0287b1a69d84492c901e8bc820e635e7133809a0 /Source/WebKit2/UIProcess/API
parent682ab87480e7757346802ce7f54cfdbdfeb2339e (diff)
downloadqtwebkit-79ad030d505ccf79cf10aa9f8189ca3e2f61f6f4.tar.gz
Imported WebKit commit c4b613825abd39ac739a47d7b4410468fcef66dc (http://svn.webkit.org/repository/webkit/trunk@121147)
New snapshot that includes Win32 debug build fix (use SVGAllInOne)
Diffstat (limited to 'Source/WebKit2/UIProcess/API')
-rw-r--r--Source/WebKit2/UIProcess/API/C/WKAPICast.h4
-rw-r--r--Source/WebKit2/UIProcess/API/C/WKIntentData.cpp100
-rw-r--r--Source/WebKit2/UIProcess/API/C/WKIntentData.h47
-rw-r--r--Source/WebKit2/UIProcess/API/C/efl/WKAPICastEfl.h35
-rw-r--r--Source/WebKit2/UIProcess/API/C/efl/WKView.cpp36
-rw-r--r--Source/WebKit2/UIProcess/API/C/efl/WKView.h39
-rw-r--r--Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp8
-rw-r--r--Source/WebKit2/UIProcess/API/efl/PageClientImpl.h4
-rw-r--r--Source/WebKit2/UIProcess/API/efl/ewk_view.cpp8
-rw-r--r--Source/WebKit2/UIProcess/API/efl/ewk_view_private.h2
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp8
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h3
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp308
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h104
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.cpp318
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h130
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActionsPrivate.h31
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.cpp345
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h92
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItemPrivate.h30
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuPrivate.h31
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitDefines.h8
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp61
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h7
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp7
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp188
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h5
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp11
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h1
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h1
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml2
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt62
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types2
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am7
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp671
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h14
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFindController.cpp3
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp5
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp147
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp26
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h2
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/webkit2.h3
-rw-r--r--Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list1
-rw-r--r--Source/WebKit2/UIProcess/API/mac/PageClientImpl.h4
-rw-r--r--Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm8
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp17
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h4
-rw-r--r--Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h1
-rw-r--r--Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_colorChooser.qml94
-rw-r--r--Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/colorChooser.html19
50 files changed, 2994 insertions, 70 deletions
diff --git a/Source/WebKit2/UIProcess/API/C/WKAPICast.h b/Source/WebKit2/UIProcess/API/C/WKAPICast.h
index 9bc9ea607..816f8f1ae 100644
--- a/Source/WebKit2/UIProcess/API/C/WKAPICast.h
+++ b/Source/WebKit2/UIProcess/API/C/WKAPICast.h
@@ -368,4 +368,8 @@ inline ProxyingRefPtr<WebGrammarDetail> toAPI(const WebCore::GrammarDetail& gram
#include "WKAPICastSoup.h"
#endif
+#if defined(BUILDING_EFL__)
+#include "WKAPICastEfl.h"
+#endif
+
#endif // WKAPICast_h
diff --git a/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp b/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp
new file mode 100644
index 000000000..a42f530ac
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/WKIntentData.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WKIntentData.h"
+
+#include "ImmutableArray.h"
+#include "ImmutableDictionary.h"
+#include "WKAPICast.h"
+
+#if ENABLE(WEB_INTENTS)
+#include "WebIntentData.h"
+#endif
+
+using namespace WebKit;
+
+WKTypeID WKIntentDataGetTypeID()
+{
+#if ENABLE(WEB_INTENTS)
+ return toAPI(WebIntentData::APIType);
+#else
+ return 0;
+#endif
+}
+
+WKStringRef WKIntentDataCopyAction(WKIntentDataRef intentRef)
+{
+#if ENABLE(WEB_INTENTS)
+ return toCopiedAPI(toImpl(intentRef)->action());
+#else
+ return 0;
+#endif
+}
+
+WKStringRef WKIntentDataCopyType(WKIntentDataRef intentRef)
+{
+#if ENABLE(WEB_INTENTS)
+ return toCopiedAPI(toImpl(intentRef)->payloadType());
+#else
+ return 0;
+#endif
+}
+
+WKURLRef WKIntentDataCopyService(WKIntentDataRef intentRef)
+{
+#if ENABLE(WEB_INTENTS)
+ return toCopiedURLAPI(toImpl(intentRef)->service());
+#else
+ return 0;
+#endif
+}
+
+WKArrayRef WKIntentDataCopySuggestions(WKIntentDataRef intentRef)
+{
+#if ENABLE(WEB_INTENTS)
+ return toAPI(toImpl(intentRef)->suggestions().leakRef());
+#else
+ return 0;
+#endif
+}
+
+WKStringRef WKIntentDataCopyExtra(WKIntentDataRef intentRef, WKStringRef key)
+{
+#if ENABLE(WEB_INTENTS)
+ return toCopiedAPI(toImpl(intentRef)->extra(toWTFString(key)));
+#else
+ return 0;
+#endif
+}
+
+WKDictionaryRef WKIntentDataCopyExtras(WKIntentDataRef intentRef)
+{
+#if ENABLE(WEB_INTENTS)
+ return toAPI(toImpl(intentRef)->extras().leakRef());
+#else
+ return 0;
+#endif
+}
diff --git a/Source/WebKit2/UIProcess/API/C/WKIntentData.h b/Source/WebKit2/UIProcess/API/C/WKIntentData.h
new file mode 100644
index 000000000..030555b4b
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/WKIntentData.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WKIntentData_h
+#define WKIntentData_h
+
+#include <WebKit2/WKBase.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WK_EXPORT WKTypeID WKIntentDataGetTypeID();
+WK_EXPORT WKStringRef WKIntentDataCopyAction(WKIntentDataRef intentRef);
+WK_EXPORT WKStringRef WKIntentDataCopyType(WKIntentDataRef intentRef);
+WK_EXPORT WKURLRef WKIntentDataCopyService(WKIntentDataRef intentRef);
+WK_EXPORT WKArrayRef WKIntentDataCopySuggestions(WKIntentDataRef intentRef);
+WK_EXPORT WKStringRef WKIntentDataCopyExtra(WKIntentDataRef intentRef, WKStringRef key);
+WK_EXPORT WKDictionaryRef WKIntentDataCopyExtras(WKIntentDataRef intentRef);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WKIntentData_h
diff --git a/Source/WebKit2/UIProcess/API/C/efl/WKAPICastEfl.h b/Source/WebKit2/UIProcess/API/C/efl/WKAPICastEfl.h
new file mode 100644
index 000000000..5a068ef36
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/efl/WKAPICastEfl.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef WKAPICastEfl_h
+#define WKAPICastEfl_h
+
+#ifndef WKAPICast_h
+#error "Please #include \"WKAPICast.h\" instead of this file directly."
+#endif
+
+typedef struct _Evas_Object Evas_Object;
+
+namespace WebKit {
+
+WK_ADD_API_MAPPING(WKViewRef, Evas_Object)
+
+}
+
+#endif // WKAPICastEfl_h
diff --git a/Source/WebKit2/UIProcess/API/C/efl/WKView.cpp b/Source/WebKit2/UIProcess/API/C/efl/WKView.cpp
new file mode 100644
index 000000000..03f6930dd
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/efl/WKView.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "WKView.h"
+
+#include "WKAPICast.h"
+#include "ewk_view_private.h"
+
+using namespace WebKit;
+
+WKViewRef WKViewCreate(Evas* canvas, WKContextRef contextRef, WKPageGroupRef pageGroupRef)
+{
+ return toAPI(ewk_view_base_add(canvas, contextRef, pageGroupRef));
+}
+
+WKPageRef WKViewGetPage(WKViewRef viewRef)
+{
+ return toAPI(ewk_view_page_get(toImpl(viewRef)));
+}
diff --git a/Source/WebKit2/UIProcess/API/C/efl/WKView.h b/Source/WebKit2/UIProcess/API/C/efl/WKView.h
new file mode 100644
index 000000000..1a7961daa
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/efl/WKView.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef WKView_h
+#define WKView_h
+
+#include <WebKit2/WKBase.h>
+
+typedef struct _Evas Evas;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WK_EXPORT WKViewRef WKViewCreate(Evas* canvas, WKContextRef context, WKPageGroupRef pageGroup);
+
+WK_EXPORT WKPageRef WKViewGetPage(WKViewRef view);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WKView_h */
diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp
index 567548f5d..e69f87d28 100644
--- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp
+++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.cpp
@@ -205,6 +205,14 @@ PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPagePr
return 0;
}
+#if ENABLE(INPUT_TYPE_COLOR)
+PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&)
+{
+ notImplemented();
+ return 0;
+}
+#endif
+
void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator>, bool, bool)
{
notImplemented();
diff --git a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h
index a4dcd93e3..427ef5297 100644
--- a/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h
+++ b/Source/WebKit2/UIProcess/API/efl/PageClientImpl.h
@@ -84,6 +84,10 @@ private:
virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*);
virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*);
+#if ENABLE(INPUT_TYPE_COLOR)
+ virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor);
+#endif
+
virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool, bool);
#if USE(ACCELERATED_COMPOSITING)
virtual void enterAcceleratedCompositingMode(const LayerTreeContext&);
diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
index 01fd5e669..fe384e377 100644
--- a/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
+++ b/Source/WebKit2/UIProcess/API/efl/ewk_view.cpp
@@ -629,3 +629,11 @@ void ewk_view_image_data_set(Evas_Object* ewkView, void* imageData, const IntSiz
evas_object_image_size_set(smartData->image, size.width(), size.height());
evas_object_image_data_copy_set(smartData->image, imageData);
}
+
+WebPageProxy* ewk_view_page_get(const Evas_Object* ewkView)
+{
+ EWK_VIEW_SD_GET_OR_RETURN(ewkView, smartData, 0);
+ EWK_VIEW_PRIV_GET_OR_RETURN(smartData, priv, 0);
+
+ return priv->pageClient->page();
+}
diff --git a/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h b/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h
index 2b3f476ba..62598e4c0 100644
--- a/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h
+++ b/Source/WebKit2/UIProcess/API/efl/ewk_view_private.h
@@ -36,4 +36,6 @@ void ewk_view_title_changed(Evas_Object* ewkView, const char* title);
Evas_Object* ewk_view_base_add(Evas* canvas, WKContextRef, WKPageGroupRef);
+WebKit::WebPageProxy* ewk_view_page_get(const Evas_Object* ewkView);
+
#endif // ewk_view_private_h
diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp
index 8fbfe73f6..8ecd480e5 100644
--- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp
@@ -229,6 +229,14 @@ PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPagePr
return WebContextMenuProxyGtk::create(m_viewWidget, page);
}
+#if ENABLE(INPUT_TYPE_COLOR)
+PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&)
+{
+ notImplemented();
+ return 0;
+}
+#endif
+
void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate)
{
notImplemented();
diff --git a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h
index 54ad99f8f..72fc34539 100644
--- a/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h
+++ b/Source/WebKit2/UIProcess/API/gtk/PageClientImpl.h
@@ -81,6 +81,9 @@ private:
virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled);
virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*);
virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*);
+#if ENABLE(INPUT_TYPE_COLOR)
+ virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& intialColor);
+#endif
virtual void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate);
virtual void didChangeScrollbarsForMainFrame() const;
virtual void flashBackingStoreUpdates(const Vector<WebCore::IntRect>& updateRects);
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp
new file mode 100644
index 000000000..f05fbf93f
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp
@@ -0,0 +1,308 @@
+/*
+ * 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 "WebKitContextMenu.h"
+
+#include "WebKitContextMenuItemPrivate.h"
+#include "WebKitContextMenuPrivate.h"
+
+using namespace WebKit;
+using namespace WebCore;
+
+struct _WebKitContextMenuPrivate {
+ GList* items;
+ WebKitContextMenuItem* parentItem;
+};
+
+G_DEFINE_TYPE(WebKitContextMenu, webkit_context_menu, G_TYPE_OBJECT)
+
+static void webkitContextMenuFinalize(GObject* object)
+{
+ WebKitContextMenu* menu = WEBKIT_CONTEXT_MENU(object);
+ webkit_context_menu_remove_all(menu);
+ menu->priv->~WebKitContextMenuPrivate();
+ G_OBJECT_CLASS(webkit_context_menu_parent_class)->finalize(object);
+}
+
+static void webkit_context_menu_init(WebKitContextMenu* menu)
+{
+ WebKitContextMenuPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(menu, WEBKIT_TYPE_CONTEXT_MENU, WebKitContextMenuPrivate);
+ menu->priv = priv;
+ new (priv) WebKitContextMenuPrivate();
+}
+
+static void webkit_context_menu_class_init(WebKitContextMenuClass* listClass)
+{
+ GObjectClass* gObjectClass = G_OBJECT_CLASS(listClass);
+ gObjectClass->finalize = webkitContextMenuFinalize;
+
+ g_type_class_add_private(listClass, sizeof(WebKitContextMenuPrivate));
+}
+
+void webkitContextMenuPopulate(WebKitContextMenu* menu, Vector<ContextMenuItem>& contextMenuItems)
+{
+ for (GList* item = menu->priv->items; item; item = g_list_next(item)) {
+ WebKitContextMenuItem* menuItem = WEBKIT_CONTEXT_MENU_ITEM(item->data);
+ contextMenuItems.append(ContextMenuItem(webkitContextMenuItemRelease(menuItem)));
+ }
+}
+
+WebKitContextMenu* webkitContextMenuCreate(WKArrayRef wkItems)
+{
+ WebKitContextMenu* menu = webkit_context_menu_new();
+ for (size_t i = 0; i < WKArrayGetSize(wkItems); ++i) {
+ WKContextMenuItemRef wkItem = static_cast<WKContextMenuItemRef>(WKArrayGetItemAtIndex(wkItems, i));
+ webkit_context_menu_prepend(menu, webkitContextMenuItemCreate(wkItem));
+ }
+ menu->priv->items = g_list_reverse(menu->priv->items);
+
+ return menu;
+}
+
+void webkitContextMenuSetParentItem(WebKitContextMenu* menu, WebKitContextMenuItem* item)
+{
+ menu->priv->parentItem = item;
+}
+
+WebKitContextMenuItem* webkitContextMenuGetParentItem(WebKitContextMenu* menu)
+{
+ return menu->priv->parentItem;
+}
+
+/**
+ * webkit_context_menu_new:
+ *
+ * Creates a new #WebKitContextMenu object to be used as a submenu of an existing
+ * #WebKitContextMenu. The context menu of a #WebKitWebView is created by the view
+ * and passed as an argument of #WebKitWebView::context-menu signal.
+ * To add items to the menu use webkit_context_menu_prepend(),
+ * webkit_context_menu_append() or webkit_context_menu_insert().
+ * See also webkit_context_menu_new_with_items() to create a #WebKitContextMenu with
+ * a list of initial items.
+ *
+ * Returns: The newly created #WebKitContextMenu object
+ */
+WebKitContextMenu* webkit_context_menu_new()
+{
+ return WEBKIT_CONTEXT_MENU(g_object_new(WEBKIT_TYPE_CONTEXT_MENU, NULL));
+}
+
+/**
+ * webkit_context_menu_new_with_items:
+ * @items: (element-type WebKitContextMenuItem): a #GList of #WebKitContextMenuItem
+ *
+ * Creates a new #WebKitContextMenu object to be used as a submenu of an existing
+ * #WebKitContextMenu with the given initial items.
+ * See also webkit_context_menu_new()
+ *
+ * Returns: The newly created #WebKitContextMenu object
+ */
+WebKitContextMenu* webkit_context_menu_new_with_items(GList* items)
+{
+ WebKitContextMenu* menu = webkit_context_menu_new();
+ g_list_foreach(items, reinterpret_cast<GFunc>(g_object_ref_sink), 0);
+ menu->priv->items = g_list_copy(items);
+
+ return menu;
+}
+
+/**
+ * webkit_context_menu_prepend:
+ * @menu: a #WebKitContextMenu
+ * @item: the #WebKitContextMenuItem to add
+ *
+ * Adds @item at the beginning of the @menu.
+ */
+void webkit_context_menu_prepend(WebKitContextMenu* menu, WebKitContextMenuItem* item)
+{
+ webkit_context_menu_insert(menu, item, 0);
+}
+
+/**
+ * webkit_context_menu_append:
+ * @menu: a #WebKitContextMenu
+ * @item: the #WebKitContextMenuItem to add
+ *
+ * Adds @item at the end of the @menu.
+ */
+void webkit_context_menu_append(WebKitContextMenu* menu, WebKitContextMenuItem* item)
+{
+ webkit_context_menu_insert(menu, item, -1);
+}
+
+/**
+ * webkit_context_menu_insert:
+ * @menu: a #WebKitContextMenu
+ * @item: the #WebKitContextMenuItem to add
+ * @position: the position to insert the item
+ *
+ * Inserts @item into the @menu at the given position.
+ * If @position is negative, or is larger than the number of items
+ * in the #WebKitContextMenu, the item is added on to the end of
+ * the @menu. The first position is 0.
+ */
+void webkit_context_menu_insert(WebKitContextMenu* menu, WebKitContextMenuItem* item, int position)
+{
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu));
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item));
+
+ g_object_ref_sink(item);
+ menu->priv->items = g_list_insert(menu->priv->items, item, position);
+}
+
+/**
+ * webkit_context_menu_move_item:
+ * @menu: a #WebKitContextMenu
+ * @item: the #WebKitContextMenuItem to add
+ * @position: the new position to move the item
+ *
+ * Moves @item to the given position in the @menu.
+ * If @position is negative, or is larger than the number of items
+ * in the #WebKitContextMenu, the item is added on to the end of
+ * the @menu.
+ * The first position is 0.
+ */
+void webkit_context_menu_move_item(WebKitContextMenu* menu, WebKitContextMenuItem* item, int position)
+{
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu));
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item));
+
+ if (!g_list_find(menu->priv->items, item))
+ return;
+
+ menu->priv->items = g_list_remove(menu->priv->items, item);
+ menu->priv->items = g_list_insert(menu->priv->items, item, position);
+}
+
+/**
+ * webkit_context_menu_get_items:
+ * @menu: a #WebKitContextMenu
+ *
+ * Returns the item list of @menu.
+ *
+ * Returns: (element-type WebKitContextMenuItem) (transfer none): a #GList of
+ * #WebKitContextMenuItem<!-- -->s
+ */
+GList* webkit_context_menu_get_items(WebKitContextMenu* menu)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0);
+
+ return menu->priv->items;
+}
+
+/**
+ * webkit_context_menu_get_n_items:
+ * @menu: a #WebKitContextMenu
+ *
+ * Gets the length of the @menu.
+ *
+ * Returns: the number of #WebKitContextMenuItem<!-- -->s in @menu
+ */
+guint webkit_context_menu_get_n_items(WebKitContextMenu* menu)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0);
+
+ return g_list_length(menu->priv->items);
+}
+
+/**
+ * webkit_context_menu_first:
+ * @menu: a #WebKitContextMenu
+ *
+ * Gets the first item in the @menu.
+ *
+ * Returns: (transfer none): the first #WebKitContextMenuItem of @menu,
+ * or %NULL if the #WebKitContextMenu is empty.
+ */
+WebKitContextMenuItem* webkit_context_menu_first(WebKitContextMenu* menu)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0);
+
+ return menu->priv->items ? WEBKIT_CONTEXT_MENU_ITEM(menu->priv->items->data) : 0;
+}
+
+/**
+ * webkit_context_menu_last:
+ * @menu: a #WebKitContextMenu
+ *
+ * Gets the last item in the @menu.
+ *
+ * Returns: (transfer none): the last #WebKitContextMenuItem of @menu,
+ * or %NULL if the #WebKitContextMenu is empty.
+ */
+WebKitContextMenuItem* webkit_context_menu_last(WebKitContextMenu* menu)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0);
+
+ GList* last = g_list_last(menu->priv->items);
+ return last ? WEBKIT_CONTEXT_MENU_ITEM(last->data) : 0;
+}
+
+/**
+ * webkit_context_menu_get_item_at_position:
+ * @menu: a #WebKitContextMenu
+ * @position: the position of the item, counting from 0
+ *
+ * Gets the item at the given position in the @menu.
+ *
+ * Returns: (transfer none): the #WebKitContextMenuItem at position @position in @menu,
+ * or %NULL if the position is off the end of the @menu.
+ */
+WebKitContextMenuItem* webkit_context_menu_get_item_at_position(WebKitContextMenu* menu, unsigned position)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), 0);
+
+ gpointer item = g_list_nth_data(menu->priv->items, position);
+ return item ? WEBKIT_CONTEXT_MENU_ITEM(item) : 0;
+}
+
+/**
+ * webkit_context_menu_remove:
+ * @menu: a #WebKitContextMenu
+ * @item: the #WebKitContextMenuItem to remove
+ *
+ * Removes @item from the @menu.
+ * See also webkit_context_menu_remove_all() to remove all items.
+ */
+void webkit_context_menu_remove(WebKitContextMenu* menu, WebKitContextMenuItem* item)
+{
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu));
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item));
+
+ if (!g_list_find(menu->priv->items, item))
+ return;
+
+ menu->priv->items = g_list_remove(menu->priv->items, item);
+ g_object_unref(item);
+}
+
+/**
+ * webkit_context_menu_remove_all:
+ * @menu: a #WebKitContextMenu
+ *
+ * Removes all items of the @menu.
+ */
+void webkit_context_menu_remove_all(WebKitContextMenu* menu)
+{
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu));
+
+ g_list_free_full(menu->priv->items, reinterpret_cast<GDestroyNotify>(g_object_unref));
+ menu->priv->items = 0;
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h
new file mode 100644
index 000000000..9df3f4c11
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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 WebKitContextMenu_h
+#define WebKitContextMenu_h
+
+#include <glib-object.h>
+#include <webkit2/WebKitContextMenuItem.h>
+#include <webkit2/WebKitDefines.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_CONTEXT_MENU (webkit_context_menu_get_type())
+#define WEBKIT_CONTEXT_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_CONTEXT_MENU, WebKitContextMenu))
+#define WEBKIT_IS_CONTEXT_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_CONTEXT_MENU))
+#define WEBKIT_CONTEXT_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_CONTEXT_MENU, WebKitContextMenuClass))
+#define WEBKIT_IS_CONTEXT_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_CONTEXT_MENU))
+#define WEBKIT_CONTEXT_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_CONTEXT_MENU, WebKitContextMenuClass))
+
+typedef struct _WebKitContextMenuClass WebKitContextMenuClass;
+typedef struct _WebKitContextMenuPrivate WebKitContextMenuPrivate;
+
+struct _WebKitContextMenu {
+ GObject parent;
+
+ WebKitContextMenuPrivate *priv;
+};
+
+struct _WebKitContextMenuClass {
+ GObjectClass parent_class;
+};
+
+WEBKIT_API GType
+webkit_context_menu_get_type (void);
+
+WEBKIT_API WebKitContextMenu *
+webkit_context_menu_new (void);
+
+WEBKIT_API WebKitContextMenu *
+webkit_context_menu_new_with_items (GList *items);
+
+WEBKIT_API void
+webkit_context_menu_prepend (WebKitContextMenu *menu,
+ WebKitContextMenuItem *item);
+
+WEBKIT_API void
+webkit_context_menu_append (WebKitContextMenu *menu,
+ WebKitContextMenuItem *item);
+
+WEBKIT_API void
+webkit_context_menu_insert (WebKitContextMenu *menu,
+ WebKitContextMenuItem *item,
+ gint position);
+
+WEBKIT_API void
+webkit_context_menu_move_item (WebKitContextMenu *menu,
+ WebKitContextMenuItem *item,
+ gint position);
+WEBKIT_API GList *
+webkit_context_menu_get_items (WebKitContextMenu *menu);
+
+WEBKIT_API guint
+webkit_context_menu_get_n_items (WebKitContextMenu *menu);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_first (WebKitContextMenu *menu);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_last (WebKitContextMenu *menu);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_get_item_at_position (WebKitContextMenu *menu,
+ guint position);
+
+WEBKIT_API void
+webkit_context_menu_remove (WebKitContextMenu *menu,
+ WebKitContextMenuItem *item);
+
+WEBKIT_API void
+webkit_context_menu_remove_all (WebKitContextMenu *menu);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.cpp
new file mode 100644
index 000000000..3793d7c0f
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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 "WebKitContextMenuActions.h"
+
+#include "WebKitContextMenuActionsPrivate.h"
+#include <WebCore/LocalizedStrings.h>
+
+using namespace WebCore;
+
+bool webkitContextMenuActionIsCheckable(WebKitContextMenuAction action)
+{
+ switch (action) {
+ case WEBKIT_CONTEXT_MENU_ACTION_BOLD:
+ case WEBKIT_CONTEXT_MENU_ACTION_ITALIC:
+ case WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE:
+ case WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS:
+ case WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+ContextMenuAction webkitContextMenuActionGetActionTag(WebKitContextMenuAction action)
+{
+ switch (action) {
+ case WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION:
+ return ContextMenuItemTagNoAction;
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK:
+ return ContextMenuItemTagOpenLink;
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW:
+ return ContextMenuItemTagOpenLinkInNewWindow;
+ case WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK:
+ return ContextMenuItemTagDownloadLinkToDisk;
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD:
+ return ContextMenuItemTagCopyLinkToClipboard;
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW:
+ return ContextMenuItemTagOpenImageInNewWindow;
+ case WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK:
+ return ContextMenuItemTagDownloadImageToDisk;
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD:
+ return ContextMenuItemTagCopyImageToClipboard;
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD:
+ return ContextMenuItemTagCopyImageUrlToClipboard;
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_FRAME_IN_NEW_WINDOW:
+ return ContextMenuItemTagOpenFrameInNewWindow;
+ case WEBKIT_CONTEXT_MENU_ACTION_GO_BACK:
+ return ContextMenuItemTagGoBack;
+ case WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD:
+ return ContextMenuItemTagGoForward;
+ case WEBKIT_CONTEXT_MENU_ACTION_STOP:
+ return ContextMenuItemTagStop;
+ case WEBKIT_CONTEXT_MENU_ACTION_RELOAD:
+ return ContextMenuItemTagReload;
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY:
+ return ContextMenuItemTagCopy;
+ case WEBKIT_CONTEXT_MENU_ACTION_CUT:
+ return ContextMenuItemTagCut;
+ case WEBKIT_CONTEXT_MENU_ACTION_PASTE:
+ return ContextMenuItemTagPaste;
+ case WEBKIT_CONTEXT_MENU_ACTION_DELETE:
+ return ContextMenuItemTagDelete;
+ case WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL:
+ return ContextMenuItemTagSelectAll;
+ case WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS:
+ return ContextMenuItemTagInputMethods;
+ case WEBKIT_CONTEXT_MENU_ACTION_UNICODE:
+ return ContextMenuItemTagUnicode;
+ case WEBKIT_CONTEXT_MENU_ACTION_SPELLING_GUESS:
+ return ContextMenuItemTagSpellingGuess;
+ case WEBKIT_CONTEXT_MENU_ACTION_NO_GUESSES_FOUND:
+ return ContextMenuItemTagNoGuessesFound;
+ case WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING:
+ return ContextMenuItemTagIgnoreSpelling;
+ case WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING:
+ return ContextMenuItemTagLearnSpelling;
+ case WEBKIT_CONTEXT_MENU_ACTION_IGNORE_GRAMMAR:
+ return ContextMenuItemTagIgnoreGrammar;
+ case WEBKIT_CONTEXT_MENU_ACTION_FONT_MENU:
+ return ContextMenuItemTagFontMenu;
+ case WEBKIT_CONTEXT_MENU_ACTION_BOLD:
+ return ContextMenuItemTagBold;
+ case WEBKIT_CONTEXT_MENU_ACTION_ITALIC:
+ return ContextMenuItemTagItalic;
+ case WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE:
+ return ContextMenuItemTagUnderline;
+ case WEBKIT_CONTEXT_MENU_ACTION_OUTLINE:
+ return ContextMenuItemTagOutline;
+ case WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT:
+ return ContextMenuItemTagInspectElement;
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW:
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_AUDIO_IN_NEW_WINDOW:
+ return ContextMenuItemTagOpenMediaInNewWindow;
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD:
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_AUDIO_LINK_TO_CLIPBOARD:
+ return ContextMenuItemTagCopyMediaLinkToClipboard;
+ case WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS:
+ return ContextMenuItemTagToggleMediaControls;
+ case WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP:
+ return ContextMenuItemTagToggleMediaLoop;
+ case WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN:
+ return ContextMenuItemTagEnterVideoFullscreen;
+ case WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY:
+ case WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PAUSE:
+ return ContextMenuItemTagMediaPlayPause;
+ case WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE:
+ return ContextMenuItemTagMediaMute;
+ case WEBKIT_CONTEXT_MENU_ACTION_CUSTOM:
+ return ContextMenuItemBaseApplicationTag;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ return ContextMenuItemBaseApplicationTag;
+}
+
+WebKitContextMenuAction webkitContextMenuActionGetForContextMenuItem(ContextMenuItem* menuItem)
+{
+ switch (menuItem->action()) {
+ case ContextMenuItemTagNoAction:
+ return WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION;
+ case ContextMenuItemTagOpenLink:
+ return WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK;
+ case ContextMenuItemTagOpenLinkInNewWindow:
+ return WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW;
+ case ContextMenuItemTagDownloadLinkToDisk:
+ return WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK;
+ case ContextMenuItemTagCopyLinkToClipboard:
+ return WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD;
+ case ContextMenuItemTagOpenImageInNewWindow:
+ return WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW;
+ case ContextMenuItemTagDownloadImageToDisk:
+ return WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK;
+ case ContextMenuItemTagCopyImageToClipboard:
+ return WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD;
+ case ContextMenuItemTagCopyImageUrlToClipboard:
+ return WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD;
+ case ContextMenuItemTagOpenFrameInNewWindow:
+ return WEBKIT_CONTEXT_MENU_ACTION_OPEN_FRAME_IN_NEW_WINDOW;
+ case ContextMenuItemTagGoBack:
+ return WEBKIT_CONTEXT_MENU_ACTION_GO_BACK;
+ case ContextMenuItemTagGoForward:
+ return WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD;
+ case ContextMenuItemTagStop:
+ return WEBKIT_CONTEXT_MENU_ACTION_STOP;
+ case ContextMenuItemTagReload:
+ return WEBKIT_CONTEXT_MENU_ACTION_RELOAD;
+ case ContextMenuItemTagCopy:
+ return WEBKIT_CONTEXT_MENU_ACTION_COPY;
+ case ContextMenuItemTagCut:
+ return WEBKIT_CONTEXT_MENU_ACTION_CUT;
+ case ContextMenuItemTagPaste:
+ return WEBKIT_CONTEXT_MENU_ACTION_PASTE;
+ case ContextMenuItemTagDelete:
+ return WEBKIT_CONTEXT_MENU_ACTION_DELETE;
+ case ContextMenuItemTagSelectAll:
+ return WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL;
+ case ContextMenuItemTagInputMethods:
+ return WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS;
+ case ContextMenuItemTagUnicode:
+ return WEBKIT_CONTEXT_MENU_ACTION_UNICODE;
+ case ContextMenuItemTagSpellingGuess:
+ return WEBKIT_CONTEXT_MENU_ACTION_SPELLING_GUESS;
+ case ContextMenuItemTagIgnoreSpelling:
+ return WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING;
+ case ContextMenuItemTagLearnSpelling:
+ return WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING;
+ case ContextMenuItemTagIgnoreGrammar:
+ return WEBKIT_CONTEXT_MENU_ACTION_IGNORE_GRAMMAR;
+ case ContextMenuItemTagFontMenu:
+ return WEBKIT_CONTEXT_MENU_ACTION_FONT_MENU;
+ case ContextMenuItemTagBold:
+ return WEBKIT_CONTEXT_MENU_ACTION_BOLD;
+ case ContextMenuItemTagItalic:
+ return WEBKIT_CONTEXT_MENU_ACTION_ITALIC;
+ case ContextMenuItemTagUnderline:
+ return WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE;
+ case ContextMenuItemTagOutline:
+ return WEBKIT_CONTEXT_MENU_ACTION_OUTLINE;
+ case ContextMenuItemTagInspectElement:
+ return WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT;
+ case ContextMenuItemTagOpenMediaInNewWindow:
+ return menuItem->title() == contextMenuItemTagOpenVideoInNewWindow() ?
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW : WEBKIT_CONTEXT_MENU_ACTION_OPEN_AUDIO_IN_NEW_WINDOW;
+ case ContextMenuItemTagCopyMediaLinkToClipboard:
+ return menuItem->title() == contextMenuItemTagCopyVideoLinkToClipboard() ?
+ WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD : WEBKIT_CONTEXT_MENU_ACTION_COPY_AUDIO_LINK_TO_CLIPBOARD;
+ case ContextMenuItemTagToggleMediaControls:
+ return WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS;
+ case ContextMenuItemTagToggleMediaLoop:
+ return WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP;
+ case ContextMenuItemTagEnterVideoFullscreen:
+ return WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN;
+ case ContextMenuItemTagMediaPlayPause:
+ return menuItem->title() == contextMenuItemTagMediaPlay() ?
+ WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY : WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PAUSE;
+ case ContextMenuItemTagMediaMute:
+ return WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE;
+ case ContextMenuItemBaseApplicationTag:
+ return WEBKIT_CONTEXT_MENU_ACTION_CUSTOM;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ return WEBKIT_CONTEXT_MENU_ACTION_CUSTOM;
+}
+
+String webkitContextMenuActionGetLabel(WebKitContextMenuAction action)
+{
+ switch (action) {
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK:
+ return contextMenuItemTagOpenLink();
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW:
+ return contextMenuItemTagOpenLinkInNewWindow();
+ case WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK:
+ return contextMenuItemTagDownloadLinkToDisk();
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD:
+ return contextMenuItemTagCopyLinkToClipboard();
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW:
+ return contextMenuItemTagOpenImageInNewWindow();
+ case WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK:
+ return contextMenuItemTagDownloadImageToDisk();
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD:
+ return contextMenuItemTagCopyImageToClipboard();
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD:
+ return contextMenuItemTagCopyImageUrlToClipboard();
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_FRAME_IN_NEW_WINDOW:
+ return contextMenuItemTagOpenFrameInNewWindow();
+ case WEBKIT_CONTEXT_MENU_ACTION_GO_BACK:
+ return contextMenuItemTagGoBack();
+ case WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD:
+ return contextMenuItemTagGoForward();
+ case WEBKIT_CONTEXT_MENU_ACTION_STOP:
+ return contextMenuItemTagStop();
+ case WEBKIT_CONTEXT_MENU_ACTION_RELOAD:
+ return contextMenuItemTagReload();
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY:
+ return contextMenuItemTagCopy();
+ case WEBKIT_CONTEXT_MENU_ACTION_CUT:
+ return contextMenuItemTagCut();
+ case WEBKIT_CONTEXT_MENU_ACTION_PASTE:
+ return contextMenuItemTagPaste();
+ case WEBKIT_CONTEXT_MENU_ACTION_DELETE:
+ return contextMenuItemTagDelete();
+ case WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL:
+ return contextMenuItemTagSelectAll();
+ case WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS:
+ return contextMenuItemTagInputMethods();
+ case WEBKIT_CONTEXT_MENU_ACTION_UNICODE:
+ return contextMenuItemTagUnicode();
+ case WEBKIT_CONTEXT_MENU_ACTION_NO_GUESSES_FOUND:
+ return contextMenuItemTagNoGuessesFound();
+ case WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING:
+ return contextMenuItemTagIgnoreSpelling();
+ case WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING:
+ return contextMenuItemTagLearnSpelling();
+ case WEBKIT_CONTEXT_MENU_ACTION_IGNORE_GRAMMAR:
+ return contextMenuItemTagIgnoreGrammar();
+ case WEBKIT_CONTEXT_MENU_ACTION_FONT_MENU:
+ return contextMenuItemTagFontMenu();
+ case WEBKIT_CONTEXT_MENU_ACTION_BOLD:
+ return contextMenuItemTagBold();
+ case WEBKIT_CONTEXT_MENU_ACTION_ITALIC:
+ return contextMenuItemTagItalic();
+ case WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE:
+ return contextMenuItemTagUnderline();
+ case WEBKIT_CONTEXT_MENU_ACTION_OUTLINE:
+ return contextMenuItemTagOutline();
+ case WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT:
+ return contextMenuItemTagInspectElement();
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW:
+ return contextMenuItemTagOpenVideoInNewWindow();
+ case WEBKIT_CONTEXT_MENU_ACTION_OPEN_AUDIO_IN_NEW_WINDOW:
+ return contextMenuItemTagOpenAudioInNewWindow();
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD:
+ return contextMenuItemTagCopyVideoLinkToClipboard();
+ case WEBKIT_CONTEXT_MENU_ACTION_COPY_AUDIO_LINK_TO_CLIPBOARD:
+ return contextMenuItemTagCopyAudioLinkToClipboard();
+ case WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS:
+ return contextMenuItemTagToggleMediaControls();
+ case WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP:
+ return contextMenuItemTagToggleMediaLoop();
+ case WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN:
+ return contextMenuItemTagEnterVideoFullscreen();
+ case WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY:
+ return contextMenuItemTagMediaPlay();
+ case WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PAUSE:
+ return contextMenuItemTagMediaPause();
+ case WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE:
+ return contextMenuItemTagMediaMute();
+ case WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION:
+ case WEBKIT_CONTEXT_MENU_ACTION_CUSTOM:
+ case WEBKIT_CONTEXT_MENU_ACTION_SPELLING_GUESS:
+ return String();
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ return String();
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h
new file mode 100644
index 000000000..185bd251f
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h
@@ -0,0 +1,130 @@
+/*
+ * 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
+
+#include <glib.h>
+
+#ifndef WebKitContextMenuActions_h
+#define WebKitContextMenuActions_h
+
+G_BEGIN_DECLS
+
+/**
+ * WebKitContextMenuAction:
+ * @WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION: No action, used by separator menu items.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK: Open current link.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW: Open current link in a new window.
+ * @WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK: Download link destination.
+ * @WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD: Copy link location to the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW: Open current image in a new window.
+ * @WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK: Download current image.
+ * @WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD: Copy current image to the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD: Copy curent image location to the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OPEN_FRAME_IN_NEW_WINDOW: Open current frame in a new window.
+ * @WEBKIT_CONTEXT_MENU_ACTION_GO_BACK: Load the previous history item.
+ * @WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD: Load the next history item.
+ * @WEBKIT_CONTEXT_MENU_ACTION_STOP: Stop any ongoing loading operation.
+ * @WEBKIT_CONTEXT_MENU_ACTION_RELOAD: Reload the conents of current view.
+ * @WEBKIT_CONTEXT_MENU_ACTION_COPY: Copy current selection the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_CUT: Cut current selection to the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_PASTE: Paste clipboard contents.
+ * @WEBKIT_CONTEXT_MENU_ACTION_DELETE: Delete current selection.
+ * @WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL: Select all text.
+ * @WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS: Input methods menu.
+ * @WEBKIT_CONTEXT_MENU_ACTION_UNICODE: Unicode menu.
+ * @WEBKIT_CONTEXT_MENU_ACTION_SPELLING_GUESS: A proposed replacement for a misspelled word.
+ * @WEBKIT_CONTEXT_MENU_ACTION_NO_GUESSES_FOUND: An indicator that spellchecking found no proposed replacements.
+ * @WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING: Causes the spellchecker to ignore the word for this session.
+ * @WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING: Causes the spellchecker to add the word to the dictionary.
+ * @WEBKIT_CONTEXT_MENU_ACTION_IGNORE_GRAMMAR: Ignore grammar.
+ * @WEBKIT_CONTEXT_MENU_ACTION_FONT_MENU: Font options menu.
+ * @WEBKIT_CONTEXT_MENU_ACTION_BOLD: Bold.
+ * @WEBKIT_CONTEXT_MENU_ACTION_ITALIC: Italic.
+ * @WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE: Underline.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OUTLINE: Outline.
+ * @WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT: Open current element in the inspector.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW: Open current video element in a new window.
+ * @WEBKIT_CONTEXT_MENU_ACTION_OPEN_AUDIO_IN_NEW_WINDOW: Open current audio element in a new window.
+ * @WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD: Copy video link location in to the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_COPY_AUDIO_LINK_TO_CLIPBOARD: Copy audio link location in to the clipboard.
+ * @WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS: Enable or disable media controls.
+ * @WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP: Enable or disable media loop.
+ * @WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN: Show current video element in fullscreen mode.
+ * @WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY: Play current media element.
+ * @WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PAUSE: Pause current media element.
+ * @WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE: Mute current media element.
+ * @WEBKIT_CONTEXT_MENU_ACTION_CUSTOM: Custom action defined by applications.
+ *
+ * Enum values used to denote the stock actions for
+ * #WebKitContextMenuItem<!-- -->s
+ */
+typedef enum {
+ WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION = 0,
+
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK,
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW,
+ WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK,
+ WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD,
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW,
+ WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK,
+ WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD,
+ WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD,
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_FRAME_IN_NEW_WINDOW,
+ WEBKIT_CONTEXT_MENU_ACTION_GO_BACK,
+ WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD,
+ WEBKIT_CONTEXT_MENU_ACTION_STOP,
+ WEBKIT_CONTEXT_MENU_ACTION_RELOAD,
+ WEBKIT_CONTEXT_MENU_ACTION_COPY,
+ WEBKIT_CONTEXT_MENU_ACTION_CUT,
+ WEBKIT_CONTEXT_MENU_ACTION_PASTE,
+ WEBKIT_CONTEXT_MENU_ACTION_DELETE,
+ WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL,
+ WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS,
+ WEBKIT_CONTEXT_MENU_ACTION_UNICODE,
+ WEBKIT_CONTEXT_MENU_ACTION_SPELLING_GUESS,
+ WEBKIT_CONTEXT_MENU_ACTION_NO_GUESSES_FOUND,
+ WEBKIT_CONTEXT_MENU_ACTION_IGNORE_SPELLING,
+ WEBKIT_CONTEXT_MENU_ACTION_LEARN_SPELLING,
+ WEBKIT_CONTEXT_MENU_ACTION_IGNORE_GRAMMAR,
+ WEBKIT_CONTEXT_MENU_ACTION_FONT_MENU,
+ WEBKIT_CONTEXT_MENU_ACTION_BOLD,
+ WEBKIT_CONTEXT_MENU_ACTION_ITALIC,
+ WEBKIT_CONTEXT_MENU_ACTION_UNDERLINE,
+ WEBKIT_CONTEXT_MENU_ACTION_OUTLINE,
+ WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT,
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW,
+ WEBKIT_CONTEXT_MENU_ACTION_OPEN_AUDIO_IN_NEW_WINDOW,
+ WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD,
+ WEBKIT_CONTEXT_MENU_ACTION_COPY_AUDIO_LINK_TO_CLIPBOARD,
+ WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS,
+ WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP,
+ WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN,
+ WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY,
+ WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PAUSE,
+ WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE,
+
+ WEBKIT_CONTEXT_MENU_ACTION_CUSTOM = 10000
+} WebKitContextMenuAction;
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActionsPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActionsPrivate.h
new file mode 100644
index 000000000..f753bb97c
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActionsPrivate.h
@@ -0,0 +1,31 @@
+/*
+ * 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 WebKitContextMenuActionsPrivate_h
+#define WebKitContextMenuActionsPrivate_h
+
+#include "WebKitContextMenuActions.h"
+#include <WebCore/ContextMenuItem.h>
+
+bool webkitContextMenuActionIsCheckable(WebKitContextMenuAction);
+WebCore::ContextMenuAction webkitContextMenuActionGetActionTag(WebKitContextMenuAction);
+WebKitContextMenuAction webkitContextMenuActionGetForContextMenuItem(WebCore::ContextMenuItem*);
+String webkitContextMenuActionGetLabel(WebKitContextMenuAction);
+
+#endif // WebKitPrintOperationPrivate_h
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.cpp
new file mode 100644
index 000000000..b2b22fe41
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.cpp
@@ -0,0 +1,345 @@
+/*
+ * 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 "WebKitContextMenuItem.h"
+
+#include "MutableArray.h"
+#include "WebContextMenuItem.h"
+#include "WebContextMenuItemData.h"
+#include "WebKitContextMenuActionsPrivate.h"
+#include "WebKitContextMenuItemPrivate.h"
+#include "WebKitContextMenuPrivate.h"
+#include <WebCore/ContextMenu.h>
+#include <WebCore/ContextMenuItem.h>
+#include <gtk/gtk.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/gobject/GRefPtr.h>
+
+using namespace WebKit;
+using namespace WebCore;
+
+struct _WebKitContextMenuItemPrivate {
+ OwnPtr<ContextMenuItem> menuItem;
+ GRefPtr<WebKitContextMenu> subMenu;
+};
+
+G_DEFINE_TYPE(WebKitContextMenuItem, webkit_context_menu_item, G_TYPE_INITIALLY_UNOWNED)
+
+static void webkitContextMenuItemFinalize(GObject* object)
+{
+ WebKitContextMenuItemPrivate* priv = WEBKIT_CONTEXT_MENU_ITEM(object)->priv;
+ if (priv->subMenu)
+ webkitContextMenuSetParentItem(priv->subMenu.get(), 0);
+ priv->~WebKitContextMenuItemPrivate();
+ G_OBJECT_CLASS(webkit_context_menu_item_parent_class)->finalize(object);
+}
+
+static void webkit_context_menu_item_init(WebKitContextMenuItem* item)
+{
+ WebKitContextMenuItemPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(item, WEBKIT_TYPE_CONTEXT_MENU_ITEM, WebKitContextMenuItemPrivate);
+ item->priv = priv;
+ new (priv) WebKitContextMenuItemPrivate();
+}
+
+static void webkit_context_menu_item_class_init(WebKitContextMenuItemClass* itemClass)
+{
+ GObjectClass* gObjectClass = G_OBJECT_CLASS(itemClass);
+ gObjectClass->finalize = webkitContextMenuItemFinalize;
+ g_type_class_add_private(itemClass, sizeof(WebKitContextMenuItemPrivate));
+}
+
+static bool checkAndWarnIfMenuHasParentItem(WebKitContextMenu* menu)
+{
+ if (menu && webkitContextMenuGetParentItem(menu)) {
+ g_warning("Attempting to set a WebKitContextMenu as submenu of "
+ "a WebKitContextMenuItem, but the menu is already "
+ "a submenu of a WebKitContextMenuItem");
+ return true;
+ }
+
+ return false;
+}
+
+static void webkitContextMenuItemSetSubMenu(WebKitContextMenuItem* item, GRefPtr<WebKitContextMenu> subMenu)
+{
+ if (checkAndWarnIfMenuHasParentItem(subMenu.get()))
+ return;
+
+ if (item->priv->subMenu)
+ webkitContextMenuSetParentItem(item->priv->subMenu.get(), 0);
+ item->priv->subMenu = subMenu;
+ if (subMenu)
+ webkitContextMenuSetParentItem(subMenu.get(), item);
+}
+
+WebKitContextMenuItem* webkitContextMenuItemCreate(WKContextMenuItemRef wkItem)
+{
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ WebContextMenuItemData* itemData = toImpl(wkItem)->data();
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(itemData->type(), itemData->action(), itemData->title(), itemData->enabled(), itemData->checked()));
+ const Vector<WebContextMenuItemData>& subMenu = itemData->submenu();
+ if (!subMenu.size())
+ return item;
+
+ RefPtr<MutableArray> subMenuItems = MutableArray::create();
+ subMenuItems->reserveCapacity(subMenu.size());
+ for (size_t i = 0; i < subMenu.size(); ++i)
+ subMenuItems->append(WebContextMenuItem::create(subMenu[i]).get());
+ webkitContextMenuItemSetSubMenu(item, adoptGRef(webkitContextMenuCreate(toAPI(subMenuItems.get()))));
+
+ return item;
+}
+
+static WebKitContextMenuItem* webkitContextMenuItemCreateForGtkItem(GtkMenuItem* menuItem)
+{
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(menuItem));
+ webkitContextMenuItemSetSubMenuFromGtkMenu(item, GTK_MENU(gtk_menu_item_get_submenu(menuItem)));
+
+ return item;
+}
+
+void webkitContextMenuItemSetSubMenuFromGtkMenu(WebKitContextMenuItem* item, GtkMenu* subMenu)
+{
+ if (!subMenu)
+ return;
+
+ GOwnPtr<GList> children(gtk_container_get_children(GTK_CONTAINER(subMenu)));
+ if (!g_list_length(children.get()))
+ return;
+
+ webkitContextMenuItemSetSubMenu(item, adoptGRef(webkit_context_menu_new()));
+ for (GList* listItem = children.get(); listItem; listItem = g_list_next(listItem)) {
+ GRefPtr<GtkWidget> widget = GTK_WIDGET(listItem->data);
+ if (!GTK_IS_MENU_ITEM(widget.get()))
+ continue;
+
+ gtk_container_remove(GTK_CONTAINER(subMenu), widget.get());
+ GtkMenuItem* menuItem = GTK_MENU_ITEM(widget.leakRef());
+ g_object_force_floating(G_OBJECT(menuItem));
+ webkit_context_menu_append(item->priv->subMenu.get(), webkitContextMenuItemCreateForGtkItem(menuItem));
+ }
+}
+
+GtkMenuItem* webkitContextMenuItemRelease(WebKitContextMenuItem* item)
+{
+ if (item->priv->subMenu) {
+ Vector<ContextMenuItem> subMenuItems;
+ webkitContextMenuPopulate(item->priv->subMenu.get(), subMenuItems);
+ ContextMenu subMenu(platformMenuDescription(subMenuItems));
+ item->priv->menuItem->setSubMenu(&subMenu);
+ }
+
+ return item->priv->menuItem->releasePlatformDescription();
+}
+
+/**
+ * webkit_context_menu_item_new:
+ * @action: a #GtkAction
+ *
+ * Creates a new #WebKitContextMenuItem for the given @action.
+ *
+ * Returns: the newly created #WebKitContextMenuItem object.
+ */
+WebKitContextMenuItem* webkit_context_menu_item_new(GtkAction* action)
+{
+ g_return_val_if_fail(GTK_IS_ACTION(action), 0);
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(GTK_MENU_ITEM(gtk_action_create_menu_item(action))));
+ item->priv->menuItem->setAction(ContextMenuItemBaseApplicationTag);
+
+ return item;
+}
+
+/**
+ * webkit_context_menu_item_new_from_stock_action:
+ * @action: a #WebKitContextMenuAction stock action
+ *
+ * Creates a new #WebKitContextMenuItem for the given stock action.
+ * Stock actions are handled automatically by WebKit so that, for example,
+ * when a menu item created with a %WEBKIT_CONTEXT_MENU_ACTION_STOP is
+ * activated the action associated will be handled by WebKit and the current
+ * load operation will be stopped. You can get the #GtkAction of a
+ * #WebKitContextMenuItem created with a #WebKitContextMenuAction with
+ * webkit_context_menu_item_get_action() and connect to #GtkAction::activate signal
+ * to be notified when the item is activated. But you can't prevent the asociated
+ * action from being performed.
+ *
+ * Returns: the newly created #WebKitContextMenuItem object.
+ */
+WebKitContextMenuItem* webkit_context_menu_item_new_from_stock_action(WebKitContextMenuAction action)
+{
+ g_return_val_if_fail(action > WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION && action < WEBKIT_CONTEXT_MENU_ACTION_CUSTOM, 0);
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ ContextMenuItemType type = webkitContextMenuActionIsCheckable(action) ? CheckableActionType : ActionType;
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(type, webkitContextMenuActionGetActionTag(action), webkitContextMenuActionGetLabel(action)));
+
+ return item;
+}
+
+/**
+ * webkit_context_menu_item_new_from_stock_action_with_label:
+ * @action: a #WebKitContextMenuAction stock action
+ * @label: a custom label text to use instead of the predefined one
+ *
+ * Creates a new #WebKitContextMenuItem for the given stock action using the given @label.
+ * Stock actions have a predefined label, this method can be used to create a
+ * #WebKitContextMenuItem for a #WebKitContextMenuAction but using a custom label.
+ *
+ * Returns: the newly created #WebKitContextMenuItem object.
+ */
+WebKitContextMenuItem* webkit_context_menu_item_new_from_stock_action_with_label(WebKitContextMenuAction action, const gchar* label)
+{
+ g_return_val_if_fail(action > WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION && action < WEBKIT_CONTEXT_MENU_ACTION_CUSTOM, 0);
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ ContextMenuItemType type = webkitContextMenuActionIsCheckable(action) ? CheckableActionType : ActionType;
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(type, webkitContextMenuActionGetActionTag(action), String::fromUTF8(label)));
+
+ return item;
+}
+
+/**
+ * webkit_context_menu_item_new_with_submenu:
+ * @label: the menu item label text
+ * @submenu: a #WebKitContextMenu to set
+ *
+ * Creates a new #WebKitContextMenuItem using the given @label with a submenu.
+ *
+ * Returns: the newly created #WebKitContextMenuItem object.
+ */
+WebKitContextMenuItem* webkit_context_menu_item_new_with_submenu(const gchar* label, WebKitContextMenu* submenu)
+{
+ g_return_val_if_fail(label, 0);
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(submenu), 0);
+
+ if (checkAndWarnIfMenuHasParentItem(submenu))
+ return 0;
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(SubmenuType, ContextMenuItemBaseApplicationTag, String::fromUTF8(label)));
+ item->priv->subMenu = submenu;
+ webkitContextMenuSetParentItem(submenu, item);
+
+ return item;
+}
+
+/**
+ * webkit_context_menu_item_new_separator:
+ *
+ * Creates a new #WebKitContextMenuItem representing a separator.
+ *
+ * Returns: the newly created #WebKitContextMenuItem object.
+ */
+WebKitContextMenuItem* webkit_context_menu_item_new_separator(void)
+{
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(g_object_new(WEBKIT_TYPE_CONTEXT_MENU_ITEM, NULL));
+ item->priv->menuItem = WTF::adoptPtr(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()));
+
+ return item;
+}
+
+/**
+ * webkit_context_menu_item_get_action:
+ * @item: a #WebKitContextMenuItem
+ *
+ * Gets the action associated to @item.
+ *
+ * Returns: (transfer none): the #GtkAction associated to the #WebKitContextMenuItem,
+ * or %NULL if @item is a separator.
+ */
+GtkAction* webkit_context_menu_item_get_action(WebKitContextMenuItem* item)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item), 0);
+
+ return item->priv->menuItem->gtkAction();
+}
+
+/**
+ * webkit_context_menu_item_get_stock_action:
+ * @item: a #WebKitContextMenuItem
+ *
+ * Gets the #WebKitContextMenuAction of @item. If the #WebKitContextMenuItem was not
+ * created for a stock action %WEBKIT_CONTEXT_MENU_ACTION_CUSTOM will be
+ * returned. If the #WebKitContextMenuItem is a separator %WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION
+ * will be returned.
+ *
+ * Returns: the #WebKitContextMenuAction of @item
+ */
+WebKitContextMenuAction webkit_context_menu_item_get_stock_action(WebKitContextMenuItem* item)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item), WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
+
+ return webkitContextMenuActionGetForContextMenuItem(item->priv->menuItem.get());
+}
+
+/**
+ * webkit_context_menu_item_is_separator:
+ * @item: a #WebKitContextMenuItem
+ *
+ * Checks whether @item is a separator.
+ *
+ * Returns: %TRUE is @item is a separator or %FALSE otherwise
+ */
+gboolean webkit_context_menu_item_is_separator(WebKitContextMenuItem* item)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item), FALSE);
+
+ return item->priv->menuItem->type() == SeparatorType;
+}
+
+/**
+ * webkit_context_menu_item_set_submenu:
+ * @item: a #WebKitContextMenuItem
+ * @submenu: (allow-none): a #WebKitContextMenu
+ *
+ * Sets or replaces the @item submenu. If @submenu is %NULL the current
+ * submenu of @item is removed.
+ */
+void webkit_context_menu_item_set_submenu(WebKitContextMenuItem* item, WebKitContextMenu* submenu)
+{
+ g_return_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item));
+
+ if (item->priv->subMenu == submenu)
+ return;
+
+ webkitContextMenuItemSetSubMenu(item, submenu);
+}
+
+/**
+ * webkit_context_menu_item_get_submenu:
+ * @item: a #WebKitContextMenuItem
+ *
+ * Gets the submenu of @item.
+ *
+ * Returns: (transfer none): the #WebKitContextMenu representing the submenu of
+ * @item or %NULL if @item doesn't have a submenu.
+ */
+WebKitContextMenu* webkit_context_menu_item_get_submenu(WebKitContextMenuItem* item)
+{
+ g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU_ITEM(item), 0);
+
+ return item->priv->subMenu.get();
+}
+
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h
new file mode 100644
index 000000000..52d912843
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h
@@ -0,0 +1,92 @@
+/*
+ * 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 WebKitContextMenuItem_h
+#define WebKitContextMenuItem_h
+
+#include <gtk/gtk.h>
+#include <webkit2/WebKitDefines.h>
+#include <webkit2/WebKitContextMenu.h>
+#include <webkit2/WebKitContextMenuActions.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_CONTEXT_MENU_ITEM (webkit_context_menu_item_get_type())
+#define WEBKIT_CONTEXT_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_CONTEXT_MENU_ITEM, WebKitContextMenuItem))
+#define WEBKIT_IS_CONTEXT_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_CONTEXT_MENU_ITEM))
+#define WEBKIT_CONTEXT_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_CONTEXT_MENU_ITEM, WebKitContextMenuItemClass))
+#define WEBKIT_IS_CONTEXT_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_CONTEXT_MENU_ITEM))
+#define WEBKIT_CONTEXT_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_CONTEXT_MENU_ITEM, WebKitContextMenuItemClass))
+
+typedef struct _WebKitContextMenuItemClass WebKitContextMenuItemClass;
+typedef struct _WebKitContextMenuItemPrivate WebKitContextMenuItemPrivate;
+
+struct _WebKitContextMenuItem {
+ GInitiallyUnowned parent;
+
+ WebKitContextMenuItemPrivate *priv;
+};
+
+struct _WebKitContextMenuItemClass {
+ GInitiallyUnownedClass parent_class;
+};
+
+WEBKIT_API GType
+webkit_context_menu_item_get_type (void);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_item_new (GtkAction *action);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_item_new_from_stock_action (WebKitContextMenuAction action);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_item_new_from_stock_action_with_label (WebKitContextMenuAction action,
+ const gchar *label);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_item_new_with_submenu (const gchar *label,
+ WebKitContextMenu *submenu);
+
+WEBKIT_API WebKitContextMenuItem *
+webkit_context_menu_item_new_separator (void);
+
+WEBKIT_API GtkAction *
+webkit_context_menu_item_get_action (WebKitContextMenuItem *item);
+
+WEBKIT_API WebKitContextMenuAction
+webkit_context_menu_item_get_stock_action (WebKitContextMenuItem *item);
+
+WEBKIT_API gboolean
+webkit_context_menu_item_is_separator (WebKitContextMenuItem *item);
+
+WEBKIT_API void
+webkit_context_menu_item_set_submenu (WebKitContextMenuItem *item,
+ WebKitContextMenu *submenu);
+
+WEBKIT_API WebKitContextMenu *
+webkit_context_menu_item_get_submenu (WebKitContextMenuItem *item);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItemPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItemPrivate.h
new file mode 100644
index 000000000..9c88003bf
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItemPrivate.h
@@ -0,0 +1,30 @@
+/*
+ * 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 WebKitContextMenuItemPrivate_h
+#define WebKitContextMenuItemPrivate_h
+
+#include "WebKitContextMenuItem.h"
+#include "WebKitPrivate.h"
+
+WebKitContextMenuItem* webkitContextMenuItemCreate(WKContextMenuItemRef);
+GtkMenuItem* webkitContextMenuItemRelease(WebKitContextMenuItem*);
+void webkitContextMenuItemSetSubMenuFromGtkMenu(WebKitContextMenuItem*, GtkMenu*);
+
+#endif // WebKitContextMenuItemPrivate_h
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuPrivate.h
new file mode 100644
index 000000000..6d3f18015
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuPrivate.h
@@ -0,0 +1,31 @@
+/*
+ * 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 WebKitContextMenuPrivate_h
+#define WebKitContextMenuPrivate_h
+
+#include "WebKitContextMenu.h"
+#include "WebKitPrivate.h"
+
+WebKitContextMenu* webkitContextMenuCreate(WKArrayRef wkItems);
+void webkitContextMenuPopulate(WebKitContextMenu*, Vector<WebCore::ContextMenuItem>&);
+void webkitContextMenuSetParentItem(WebKitContextMenu*, WebKitContextMenuItem*);
+WebKitContextMenuItem* webkitContextMenuGetParentItem(WebKitContextMenu*);
+
+#endif // WebKitContextMenuPrivate_h
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitDefines.h b/Source/WebKit2/UIProcess/API/gtk/WebKitDefines.h
index 96bcb4ea2..733bf884c 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitDefines.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitDefines.h
@@ -32,9 +32,11 @@
#include <glib.h>
-typedef struct _WebKitPrintOperation WebKitPrintOperation;
-typedef struct _WebKitFindController WebKitFindController;
-typedef struct _WebKitWebView WebKitWebView;
+typedef struct _WebKitPrintOperation WebKitPrintOperation;
+typedef struct _WebKitFindController WebKitFindController;
+typedef struct _WebKitWebView WebKitWebView;
+typedef struct _WebKitContextMenu WebKitContextMenu;
+typedef struct _WebKitContextMenuItem WebKitContextMenuItem;
#ifdef G_OS_WIN32
# ifdef BUILDING_WEBKIT
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp
index 02e82b020..9e24aabb1 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.cpp
@@ -33,6 +33,7 @@
#include "WebKitPrivate.h"
#include "WebKitSettingsPrivate.h"
+#include "WebPageProxy.h"
#include <glib/gi18n-lib.h>
#include <wtf/text/CString.h>
@@ -46,6 +47,7 @@ struct _WebKitSettingsPrivate {
CString fantasyFontFamily;
CString pictographFontFamily;
CString defaultCharset;
+ bool allowModalDialogs;
bool zoomTextOnly;
};
@@ -105,6 +107,7 @@ enum {
PROP_PRINT_BACKGROUNDS,
PROP_ENABLE_WEBAUDIO,
PROP_ENABLE_WEBGL,
+ PROP_ALLOW_MODAL_DIALOGS,
PROP_ZOOM_TEXT_ONLY,
PROP_JAVASCRIPT_CAN_ACCESS_CLIPBOARD,
PROP_MEDIA_PLAYBACK_REQUIRES_USER_GESTURE,
@@ -216,6 +219,9 @@ static void webKitSettingsSetProperty(GObject* object, guint propId, const GValu
case PROP_ENABLE_WEBGL:
webkit_settings_set_enable_webgl(settings, g_value_get_boolean(value));
break;
+ case PROP_ALLOW_MODAL_DIALOGS:
+ webkit_settings_set_allow_modal_dialogs(settings, g_value_get_boolean(value));
+ break;
case PROP_ZOOM_TEXT_ONLY:
webkit_settings_set_zoom_text_only(settings, g_value_get_boolean(value));
break;
@@ -341,6 +347,9 @@ static void webKitSettingsGetProperty(GObject* object, guint propId, GValue* val
case PROP_ENABLE_WEBGL:
g_value_set_boolean(value, webkit_settings_get_enable_webgl(settings));
break;
+ case PROP_ALLOW_MODAL_DIALOGS:
+ g_value_set_boolean(value, webkit_settings_get_allow_modal_dialogs(settings));
+ break;
case PROP_ZOOM_TEXT_ONLY:
g_value_set_boolean(value, webkit_settings_get_zoom_text_only(settings));
break;
@@ -853,6 +862,24 @@ static void webkit_settings_class_init(WebKitSettingsClass* klass)
readWriteConstructParamFlags));
/**
+ * WebKitSettings:allow-modal-dialogs:
+ *
+ * Determine whether it's allowed to create and run modal dialogs
+ * from a #WebKitWebView through JavaScript with
+ * <function>window.showModalDialog</function>. If it's set to
+ * %FALSE, the associated #WebKitWebView won't be able to create
+ * new modal dialogs, so not even the #WebKitWebView::create
+ * signal will be emitted.
+ */
+ g_object_class_install_property(gObjectClass,
+ PROP_ALLOW_MODAL_DIALOGS,
+ g_param_spec_boolean("allow-modal-dialogs",
+ _("Allow modal dialogs"),
+ _("Whether it is possible to create modal dialogs"),
+ FALSE,
+ readWriteConstructParamFlags));
+
+ /**
* WebKitSettings:zoom-text-only:
*
* Whether #WebKitWebView:zoom-level affects only the
@@ -969,6 +996,7 @@ static void webkit_settings_init(WebKitSettings* settings)
void webkitSettingsAttachSettingsToPage(WebKitSettings* settings, WKPageRef wkPage)
{
WKPageGroupSetPreferences(WKPageGetPageGroup(wkPage), settings->priv->preferences.get());
+ WebKit::toImpl(wkPage)->setCanRunModal(settings->priv->allowModalDialogs);
}
/**
@@ -2189,6 +2217,39 @@ void webkit_settings_set_enable_webgl(WebKitSettings* settings, gboolean enabled
}
/**
+ * webkit_settings_set_allow_modal_dialogs:
+ * @settings: a #WebKitSettings
+ * @allowed: Value to be set
+ *
+ * Set the #WebKitSettings:allow-modal-dialogs property.
+ */
+void webkit_settings_set_allow_modal_dialogs(WebKitSettings* settings, gboolean allowed)
+{
+ g_return_if_fail(WEBKIT_IS_SETTINGS(settings));
+
+ WebKitSettingsPrivate* priv = settings->priv;
+ if (priv->allowModalDialogs == allowed)
+ return;
+
+ priv->allowModalDialogs = allowed;
+ g_object_notify(G_OBJECT(settings), "allow-modal-dialogs");
+}
+
+/**
+ * webkit_settings_get_allow_modal_dialogs:
+ * @settings: a #WebKitSettings
+ *
+ * Get the #WebKitSettings:allow-modal-dialogs property.
+ *
+ * Returns: %TRUE if it's allowed to create and run modal dialogs or %FALSE otherwise.
+ */
+gboolean webkit_settings_get_allow_modal_dialogs(WebKitSettings* settings)
+{
+ g_return_val_if_fail(WEBKIT_IS_SETTINGS(settings), FALSE);
+ return settings->priv->allowModalDialogs;
+}
+
+/**
* webkit_settings_set_zoom_text_only:
* @settings: a #WebKitSettings
* @zoom_text_only: Value to be set
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h
index 53ebda299..a86d6bc1e 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitSettings.h
@@ -308,6 +308,13 @@ webkit_settings_set_enable_webgl (WebKitSettings *
gboolean enabled);
WEBKIT_API void
+webkit_settings_set_allow_modal_dialogs (WebKitSettings *settings,
+ gboolean allowed);
+
+WEBKIT_API gboolean
+webkit_settings_get_allow_modal_dialogs (WebKitSettings *settings);
+
+WEBKIT_API void
webkit_settings_set_zoom_text_only (WebKitSettings *settings,
gboolean zoom_text_only);
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp
index 7d4eedfb6..1d985d342 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp
@@ -151,6 +151,11 @@ static void decidePolicyForGeolocationPermissionRequest(WKPageRef, WKFrameRef, W
webkitWebViewMakePermissionRequest(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_PERMISSION_REQUEST(geolocationPermissionRequest.get()));
}
+static void runModal(WKPageRef page, const void* clientInfo)
+{
+ webkitWebViewRunAsModal(WEBKIT_WEB_VIEW(clientInfo));
+}
+
void attachUIClientToView(WebKitWebView* webView)
{
WKPageUIClient wkUIClient = {
@@ -191,7 +196,7 @@ void attachUIClientToView(WebKitWebView* webView)
0, // drawHeader
0, // drawFooter
printFrame,
- 0, // runModal
+ runModal,
0, // didCompleteRubberBandForMainFrame
0, // saveDataToFileInDownloadsFolder
0, // shouldInterruptJavaScript
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
index 7f5764e7d..94a94ca09 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
@@ -25,6 +25,8 @@
#include "WebContextMenuItemData.h"
#include "WebKitBackForwardListPrivate.h"
#include "WebKitContextMenuClient.h"
+#include "WebKitContextMenuItemPrivate.h"
+#include "WebKitContextMenuPrivate.h"
#include "WebKitEnumTypes.h"
#include "WebKitError.h"
#include "WebKitFullscreenClient.h"
@@ -50,6 +52,7 @@
#include "WebPageProxy.h"
#include <JavaScriptCore/APICast.h>
#include <WebCore/DragIcon.h>
+#include <WebCore/GOwnPtrGtk.h>
#include <WebCore/GtkUtilities.h>
#include <glib/gi18n-lib.h>
#include <wtf/gobject/GOwnPtr.h>
@@ -65,6 +68,7 @@ enum {
CREATE,
READY_TO_SHOW,
+ RUN_AS_MODAL,
CLOSE,
SCRIPT_DIALOG,
@@ -83,6 +87,8 @@ enum {
RUN_FILE_CHOOSER,
+ CONTEXT_MENU,
+
LAST_SIGNAL
};
@@ -118,6 +124,8 @@ struct _WebKitWebViewPrivate {
GRefPtr<WebKitSettings> settings;
GRefPtr<WebKitWindowProperties> windowProperties;
+ GRefPtr<GMainLoop> modalLoop;
+
GRefPtr<WebKitHitTestResult> mouseTargetHitTestResult;
unsigned mouseTargetModifiers;
@@ -223,6 +231,14 @@ static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionR
return TRUE;
}
+static void allowModalDialogsChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
+{
+ WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
+ if (!page)
+ return;
+ page->setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings));
+}
+
static void zoomTextOnlyChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
{
WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
@@ -236,9 +252,18 @@ static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* set
{
webView->priv->settings = settings;
webkitSettingsAttachSettingsToPage(webView->priv->settings.get(), wkPage);
+ g_signal_connect(settings, "notify::allow-modal-dialogs", G_CALLBACK(allowModalDialogsChanged), webView);
g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView);
}
+static void webkitWebViewDisconnectSettingsSignalHandlers(WebKitWebView* webView)
+{
+ WebKitSettings* settings = webView->priv->settings.get();
+ g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(allowModalDialogsChanged), webView);
+ g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView);
+
+}
+
static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request)
{
GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request);
@@ -353,8 +378,16 @@ static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* valu
static void webkitWebViewFinalize(GObject* object)
{
WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(object)->priv;
+
if (priv->javascriptGlobalContext)
JSGlobalContextRelease(priv->javascriptGlobalContext);
+
+ // For modal dialogs, make sure the main loop is stopped when finalizing the webView.
+ if (priv->modalLoop && g_main_loop_is_running(priv->modalLoop.get()))
+ g_main_loop_quit(priv->modalLoop.get());
+
+ webkitWebViewDisconnectSettingsSignalHandlers(WEBKIT_WEB_VIEW(object));
+
priv->~WebKitWebViewPrivate();
G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
}
@@ -604,6 +637,27 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ /**
+ * WebKitWebView::run-as-modal:
+ * @web_view: the #WebKitWebView on which the signal is emitted
+ *
+ * Emitted after #WebKitWebView::ready-to-show on the newly
+ * created #WebKitWebView when JavaScript code calls
+ * <function>window.showModalDialog</function>. The purpose of
+ * this signal is to allow the client application to prepare the
+ * new view to behave as modal. Once the signal is emitted a new
+ * mainloop will be run to block user interaction in the parent
+ * #WebKitWebView until the new dialog is closed.
+ */
+ signals[RUN_AS_MODAL] =
+ g_signal_new("run-as-modal",
+ G_TYPE_FROM_CLASS(webViewClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebViewClass, run_as_modal),
+ 0, 0,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
/**
* WebKitWebView::close:
* @webView: the #WebKitWebView on which the signal is emitted
@@ -933,6 +987,62 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
webkit_marshal_BOOLEAN__OBJECT,
G_TYPE_BOOLEAN, 1, /* number of parameters */
WEBKIT_TYPE_FILE_CHOOSER_REQUEST);
+
+ /**
+ * WebKitWebView::context-menu:
+ * @web_view: the #WebKitWebView on which the signal is emitted
+ * @context_menu: the proposed #WebKitContextMenu
+ * @event: the #GdkEvent that triggered the context menu
+ * @hit_test_result: a #WebKitHitTestResult
+ *
+ * Emmited when a context menu is about to be displayed to give the application
+ * a chance to customize the proposed menu, prevent the menu from being displayed
+ * or build its own context menu.
+ * <itemizedlist>
+ * <listitem><para>
+ * To customize the proposed menu you can use webkit_context_menu_prepend(),
+ * webkit_context_menu_append() or webkit_context_menu_insert() to add new
+ * #WebKitContextMenuItem<!-- -->s to @context_menu, webkit_context_menu_move_item()
+ * to reorder existing items, or webkit_context_menu_remove() to remove an
+ * existing item. The signal handler should return %FALSE, and the menu represented
+ * by @context_menu will be shown.
+ * </para></listitem>
+ * <listitem><para>
+ * To prevent the menu from being displayed you can just connect to this signal
+ * and return %TRUE so that the proposed menu will not be shown.
+ * </para></listitem>
+ * <listitem><para>
+ * To build your own menu, you can remove all items from the proposed menu with
+ * webkit_context_menu_remove_all(), add your own items and return %FALSE so
+ * that the menu will be shown. You can also ignore the proposed #WebKitContextMenu,
+ * build your own #GtkMenu and return %TRUE to prevent the proposed menu from being shown.
+ * </para></listitem>
+ * <listitem><para>
+ * If you just want the default menu to be shown always, simply don't connect to this
+ * signal because showing the proposed context menu is the default behaviour.
+ * </para></listitem>
+ * </itemizedlist>
+ *
+ * If the signal handler returns %FALSE the context menu represented by @context_menu
+ * will be shown, if it return %TRUE the context menu will not be shown.
+ *
+ * The proposed #WebKitContextMenu passed in @context_menu argument is only valid
+ * during the signal emission.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ */
+ signals[CONTEXT_MENU] =
+ g_signal_new("context-menu",
+ G_TYPE_FROM_CLASS(webViewClass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(WebKitWebViewClass, context_menu),
+ g_signal_accumulator_true_handled, 0,
+ webkit_marshal_BOOLEAN__OBJECT_BOXED_OBJECT,
+ G_TYPE_BOOLEAN, 3,
+ WEBKIT_TYPE_CONTEXT_MENU,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
+ WEBKIT_TYPE_HIT_TEST_RESULT);
}
static bool updateReplaceContentStatus(WebKitWebView* webView, WebKitLoadEvent loadEvent)
@@ -1034,6 +1144,16 @@ void webkitWebViewReadyToShowPage(WebKitWebView* webView)
g_signal_emit(webView, signals[READY_TO_SHOW], 0, NULL);
}
+void webkitWebViewRunAsModal(WebKitWebView* webView)
+{
+ g_signal_emit(webView, signals[RUN_AS_MODAL], 0, NULL);
+
+ webView->priv->modalLoop = adoptGRef(g_main_loop_new(0, FALSE));
+ GDK_THREADS_ENTER();
+ g_main_loop_run(webView->priv->modalLoop.get());
+ GDK_THREADS_LEAVE();
+}
+
void webkitWebViewClosePage(WebKitWebView* webView)
{
g_signal_emit(webView, signals[CLOSE], 0, NULL);
@@ -1172,14 +1292,6 @@ void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChoose
g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue);
}
-static void webkitWebViewCreateAndAppendDefaultMenuItems(WebKitWebView* webView, WKArrayRef wkProposedMenu, Vector<ContextMenuItem>& contextMenuItems)
-{
- for (size_t i = 0; i < WKArrayGetSize(wkProposedMenu); ++i) {
- WKContextMenuItemRef wkItem = static_cast<WKContextMenuItemRef>(WKArrayGetItemAtIndex(wkProposedMenu, i));
- contextMenuItems.append(toImpl(wkItem)->data()->core());
- }
-}
-
static bool webkitWebViewShouldShowInputMethodsMenu(WebKitWebView* webView)
{
GtkSettings* settings = gtk_widget_get_settings(GTK_WIDGET(webView));
@@ -1191,33 +1303,65 @@ static bool webkitWebViewShouldShowInputMethodsMenu(WebKitWebView* webView)
return showInputMethodMenu;
}
-static void webkitWebViewCreateAndAppendInputMethodsMenuItem(WebKitWebView* webView, Vector<ContextMenuItem>& contextMenuItems)
+static int getUnicodeMenuItemPosition(WebKitContextMenu* contextMenu)
+{
+ GList* items = webkit_context_menu_get_items(contextMenu);
+ GList* iter;
+ int i = 0;
+ for (iter = items, i = 0; iter; iter = g_list_next(iter), ++i) {
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(iter->data);
+
+ if (webkit_context_menu_item_is_separator(item))
+ continue;
+ if (webkit_context_menu_item_get_stock_action(item) == WEBKIT_CONTEXT_MENU_ACTION_UNICODE)
+ return i;
+ }
+ return -1;
+}
+
+static void webkitWebViewCreateAndAppendInputMethodsMenuItem(WebKitWebView* webView, WebKitContextMenu* contextMenu)
{
if (!webkitWebViewShouldShowInputMethodsMenu(webView))
return;
+ // Place the im context menu item right before the unicode menu item
+ // if it's present.
+ int unicodeMenuItemPosition = getUnicodeMenuItemPosition(contextMenu);
+ if (unicodeMenuItemPosition == -1)
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
+
GtkIMContext* imContext = webkitWebViewBaseGetIMContext(WEBKIT_WEB_VIEW_BASE(webView));
GtkMenu* imContextMenu = GTK_MENU(gtk_menu_new());
gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(imContext), GTK_MENU_SHELL(imContextMenu));
- ContextMenu subMenu(imContextMenu);
-
- ContextMenuItem separator(SeparatorType, ContextMenuItemTagNoAction, String());
- contextMenuItems.append(separator);
- ContextMenuItem menuItem(SubmenuType, ContextMenuItemTagNoAction, _("Input _Methods"), &subMenu);
- contextMenuItems.append(menuItem);
+ WebKitContextMenuItem* menuItem = webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS);
+ webkitContextMenuItemSetSubMenuFromGtkMenu(menuItem, imContextMenu);
+ webkit_context_menu_insert(contextMenu, menuItem, unicodeMenuItemPosition);
}
void webkitWebViewPopulateContextMenu(WebKitWebView* webView, WKArrayRef wkProposedMenu, WKHitTestResultRef wkHitTestResult)
{
- WebContextMenuProxyGtk* contextMenu = webkitWebViewBaseGetActiveContextMenuProxy(WEBKIT_WEB_VIEW_BASE(webView));
- ASSERT(contextMenu);
+ WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
+ WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase);
+ ASSERT(contextMenuProxy);
- Vector<ContextMenuItem> contextMenuItems;
- webkitWebViewCreateAndAppendDefaultMenuItems(webView, wkProposedMenu, contextMenuItems);
+ GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(wkProposedMenu));
if (WKHitTestResultIsContentEditable(wkHitTestResult))
- webkitWebViewCreateAndAppendInputMethodsMenuItem(webView, contextMenuItems);
+ webkitWebViewCreateAndAppendInputMethodsMenuItem(webView, contextMenu.get());
+
+ GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(wkHitTestResult));
+ GOwnPtr<GdkEvent> contextMenuEvent(webkitWebViewBaseTakeContextMenuEvent(webViewBase));
+
+ gboolean returnValue;
+ g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), contextMenuEvent.get(), hitTestResult.get(), &returnValue);
+ if (returnValue)
+ return;
+
+ Vector<ContextMenuItem> contextMenuItems;
+ webkitContextMenuPopulate(contextMenu.get(), contextMenuItems);
+ contextMenuProxy->populate(contextMenuItems);
- contextMenu->populate(contextMenuItems);
+ // Clear the menu to make sure it's useless after signal emission.
+ webkit_context_menu_remove_all(contextMenu.get());
}
/**
@@ -1684,7 +1828,7 @@ void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settin
if (webView->priv->settings == settings)
return;
- g_signal_handlers_disconnect_by_func(webView->priv->settings.get(), reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView);
+ webkitWebViewDisconnectSettingsSignalHandlers(webView);
webkitWebViewSetSettings(webView, settings, toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
index 716fbbd08..9328fa12f 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
@@ -136,6 +136,7 @@ struct _WebKitWebViewClass {
GtkWidget *(* create) (WebKitWebView *web_view);
void (* ready_to_show) (WebKitWebView *web_view);
+ void (* run_as_modal) (WebKitWebView *web_view);
void (* close) (WebKitWebView *web_view);
gboolean (* script_dialog) (WebKitWebView *web_view,
@@ -158,6 +159,10 @@ struct _WebKitWebViewClass {
gboolean (* leave_fullscreen) (WebKitWebView *web_view);
gboolean (* run_file_chooser) (WebKitWebView *web_view,
WebKitFileChooserRequest *request);
+ gboolean (* context_menu) (WebKitWebView *web_view,
+ WebKitContextMenu *context_menu,
+ GdkEvent *event,
+ WebKitHitTestResult *hit_test_result);
/* Padding for future expansion */
void (*_webkit_reserved0) (void);
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
index a2cc1d97b..b7ffc98b8 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
@@ -46,6 +46,7 @@
#include <WebCore/DataObjectGtk.h>
#include <WebCore/DragData.h>
#include <WebCore/DragIcon.h>
+#include <WebCore/GOwnPtrGtk.h>
#include <WebCore/GtkClickCounter.h>
#include <WebCore/GtkDragAndDropHelper.h>
#include <WebCore/GtkUtilities.h>
@@ -94,6 +95,7 @@ struct _WebKitWebViewBasePrivate {
#endif
GtkWidget* inspectorView;
unsigned inspectorViewHeight;
+ GOwnPtr<GdkEvent> contextMenuEvent;
WebContextMenuProxyGtk* activeContextMenuProxy;
};
@@ -448,6 +450,10 @@ static gboolean webkitWebViewBaseButtonPressEvent(GtkWidget* widget, GdkEventBut
if (!priv->clickCounter.shouldProcessButtonEvent(buttonEvent))
return TRUE;
+
+ // If it's a right click event save it as a possible context menu event.
+ if (buttonEvent->button == 3)
+ priv->contextMenuEvent.set(gdk_event_copy(reinterpret_cast<GdkEvent*>(buttonEvent)));
priv->pageProxy->handleMouseEvent(NativeWebMouseEvent(reinterpret_cast<GdkEvent*>(buttonEvent),
priv->clickCounter.clickCountForGdkButtonEvent(widget, buttonEvent)));
return TRUE;
@@ -784,3 +790,8 @@ WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebView
{
return webkitWebViewBase->priv->activeContextMenuProxy;
}
+
+GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase* webkitWebViewBase)
+{
+ return webkitWebViewBase->priv->contextMenuEvent.release();
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
index 45ffbf283..70cc72575 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
@@ -49,5 +49,6 @@ void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase*, const WKFul
void webkitWebViewBaseSetInspectorViewHeight(WebKitWebViewBase*, unsigned height);
void webkitWebViewBaseSetActiveContextMenuProxy(WebKitWebViewBase*, WebContextMenuProxyGtk*);
WebContextMenuProxyGtk* webkitWebViewBaseGetActiveContextMenuProxy(WebKitWebViewBase*);
+GdkEvent* webkitWebViewBaseTakeContextMenuEvent(WebKitWebViewBase*);
#endif // WebKitWebViewBasePrivate_h
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h
index aedcdee6e..b602f4fe0 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h
@@ -38,6 +38,7 @@ void webkitWebViewSetTitle(WebKitWebView*, const CString&);
void webkitWebViewUpdateURI(WebKitWebView*);
WKPageRef webkitWebViewCreateNewPage(WebKitWebView*, WKDictionaryRef wkWindowFeatures);
void webkitWebViewReadyToShowPage(WebKitWebView*);
+void webkitWebViewRunAsModal(WebKitWebView*);
void webkitWebViewClosePage(WebKitWebView*);
void webkitWebViewRunJavaScriptAlert(WebKitWebView*, const CString& message);
bool webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message);
diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml
index c2eebf36c..6b62d6f69 100644
--- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml
+++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml
@@ -37,6 +37,8 @@
<xi:include href="xml/WebKitWebInspector.xml"/>
<xi:include href="xml/WebKitURISchemeRequest.xml"/>
<xi:include href="xml/WebKitVersion.xml"/>
+ <xi:include href="xml/WebKitContextMenu.xml"/>
+ <xi:include href="xml/WebKitContextMenuItem.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 1b97de88f..aca34df0b 100644
--- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt
+++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt
@@ -256,6 +256,8 @@ webkit_settings_get_enable_webaudio
webkit_settings_set_enable_webaudio
webkit_settings_get_enable_webgl
webkit_settings_set_enable_webgl
+webkit_settings_set_allow_modal_dialogs
+webkit_settings_get_allow_modal_dialogs
webkit_settings_get_zoom_text_only
webkit_settings_set_zoom_text_only
webkit_settings_get_javascript_can_access_clipboard
@@ -744,3 +746,63 @@ WEBKIT_MINOR_VERSION
WEBKIT_MICRO_VERSION
WEBKIT_CHECK_VERSION
</SECTION>
+
+<SECTION>
+<FILE>WebKitContextMenu</FILE>
+WebKitContextMenu
+webkit_context_menu_new
+webkit_context_menu_new_with_items
+webkit_context_menu_prepend
+webkit_context_menu_append
+webkit_context_menu_insert
+webkit_context_menu_move_item
+webkit_context_menu_get_items
+webkit_context_menu_get_n_items
+webkit_context_menu_first
+webkit_context_menu_last
+webkit_context_menu_get_item_at_position
+webkit_context_menu_remove
+webkit_context_menu_remove_all
+
+<SUBSECTION Standard>
+WebKitContextMenuClass
+WEBKIT_TYPE_CONTEXT_MENU
+WEBKIT_CONTEXT_MENU
+WEBKIT_IS_CONTEXT_MENU
+WEBKIT_CONTEXT_MENU_CLASS
+WEBKIT_IS_CONTEXT_MENU_CLASS
+WEBKIT_CONTEXT_MENU_GET_CLASS
+
+<SUBSECTION Private>
+WebKitContextMenuPrivate
+webkit_context_menu_get_type
+</SECTION>
+
+<SECTION>
+<FILE>WebKitContextMenuItem</FILE>
+WebKitContextMenuItem
+WebKitContextMenuAction
+webkit_context_menu_item_new
+webkit_context_menu_item_new_from_stock_action
+webkit_context_menu_item_new_from_stock_action_with_label
+webkit_context_menu_item_new_with_submenu
+webkit_context_menu_item_new_separator
+webkit_context_menu_item_get_action
+webkit_context_menu_item_get_stock_action
+webkit_context_menu_item_is_separator
+webkit_context_menu_item_set_submenu
+webkit_context_menu_item_get_submenu
+
+<SUBSECTION Standard>
+WebKitContextMenuItemClass
+WEBKIT_TYPE_CONTEXT_MENU_ITEM
+WEBKIT_CONTEXT_MENU_ITEM
+WEBKIT_IS_CONTEXT_MENU_ITEM
+WEBKIT_CONTEXT_MENU_ITEM_CLASS
+WEBKIT_IS_CONTEXT_MENU_ITEM_CLASS
+WEBKIT_CONTEXT_MENU_ITEM_GET_CLASS
+
+<SUBSECTION Private>
+WebKitContextMenuItemPrivate
+webkit_context_menu_item_get_type
+</SECTION>
diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
index d155982f2..4d8843e9c 100644
--- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
+++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
@@ -19,3 +19,5 @@ webkit_plugin_get_type
webkit_mime_info_get_type
webkit_web_inspector_get_type
webkit_uri_scheme_request_get_type
+webkit_context_menu_get_type
+webkit_context_menu_item_get_type
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am
index 7adae8adc..058a613f1 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am
@@ -2,6 +2,7 @@ if ENABLE_WEBKIT2
TEST_PROGS += \
Programs/WebKit2APITests/TestBackForwardList \
+ Programs/WebKit2APITests/TestContextMenu \
Programs/WebKit2APITests/TestCookieManager \
Programs/WebKit2APITests/TestDownloads \
Programs/WebKit2APITests/TestInspector \
@@ -167,4 +168,10 @@ Programs_WebKit2APITests_TestWebKitVersion_CPPFLAGS = $(webkit2_tests_cppflags)
Programs_WebKit2APITests_TestWebKitVersion_LDADD = $(webkit2_tests_ldadd)
Programs_WebKit2APITests_TestWebKitVersion_LDFLAGS = $(webkit2_tests_ldflags)
+Programs_WebKit2APITests_TestContextMenu_SOURCES = \
+ Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp
+Programs_WebKit2APITests_TestContextMenu_CPPFLAGS = $(webkit2_tests_cppflags)
+Programs_WebKit2APITests_TestContextMenu_LDADD = $(webkit2_tests_ldadd)
+Programs_WebKit2APITests_TestContextMenu_LDFLAGS = $(webkit2_tests_ldflags)
+
endif # ENABLE_WEBKIT2
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp
new file mode 100644
index 000000000..f74016006
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "WebViewTest.h"
+#include <wtf/gobject/GRefPtr.h>
+
+class ContextMenuTest: public WebViewTest {
+public:
+ enum ContextMenuItemStateFlags {
+ Visible = 1 << 0,
+ Enabled = 1 << 1,
+ Checked = 1 << 2
+ };
+
+ void checkContextMenuEvent(GdkEvent* event)
+ {
+ g_assert(event);
+ g_assert_cmpint(event->type, ==, GDK_BUTTON_PRESS);
+ g_assert_cmpint(event->button.button, ==, 3);
+ g_assert_cmpint(event->button.x, ==, m_menuPositionX);
+ g_assert_cmpint(event->button.y, ==, m_menuPositionY);
+ }
+
+ static gboolean contextMenuCallback(WebKitWebView* webView, WebKitContextMenu* contextMenu, GdkEvent* event, WebKitHitTestResult* hitTestResult, ContextMenuTest* test)
+ {
+ g_assert(WEBKIT_IS_CONTEXT_MENU(contextMenu));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(contextMenu));
+ test->checkContextMenuEvent(event);
+ g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(hitTestResult));
+
+ return test->contextMenu(contextMenu, event, hitTestResult);
+ }
+
+ ContextMenuTest()
+ : m_menuPositionX(0)
+ , m_menuPositionY(0)
+ {
+ g_signal_connect(m_webView, "context-menu", G_CALLBACK(contextMenuCallback), this);
+ }
+
+ ~ContextMenuTest()
+ {
+ g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ }
+
+ virtual bool contextMenu(WebKitContextMenu*, GdkEvent*, WebKitHitTestResult*) = 0;
+
+ bool shouldShowInputMethodsMenu()
+ {
+ GtkSettings* settings = gtk_widget_get_settings(GTK_WIDGET(m_webView));
+ if (!settings)
+ return true;
+
+ gboolean showInputMethodMenu;
+ g_object_get(settings, "gtk-show-input-method-menu", &showInputMethodMenu, NULL);
+ return showInputMethodMenu;
+ }
+
+ void checkActionState(GtkAction* action, unsigned state)
+ {
+ if (state & Visible)
+ g_assert(gtk_action_get_visible(action));
+ else
+ g_assert(!gtk_action_get_visible(action));
+
+ if (state & Enabled)
+ g_assert(gtk_action_get_sensitive(action));
+ else
+ g_assert(!gtk_action_get_sensitive(action));
+
+ if (GTK_IS_TOGGLE_ACTION(action)) {
+ if (state & Checked)
+ g_assert(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
+ else
+ g_assert(!gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
+ }
+ }
+
+ GList* checkCurrentItemIsStockActionAndGetNext(GList* items, WebKitContextMenuAction stockAction, unsigned state)
+ {
+ g_assert(items);
+ g_assert(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data));
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(item));
+
+ GtkAction* action = webkit_context_menu_item_get_action(item);
+ g_assert(GTK_IS_ACTION(action));
+
+ g_assert_cmpint(webkit_context_menu_item_get_stock_action(item), ==, stockAction);
+
+ checkActionState(action, state);
+
+ return g_list_next(items);
+ }
+
+ GList* checkCurrentItemIsCustomActionAndGetNext(GList* items, const char* label, unsigned state)
+ {
+ g_assert(items);
+ g_assert(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data));
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(item));
+
+ GtkAction* action = webkit_context_menu_item_get_action(item);
+ g_assert(GTK_IS_ACTION(action));
+
+ g_assert_cmpint(webkit_context_menu_item_get_stock_action(item), ==, WEBKIT_CONTEXT_MENU_ACTION_CUSTOM);
+ g_assert_cmpstr(gtk_action_get_label(action), ==, label);
+
+ checkActionState(action, state);
+
+ return g_list_next(items);
+ }
+
+ GList* checkCurrentItemIsSubMenuAndGetNext(GList* items, const char* label, unsigned state, GList** subMenuIter)
+ {
+ g_assert(items);
+ g_assert(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data));
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(item));
+
+ GtkAction* action = webkit_context_menu_item_get_action(item);
+ g_assert(GTK_IS_ACTION(action));
+
+ g_assert_cmpstr(gtk_action_get_label(action), ==, label);
+ checkActionState(action, state);
+
+ WebKitContextMenu* subMenu = webkit_context_menu_item_get_submenu(item);
+ g_assert(WEBKIT_IS_CONTEXT_MENU(subMenu));
+ if (subMenuIter)
+ *subMenuIter = webkit_context_menu_get_items(subMenu);
+
+ return g_list_next(items);
+ }
+
+ GList* checkCurrentItemIsSeparatorAndGetNext(GList* items)
+ {
+ g_assert(items);
+ g_assert(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data));
+
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data);
+ g_assert(webkit_context_menu_item_is_separator(item));
+
+ return g_list_next(items);
+ }
+
+ static gboolean doRightClickIdleCallback(ContextMenuTest* test)
+ {
+ test->clickMouseButton(test->m_menuPositionX, test->m_menuPositionY, 3);
+ return FALSE;
+ }
+
+ void showContextMenuAtPositionAndWaitUntilFinished(int x, int y)
+ {
+ m_menuPositionX = x;
+ m_menuPositionY = y;
+ g_idle_add(reinterpret_cast<GSourceFunc>(doRightClickIdleCallback), this);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void showContextMenuAndWaitUntilFinished()
+ {
+ showContextMenuAtPositionAndWaitUntilFinished(0, 0);
+ }
+
+ double m_menuPositionX;
+ double m_menuPositionY;
+};
+
+class ContextMenuDefaultTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuDefaultTest);
+
+ enum DefaultMenuType {
+ Navigation,
+ Link,
+ Image,
+ LinkImage,
+ Video,
+ Editable
+ };
+
+ ContextMenuDefaultTest()
+ : m_expectedMenuType(Navigation)
+ {
+ }
+
+ bool contextMenu(WebKitContextMenu* contextMenu, GdkEvent* event, WebKitHitTestResult* hitTestResult)
+ {
+ GList* iter = webkit_context_menu_get_items(contextMenu);
+
+ switch (m_expectedMenuType) {
+ case Navigation:
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK, Visible);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD, Visible);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP, Visible);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD, Visible | Enabled);
+ break;
+ case Link:
+ g_assert(webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD, Visible | Enabled);
+ break;
+ case Image:
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD, Visible | Enabled);
+ break;
+ case LinkImage:
+ g_assert(webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD, Visible | Enabled);
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD, Visible | Enabled);
+ break;
+ case Video:
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN, Visible);
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW, Visible | Enabled);
+ break;
+ case Editable:
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_editable(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_CUT, Visible);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_PASTE, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DELETE, Visible);
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL, Visible | Enabled);
+ if (shouldShowInputMethodsMenu()) {
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_UNICODE, Visible | Enabled);
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (webkit_settings_get_enable_developer_extras(webkit_web_view_get_settings(m_webView))) {
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT, Visible | Enabled);
+ }
+ g_assert(!iter);
+
+ quitMainLoop();
+
+ return true;
+ }
+
+ DefaultMenuType m_expectedMenuType;
+};
+
+static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ const char* linksHTML =
+ "<html><body>"
+ " <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>"
+ " <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>"
+ " <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='0xdeadbeef' width=5 height=5></img></a>"
+ " <video style='position:absolute; left:1; top:30' width=10 height=10 controls='controls'><source src='movie.ogg' type='video/ogg' /></video>"
+ " <input style='position:absolute; left:1; top:50' size='10'></input>"
+ "</body></html>";
+ test->loadHtml(linksHTML, "file:///");
+ test->waitUntilLoadFinished();
+
+ // Context menu for document.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Navigation;
+ test->showContextMenuAtPositionAndWaitUntilFinished(0, 0);
+
+ // Context menu for link.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Link;
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 1);
+
+ // Context menu for image.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Image;
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 10);
+
+ // Enable developer extras now, so that inspector element
+ // will be shown in the default context menu.
+ webkit_settings_set_enable_developer_extras(webkit_web_view_get_settings(test->m_webView), TRUE);
+
+ // Context menu for image link.
+ test->m_expectedMenuType = ContextMenuDefaultTest::LinkImage;
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 20);
+
+ // Context menu for image video.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Video;
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 30);
+
+ // Context menu for editable.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Editable;
+ test->showContextMenuAtPositionAndWaitUntilFinished(5, 55);
+}
+
+class ContextMenuCustomTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuCustomTest);
+
+ ContextMenuCustomTest()
+ : m_itemToActivateLabel(0)
+ , m_activated(false)
+ , m_toggled(false)
+ {
+ }
+
+ bool contextMenu(WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult* hitTestResult)
+ {
+ // Append our custom item to the default menu.
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new(m_action.get()));
+ quitMainLoop();
+
+ return false;
+ }
+
+ GtkMenu* getPopupMenu()
+ {
+ GOwnPtr<GList> toplevels(gtk_window_list_toplevels());
+ for (GList* iter = toplevels.get(); iter; iter = g_list_next(iter)) {
+ if (!GTK_IS_WINDOW(iter->data))
+ continue;
+
+ GtkWidget* child = gtk_bin_get_child(GTK_BIN(iter->data));
+ if (!GTK_IS_MENU(child))
+ continue;
+
+ if (gtk_menu_get_attach_widget(GTK_MENU(child)) == GTK_WIDGET(m_webView))
+ return GTK_MENU(child);
+ }
+ g_assert_not_reached();
+ return 0;
+ }
+
+ GtkMenuItem* getMenuItem(GtkMenu* menu, const gchar* itemLabel)
+ {
+ GOwnPtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu)));
+ for (GList* iter = items.get(); iter; iter = g_list_next(iter)) {
+ GtkMenuItem* child = GTK_MENU_ITEM(iter->data);
+ if (g_str_equal(itemLabel, gtk_menu_item_get_label(child)))
+ return child;
+ }
+ g_assert_not_reached();
+ return 0;
+ }
+
+ void activateMenuItem()
+ {
+ g_assert(m_itemToActivateLabel);
+ GtkMenu* menu = getPopupMenu();
+ GtkMenuItem* item = getMenuItem(menu, m_itemToActivateLabel);
+ gtk_menu_shell_activate_item(GTK_MENU_SHELL(menu), GTK_WIDGET(item), TRUE);
+ m_itemToActivateLabel = 0;
+ quitMainLoop();
+ }
+
+ static gboolean activateMenuItemIdleCallback(gpointer userData)
+ {
+ ContextMenuCustomTest* test = static_cast<ContextMenuCustomTest*>(userData);
+ test->activateMenuItem();
+ return FALSE;
+ }
+
+ void activateCustomMenuItemAndWaitUntilActivated(const char* actionLabel)
+ {
+ m_activated = m_toggled = false;
+ m_itemToActivateLabel = actionLabel;
+ g_idle_add(activateMenuItemIdleCallback, this);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void toggleCustomMenuItemAndWaitUntilToggled(const char* actionLabel)
+ {
+ activateCustomMenuItemAndWaitUntilActivated(actionLabel);
+ }
+
+ static void actionActivatedCallback(GtkAction*, ContextMenuCustomTest* test)
+ {
+ test->m_activated = true;
+ }
+
+ static void actionToggledCallback(GtkAction*, ContextMenuCustomTest* test)
+ {
+ test->m_toggled = true;
+ }
+
+ void setAction(GtkAction* action)
+ {
+ m_action = action;
+ if (GTK_IS_TOGGLE_ACTION(action))
+ g_signal_connect(action, "toggled", G_CALLBACK(actionToggledCallback), this);
+ else
+ g_signal_connect(action, "activate", G_CALLBACK(actionActivatedCallback), this);
+ }
+
+ GRefPtr<GtkAction> m_action;
+ const char* m_itemToActivateLabel;
+ bool m_activated;
+ bool m_toggled;
+};
+
+static void testContextMenuPopulateMenu(ContextMenuCustomTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>", "file:///");
+ test->waitUntilLoadFinished();
+
+ // Create a custom menu item.
+ GRefPtr<GtkAction> action = adoptGRef(gtk_action_new("WebKitGTK+CustomAction", "Custom _Action", 0, 0));
+ test->setAction(action.get());
+ test->showContextMenuAndWaitUntilFinished();
+ test->activateCustomMenuItemAndWaitUntilActivated(gtk_action_get_label(action.get()));
+ g_assert(test->m_activated);
+ g_assert(!test->m_toggled);
+
+ // Create a custom toggle menu item.
+ GRefPtr<GtkAction> toggleAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new("WebKitGTK+CustomToggleAction", "Custom _Toggle Action", 0, 0)));
+ test->setAction(toggleAction.get());
+ test->showContextMenuAndWaitUntilFinished();
+ test->toggleCustomMenuItemAndWaitUntilToggled(gtk_action_get_label(toggleAction.get()));
+ g_assert(!test->m_activated);
+ g_assert(test->m_toggled);
+}
+
+class ContextMenuCustomFullTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuCustomFullTest);
+
+ bool contextMenu(WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult*)
+ {
+ // Clear proposed menu and build our own.
+ webkit_context_menu_remove_all(contextMenu);
+ g_assert_cmpint(webkit_context_menu_get_n_items(contextMenu), ==, 0);
+
+ // Add actions from stock.
+ webkit_context_menu_prepend(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_GO_BACK));
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD));
+ webkit_context_menu_insert(contextMenu, webkit_context_menu_item_new_separator(), 2);
+
+ // Add custom actions.
+ GRefPtr<GtkAction> action = adoptGRef(gtk_action_new("WebKitGTK+CustomAction", "Custom _Action", 0, 0));
+ gtk_action_set_sensitive(action.get(), FALSE);
+ webkit_context_menu_insert(contextMenu, webkit_context_menu_item_new(action.get()), -1);
+ GRefPtr<GtkAction> toggleAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new("WebKitGTK+CustomToggleAction", "Custom _Toggle Action", 0, 0)));
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggleAction.get()), TRUE);
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new(toggleAction.get()));
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
+
+ // Add a submenu.
+ GRefPtr<WebKitContextMenu> subMenu = adoptGRef(webkit_context_menu_new());
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(subMenu.get()));
+ webkit_context_menu_insert(subMenu.get(), webkit_context_menu_item_new_from_stock_action_with_label(WEBKIT_CONTEXT_MENU_ACTION_STOP, "Stop Load"), 0);
+ webkit_context_menu_insert(subMenu.get(), webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_RELOAD), -1);
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_with_submenu("Load options", subMenu.get()));
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
+
+ // Move Load submenu before custom actions.
+ webkit_context_menu_move_item(contextMenu, webkit_context_menu_last(contextMenu), 3);
+ webkit_context_menu_move_item(contextMenu, webkit_context_menu_last(contextMenu), 3);
+
+ // If last item is a separator, remove it.
+ if (webkit_context_menu_item_is_separator(webkit_context_menu_last(contextMenu)))
+ webkit_context_menu_remove(contextMenu, webkit_context_menu_last(contextMenu));
+
+ // Check the menu.
+ GList* iter = webkit_context_menu_get_items(contextMenu);
+
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK, Visible | Enabled);
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD, Visible | Enabled);
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+
+ GList* subMenuIter = 0;
+ iter = checkCurrentItemIsSubMenuAndGetNext(iter, "Load options", Visible | Enabled, &subMenuIter);
+ subMenuIter = checkCurrentItemIsStockActionAndGetNext(subMenuIter, WEBKIT_CONTEXT_MENU_ACTION_STOP, Visible | Enabled);
+ subMenuIter = checkCurrentItemIsStockActionAndGetNext(subMenuIter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD, Visible | Enabled);
+ iter = checkCurrentItemIsSeparatorAndGetNext(iter);
+
+ iter = checkCurrentItemIsCustomActionAndGetNext(iter, "Custom _Action", Visible);
+ iter = checkCurrentItemIsCustomActionAndGetNext(iter, "Custom _Toggle Action", Visible | Enabled | Checked);
+ g_assert(!iter);
+
+ quitMainLoop();
+
+ return true;
+ }
+};
+
+static void testContextMenuCustomMenu(ContextMenuCustomFullTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>", "file:///");
+ test->waitUntilLoadFinished();
+
+ test->showContextMenuAndWaitUntilFinished();
+}
+
+class ContextMenuDisabledTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuDisabledTest);
+
+ enum DisableMode {
+ IgnoreClicks,
+ IgnoreDefaultMenu
+ };
+
+ static gboolean buttonPressEventCallback(GtkWidget*, GdkEvent* event, ContextMenuDisabledTest* test)
+ {
+ if (event->button.button != 3)
+ return FALSE;
+ return test->rightButtonPressed();
+ }
+
+ ContextMenuDisabledTest()
+ : m_disableMode(IgnoreClicks)
+ {
+ g_signal_connect(m_webView, "button-press-event", G_CALLBACK(buttonPressEventCallback), this);
+ }
+
+ bool contextMenu(WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult*)
+ {
+ if (m_disableMode == IgnoreClicks)
+ g_assert_not_reached();
+ else
+ quitMainLoop();
+
+ return true;
+ }
+
+ bool rightButtonPressed()
+ {
+ if (m_disableMode == IgnoreClicks) {
+ quitMainLoopAfterProcessingPendingEvents();
+ return true;
+ }
+ return false;
+ }
+
+ DisableMode m_disableMode;
+};
+
+static void testContextMenuDisableMenu(ContextMenuDisabledTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>", "file:///");
+ test->waitUntilLoadFinished();
+
+ test->m_disableMode = ContextMenuDisabledTest::IgnoreDefaultMenu;
+ test->showContextMenuAndWaitUntilFinished();
+
+ test->m_disableMode = ContextMenuDisabledTest::IgnoreClicks;
+ test->showContextMenuAndWaitUntilFinished();
+}
+
+class ContextMenuSubmenuTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuSubmenuTest);
+
+ bool contextMenu(WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult*)
+ {
+ size_t menuSize = webkit_context_menu_get_n_items(contextMenu);
+ GRefPtr<WebKitContextMenu> subMenu = adoptGRef(webkit_context_menu_new());
+ webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_with_submenu("SubMenuItem", subMenu.get()));
+ g_assert_cmpuint(webkit_context_menu_get_n_items(contextMenu), ==, menuSize + 1);
+
+ GRefPtr<WebKitContextMenu> subMenu2 = adoptGRef(webkit_context_menu_new());
+ GRefPtr<WebKitContextMenuItem> item = webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK);
+
+ // Add submenu to newly created item.
+ g_assert(!webkit_context_menu_item_get_submenu(item.get()));
+ webkit_context_menu_item_set_submenu(item.get(), subMenu2.get());
+ g_assert(webkit_context_menu_item_get_submenu(item.get()) == subMenu2.get());
+
+ // Replace the submenu.
+ webkit_context_menu_item_set_submenu(item.get(), 0);
+ g_assert(!webkit_context_menu_item_get_submenu(item.get()));
+
+ // Try to add a submenu already added to another item.
+ removeLogFatalFlag(G_LOG_LEVEL_WARNING);
+ webkit_context_menu_item_set_submenu(item.get(), subMenu.get());
+ addLogFatalFlag(G_LOG_LEVEL_WARNING);
+ g_assert(!webkit_context_menu_item_get_submenu(item.get()));
+
+ // A removed submenu shouldn't have a parent.
+ webkit_context_menu_item_set_submenu(item.get(), subMenu2.get());
+ g_assert(webkit_context_menu_item_get_submenu(item.get()) == subMenu2.get());
+
+ quitMainLoop();
+
+ return true;
+ }
+};
+
+static void testContextMenuSubMenu(ContextMenuSubmenuTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>", "file:///");
+ test->waitUntilLoadFinished();
+
+ test->showContextMenuAndWaitUntilFinished();
+}
+
+void beforeAll()
+{
+ ContextMenuDefaultTest::add("WebKitWebView", "default-menu", testContextMenuDefaultMenu);
+ ContextMenuCustomTest::add("WebKitWebView", "populate-menu", testContextMenuPopulateMenu);
+ ContextMenuCustomFullTest::add("WebKitWebView", "custom-menu", testContextMenuCustomMenu);
+ ContextMenuDisabledTest::add("WebKitWebView", "disable-menu", testContextMenuDisableMenu);
+ ContextMenuSubmenuTest::add("WebKitWebView", "submenu", testContextMenuSubMenu);
+}
+
+void afterAll()
+{
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h
index 219cb44ed..6929c3595 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestMain.h
@@ -75,6 +75,20 @@ public:
return resourcesDir.get();
}
+ void addLogFatalFlag(unsigned flag)
+ {
+ unsigned fatalMask = g_log_set_always_fatal(static_cast<GLogLevelFlags>(G_LOG_FATAL_MASK));
+ fatalMask |= flag;
+ g_log_set_always_fatal(static_cast<GLogLevelFlags>(fatalMask));
+ }
+
+ void removeLogFatalFlag(unsigned flag)
+ {
+ unsigned fatalMask = g_log_set_always_fatal(static_cast<GLogLevelFlags>(G_LOG_FATAL_MASK));
+ fatalMask &= ~flag;
+ g_log_set_always_fatal(static_cast<GLogLevelFlags>(fatalMask));
+ }
+
HashSet<GObject*> m_watchedObjects;
};
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFindController.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFindController.cpp
index ae9ff2f7a..a185db8a7 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFindController.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitFindController.cpp
@@ -324,8 +324,6 @@ static void testFindControllerHide(FindControllerTest* test, gconstpointer)
g_assert(highlightPixbuf);
g_assert(!gdkPixbufEqual(originalPixbuf.get(), highlightPixbuf.get()));
-#if (0)
- // Requires http://webkit.org/b/77747 to be fixed
WebKitFindController* findController = webkit_web_view_get_find_controller(test->m_webView);
webkit_find_controller_search_finish(findController);
webkit_web_view_execute_editing_command(test->m_webView, "Unselect");
@@ -334,7 +332,6 @@ static void testFindControllerHide(FindControllerTest* test, gconstpointer)
GRefPtr<GdkPixbuf> unhighlightPixbuf = gdk_pixbuf_get_from_window(webViewGdkWindow, 0, 0, allocatedHeight, allocatedWidth);
g_assert(unhighlightPixbuf);
g_assert(gdkPixbufEqual(originalPixbuf.get(), unhighlightPixbuf.get()));
-#endif
}
static void testFindControllerInstance(FindControllerTest* test, gconstpointer)
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp
index 4616d105f..2cebdd995 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitSettings.cpp
@@ -199,6 +199,11 @@ static void testWebKitSettings(Test*, gconstpointer)
webkit_settings_set_enable_webgl(settings, TRUE);
g_assert(webkit_settings_get_enable_webgl(settings));
+ // Allow Modal Dialogs is disabled by default.
+ g_assert(!webkit_settings_get_allow_modal_dialogs(settings));
+ webkit_settings_set_allow_modal_dialogs(settings, TRUE);
+ g_assert(webkit_settings_get_allow_modal_dialogs(settings));
+
// Zoom text only is disabled by default.
g_assert(!webkit_settings_get_zoom_text_only(settings));
webkit_settings_set_zoom_text_only(settings, TRUE);
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp
index 646752974..3e194a179 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp
@@ -103,6 +103,7 @@ public:
enum WebViewEvents {
Create,
ReadyToShow,
+ RunAsModal,
Close
};
@@ -178,46 +179,19 @@ public:
test->m_windowPropertiesChanged.add(g_param_spec_get_name(paramSpec));
}
- static void viewClose(WebKitWebView* webView, UIClientTest* test)
+ static GtkWidget* viewCreateCallback(WebKitWebView* webView, UIClientTest* test)
{
- g_assert(webView != test->m_webView);
-
- test->m_webViewEvents.append(Close);
- g_object_unref(webView);
-
- g_main_loop_quit(test->m_mainLoop);
+ return test->viewCreate(webView);
}
- static void viewReadyToShow(WebKitWebView* webView, UIClientTest* test)
+ static void viewReadyToShowCallback(WebKitWebView* webView, UIClientTest* test)
{
- g_assert(webView != test->m_webView);
-
- WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(webView);
- g_assert(windowProperties);
- WindowProperties(windowProperties).assertEqual(test->m_windowProperties);
-
- test->m_webViewEvents.append(ReadyToShow);
+ test->viewReadyToShow(webView);
}
- static GtkWidget* viewCreate(WebKitWebView* webView, UIClientTest* test)
+ static void viewCloseCallback(WebKitWebView* webView, UIClientTest* test)
{
- g_assert(webView == test->m_webView);
-
- GtkWidget* newWebView = webkit_web_view_new_with_context(webkit_web_view_get_context(webView));
- g_object_ref_sink(newWebView);
-
- test->m_webViewEvents.append(Create);
-
- WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(newWebView));
- g_assert(windowProperties);
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(windowProperties));
- test->m_windowPropertiesChanged.clear();
- g_signal_connect(windowProperties, "notify", G_CALLBACK(windowPropertiesNotifyCallback), test);
-
- g_signal_connect(newWebView, "ready-to-show", G_CALLBACK(viewReadyToShow), test);
- g_signal_connect(newWebView, "close", G_CALLBACK(viewClose), test);
-
- return newWebView;
+ test->viewClose(webView);
}
void scriptAlert(WebKitScriptDialog* dialog)
@@ -300,7 +274,7 @@ public:
, m_mouseTargetModifiers(0)
{
webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
- g_signal_connect(m_webView, "create", G_CALLBACK(viewCreate), this);
+ g_signal_connect(m_webView, "create", G_CALLBACK(viewCreateCallback), this);
g_signal_connect(m_webView, "script-dialog", G_CALLBACK(scriptDialog), this);
g_signal_connect(m_webView, "mouse-target-changed", G_CALLBACK(mouseTargetChanged), this);
g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequested), this);
@@ -328,6 +302,48 @@ public:
return m_mouseTargetHitTestResult.get();
}
+ virtual GtkWidget* viewCreate(WebKitWebView* webView)
+ {
+ g_assert(webView == m_webView);
+
+ GtkWidget* newWebView = webkit_web_view_new_with_context(webkit_web_view_get_context(webView));
+ g_object_ref_sink(newWebView);
+
+ m_webViewEvents.append(Create);
+
+ WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(newWebView));
+ g_assert(windowProperties);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(windowProperties));
+ m_windowPropertiesChanged.clear();
+
+ g_signal_connect(windowProperties, "notify", G_CALLBACK(windowPropertiesNotifyCallback), this);
+ g_signal_connect(newWebView, "ready-to-show", G_CALLBACK(viewReadyToShowCallback), this);
+ g_signal_connect(newWebView, "close", G_CALLBACK(viewCloseCallback), this);
+
+ return newWebView;
+ }
+
+ virtual void viewReadyToShow(WebKitWebView* webView)
+ {
+ g_assert(webView != m_webView);
+
+ WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(webView);
+ g_assert(windowProperties);
+ WindowProperties(windowProperties).assertEqual(m_windowProperties);
+
+ m_webViewEvents.append(ReadyToShow);
+ }
+
+ virtual void viewClose(WebKitWebView* webView)
+ {
+ g_assert(webView != m_webView);
+
+ m_webViewEvents.append(Close);
+ g_object_unref(webView);
+
+ g_main_loop_quit(m_mainLoop);
+ }
+
Vector<WebViewEvents> m_webViewEvents;
WebKitScriptDialogType m_scriptDialogType;
bool m_scriptDialogConfirmed;
@@ -358,6 +374,62 @@ static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeT
return gtk_file_filter_filter(filter, &filterInfo);
}
+class ModalDialogsTest: public UIClientTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ModalDialogsTest);
+
+ static void dialogRunAsModalCallback(WebKitWebView* webView, ModalDialogsTest* test)
+ {
+ g_assert(webView != test->m_webView);
+ test->m_webViewEvents.append(RunAsModal);
+ }
+
+ GtkWidget* viewCreate(WebKitWebView* webView)
+ {
+ g_assert(webView == m_webView);
+
+ GtkWidget* newWebView = UIClientTest::viewCreate(webView);
+ g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(dialogRunAsModalCallback), this);
+ return newWebView;
+ }
+
+ void viewReadyToShow(WebKitWebView* webView)
+ {
+ g_assert(webView != m_webView);
+ m_webViewEvents.append(ReadyToShow);
+ }
+};
+
+static void testWebViewAllowModalDialogs(ModalDialogsTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ webkit_settings_set_allow_modal_dialogs(settings, TRUE);
+
+ test->loadHtml("<html><body onload=\"window.showModalDialog('data:text/html,<html><body/><script>window.close();</script></html>')\"></body></html>", 0);
+ test->waitUntilMainLoopFinishes();
+
+ Vector<UIClientTest::WebViewEvents>& events = test->m_webViewEvents;
+ g_assert_cmpint(events.size(), ==, 4);
+ g_assert_cmpint(events[0], ==, UIClientTest::Create);
+ g_assert_cmpint(events[1], ==, UIClientTest::ReadyToShow);
+ g_assert_cmpint(events[2], ==, UIClientTest::RunAsModal);
+ g_assert_cmpint(events[3], ==, UIClientTest::Close);
+}
+
+static void testWebViewDisallowModalDialogs(ModalDialogsTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ webkit_settings_set_allow_modal_dialogs(settings, FALSE);
+
+ test->loadHtml("<html><body onload=\"window.showModalDialog('data:text/html,<html><body/><script>window.close();</script></html>')\"></body></html>", 0);
+ // We need to use a timeout here because the viewClose() function
+ // won't ever be called as the dialog won't be created.
+ test->wait(1);
+
+ Vector<UIClientTest::WebViewEvents>& events = test->m_webViewEvents;
+ g_assert_cmpint(events.size(), ==, 0);
+}
+
static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer)
{
static const char* htmlOnLoadFormat = "<html><body onLoad=\"%s\"></body></html>";
@@ -483,6 +555,10 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
{
+ // Some versions of geoclue give a runtime warning because it tries
+ // to register the error quark twice. See https://bugs.webkit.org/show_bug.cgi?id=89858.
+ // Make warnings non-fatal for this test to make it pass.
+ test->removeLogFatalFlag(G_LOG_LEVEL_WARNING);
test->showInWindowAndWaitUntilMapped();
static const char* geolocationRequestHTML =
"<html>"
@@ -515,6 +591,7 @@ static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
// Check that we did not get the PERMISSION_DENIED error now.
result = webkit_web_view_get_title(test->m_webView);
g_assert_cmpstr(result, !=, "1");
+ test->addLogFatalFlag(G_LOG_LEVEL_WARNING);
}
static void testWebViewZoomLevel(WebViewTest* test, gconstpointer)
@@ -795,6 +872,8 @@ void beforeAll()
WebViewTest::add("WebKitWebView", "settings", testWebViewSettings);
WebViewTest::add("WebKitWebView", "replace-content", testWebViewReplaceContent);
UIClientTest::add("WebKitWebView", "create-ready-close", testWebViewCreateReadyClose);
+ ModalDialogsTest::add("WebKitWebView", "allow-modal-dialogs", testWebViewAllowModalDialogs);
+ ModalDialogsTest::add("WebKitWebView", "disallow-modal-dialogs", testWebViewDisallowModalDialogs);
UIClientTest::add("WebKitWebView", "javascript-dialogs", testWebViewJavaScriptDialogs);
UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties);
UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget);
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
index e355f786d..321b6a37a 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
@@ -43,12 +43,6 @@ WebViewTest::~WebViewTest()
g_main_loop_unref(m_mainLoop);
}
-static gboolean testLoadTimeoutFinishLoop(GMainLoop* loop)
-{
- g_main_loop_quit(loop);
- return FALSE;
-}
-
void WebViewTest::loadURI(const char* uri)
{
m_activeURI = uri;
@@ -112,9 +106,27 @@ void WebViewTest::goToBackForwardListItem(WebKitBackForwardListItem* item)
webkit_web_view_go_to_back_forward_list_item(m_webView, item);
}
+void WebViewTest::quitMainLoop()
+{
+ g_main_loop_quit(m_mainLoop);
+}
+
+void WebViewTest::quitMainLoopAfterProcessingPendingEvents()
+{
+ while (gtk_events_pending())
+ gtk_main_iteration();
+ quitMainLoop();
+}
+
+static gboolean quitMainLoopIdleCallback(WebViewTest* test)
+{
+ test->quitMainLoop();
+ return FALSE;
+}
+
void WebViewTest::wait(double seconds)
{
- g_timeout_add_seconds(seconds, reinterpret_cast<GSourceFunc>(testLoadTimeoutFinishLoop), m_mainLoop);
+ g_timeout_add_seconds(seconds, reinterpret_cast<GSourceFunc>(quitMainLoopIdleCallback), this);
g_main_loop_run(m_mainLoop);
}
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
index ff6a8c737..8e469f142 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
@@ -40,6 +40,8 @@ public:
void goForward();
void goToBackForwardListItem(WebKitBackForwardListItem*);
+ void quitMainLoop();
+ void quitMainLoopAfterProcessingPendingEvents();
void wait(double seconds);
void waitUntilLoadFinished();
void waitUntilTitleChangedTo(const char* expectedTitle);
diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h
index bf37fcb73..58ac2b7e9 100644
--- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h
+++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h
@@ -25,6 +25,9 @@
#include <webkit2/WebKitBackForwardList.h>
#include <webkit2/WebKitBackForwardListItem.h>
+#include <webkit2/WebKitContextMenu.h>
+#include <webkit2/WebKitContextMenuActions.h>
+#include <webkit2/WebKitContextMenuItem.h>
#include <webkit2/WebKitCookieManager.h>
#include <webkit2/WebKitDefines.h>
#include <webkit2/WebKitDownload.h>
diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list
index de3032819..e6c8a1016 100644
--- a/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list
+++ b/Source/WebKit2/UIProcess/API/gtk/webkit2marshal.list
@@ -1,6 +1,7 @@
BOOLEAN:BOXED
BOOLEAN:ENUM,STRING,POINTER
BOOLEAN:OBJECT
+BOOLEAN:OBJECT,BOXED,OBJECT
BOOLEAN:OBJECT,ENUM
BOOLEAN:STRING
BOOLEAN:VOID
diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h
index ac074e8cc..8af6ff40c 100644
--- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h
+++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h
@@ -94,6 +94,10 @@ private:
virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*);
virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*);
+#if ENABLE(INPUT_TYPE_COLOR)
+ virtual PassRefPtr<WebColorChooserProxy> createColorChooserProxy(WebPageProxy*, const WebCore::Color& initialColor);
+#endif
+
void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut, bool animate);
virtual void enterAcceleratedCompositingMode(const LayerTreeContext&);
diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm
index 8d0913e52..3bd702078 100644
--- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm
+++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm
@@ -360,6 +360,14 @@ PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPagePr
return WebContextMenuProxyMac::create(m_wkView, page);
}
+#if ENABLE(INPUT_TYPE_COLOR)
+PassRefPtr<WebColorChooserProxy> PageClientImpl::createColorChooserProxy(WebPageProxy*, const WebCore::Color&)
+{
+ notImplemented();
+ return 0;
+}
+#endif
+
void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut, bool animate)
{
[m_wkView _setFindIndicator:findIndicator fadeOut:fadeOut animate:animate];
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
index c52da4df6..046d80339 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview.cpp
@@ -266,6 +266,7 @@ QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport)
, proxyAuthenticationDialog(0)
, filePicker(0)
, databaseQuotaDialog(0)
+ , colorChooser(0)
, m_useDefaultContentItemSize(true)
, m_navigatorQtObjectEnabled(false)
, m_renderToOffscreenBuffer(false)
@@ -1146,6 +1147,22 @@ void QQuickWebViewExperimental::setDatabaseQuotaDialog(QQmlComponent* databaseQu
emit databaseQuotaDialogChanged();
}
+QQmlComponent* QQuickWebViewExperimental::colorChooser() const
+{
+ Q_D(const QQuickWebView);
+ return d->colorChooser;
+}
+
+void QQuickWebViewExperimental::setColorChooser(QQmlComponent* colorChooser)
+{
+ Q_D(QQuickWebView);
+ if (d->colorChooser == colorChooser)
+ return;
+
+ d->colorChooser = colorChooser;
+ emit colorChooserChanged();
+}
+
QString QQuickWebViewExperimental::userAgent() const
{
Q_D(const QQuickWebView);
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
index b00e12e4b..e2c8c0dad 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p.h
@@ -265,6 +265,7 @@ class QWEBKIT_EXPORT QQuickWebViewExperimental : public QObject {
Q_PROPERTY(QQmlComponent* itemSelector READ itemSelector WRITE setItemSelector NOTIFY itemSelectorChanged)
Q_PROPERTY(QQmlComponent* filePicker READ filePicker WRITE setFilePicker NOTIFY filePickerChanged)
Q_PROPERTY(QQmlComponent* databaseQuotaDialog READ databaseQuotaDialog WRITE setDatabaseQuotaDialog NOTIFY databaseQuotaDialogChanged)
+ Q_PROPERTY(QQmlComponent* colorChooser READ colorChooser WRITE setColorChooser NOTIFY colorChooserChanged)
Q_PROPERTY(QWebPreferences* preferences READ preferences CONSTANT FINAL)
Q_PROPERTY(QWebKitTest* test READ test CONSTANT FINAL)
@@ -300,6 +301,8 @@ public:
void setFilePicker(QQmlComponent*);
QQmlComponent* databaseQuotaDialog() const;
void setDatabaseQuotaDialog(QQmlComponent*);
+ QQmlComponent* colorChooser() const;
+ void setColorChooser(QQmlComponent*);
QString userAgent() const;
void setUserAgent(const QString& userAgent);
int deviceWidth() const;
@@ -356,6 +359,7 @@ Q_SIGNALS:
void itemSelectorChanged();
void filePickerChanged();
void databaseQuotaDialogChanged();
+ void colorChooserChanged();
void downloadRequested(QWebDownloadItem* downloadItem);
void permissionRequested(QWebPermissionRequest* permission);
void messageReceived(const QVariantMap& message);
diff --git a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
index c5535a3c8..f102f6030 100644
--- a/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
+++ b/Source/WebKit2/UIProcess/API/qt/qquickwebview_p_p.h
@@ -185,6 +185,7 @@ protected:
QQmlComponent* proxyAuthenticationDialog;
QQmlComponent* filePicker;
QQmlComponent* databaseQuotaDialog;
+ QQmlComponent* colorChooser;
QList<QUrl> userScripts;
diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_colorChooser.qml b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_colorChooser.qml
new file mode 100644
index 000000000..366e7c00c
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/WebView/tst_colorChooser.qml
@@ -0,0 +1,94 @@
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebKit 3.0
+import QtWebKit.experimental 1.0
+import "../common"
+
+TestWebView {
+ id: webView
+
+ width: 400
+ height: 400
+
+ property bool featureEnabled
+
+ property string selectedColor
+ property bool shouldReject
+ property bool shouldAcceptCurrent
+
+ experimental.colorChooser: Item {
+ Component.onCompleted: {
+ if (WebView.view.shouldReject)
+ model.reject()
+ else if (WebView.view.shouldAcceptCurrent)
+ model.accept(model.currentColor)
+ else
+ model.accept(WebView.view.selectedColor)
+ }
+ }
+
+ function openColorChooser() {
+ webView.experimental.test.touchTap(webView, 25, 25)
+ }
+
+ SignalSpy {
+ id: titleSpy
+ target: webView
+ signalName: "titleChanged"
+ }
+
+ TestCase {
+ id: test
+ name: "WebViewColorChooser"
+ when: windowShown
+
+ function init() {
+ webView.url = Qt.resolvedUrl("../common/colorChooser.html")
+ verify(webView.waitForLoadSucceeded())
+
+ webView.featureEnabled = (webView.title == "Feature enabled")
+
+ titleSpy.clear()
+
+ webView.shouldReject = false;
+ webView.shouldAcceptCurrent = false;
+ }
+
+ function test_accept() {
+ if (!webView.featureEnabled)
+ return
+
+ // The title changes here twice: first
+ // when we click, it changes from "Feature enabled"
+ // to the sanitized color and next, when we
+ // pick a new color with the chooser.
+ webView.selectedColor = "#020020"
+ openColorChooser()
+ titleSpy.wait()
+ compare(titleSpy.count, 2)
+ compare(webView.title, "#020020")
+ }
+
+ function test_currentValue() {
+ if (!webView.featureEnabled)
+ return
+
+ webView.shouldAcceptCurrent = true
+ openColorChooser()
+ titleSpy.wait()
+ compare(titleSpy.count, 1)
+ compare(webView.title, "#000000")
+ }
+
+ function test_reject() {
+ if (!webView.featureEnabled)
+ return
+
+ webView.shouldReject = true;
+ openColorChooser()
+ titleSpy.wait()
+ compare(titleSpy.count, 1)
+ compare(webView.title, "#000000")
+ }
+ }
+}
diff --git a/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/colorChooser.html b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/colorChooser.html
new file mode 100644
index 000000000..b04710ab9
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/qt/tests/qmltests/common/colorChooser.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Feature disabled</title>
+<script>
+function detectInputTypeColorEnabled() {
+ var element = document.getElementById('test')
+ element.value = 'should sanitize';
+ if (element.value != 'should sanitize')
+ document.title = 'Feature enabled';
+}
+function updateTitle(element) {
+ document.title = element.value;
+}
+</script>
+</head>
+<body onload='detectInputTypeColorEnabled()'>
+<input id='test' type='color' onclick='updateTitle(this)' onchange='updateTitle(this)' style='width:50px; height:50px; position:"absolute"; top:0px; left:0px'>
+</html>