diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-06-25 13:35:59 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-06-25 13:35:59 +0200 |
commit | 79ad030d505ccf79cf10aa9f8189ca3e2f61f6f4 (patch) | |
tree | 0287b1a69d84492c901e8bc820e635e7133809a0 /Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp | |
parent | 682ab87480e7757346802ce7f54cfdbdfeb2339e (diff) | |
download | qtwebkit-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/gtk/tests/TestContextMenu.cpp')
-rw-r--r-- | Source/WebKit2/UIProcess/API/gtk/tests/TestContextMenu.cpp | 671 |
1 files changed, 671 insertions, 0 deletions
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() +{ +} |