1/*
2    Copyright (C) 2012 Samsung Electronics
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public License
15    along with this library; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18
19#include "config.h"
20
21#include "UnitTestUtils/EWK2UnitTestBase.h"
22#include "UnitTestUtils/EWK2UnitTestEnvironment.h"
23#include <EWebKit2.h>
24#include <Ecore.h>
25
26using namespace EWK2UnitTest;
27
28extern EWK2UnitTestEnvironment* environment;
29
30static bool testFinished = false;
31
32static const Ewk_Context_Menu_Item_Type customItemType = EWK_ACTION_TYPE;
33static const Ewk_Context_Menu_Item_Action customItemTag = EWK_CONTEXT_MENU_ITEM_BASE_APPLICATION_TAG;
34static const char customItemTitle[] = "Custom Item";
35static const bool customItemChecked = false;
36static const bool customItemEnabled = true;
37
38static const char webkitItemTitle1[] = "Open Link";
39static const char webkitItemTitle2[] = "Open Link in New Window";
40static const char webkitItemTitle3[] = "Download Linked File";
41static const char webkitItemTitle4[] = "Copy Link Location";
42static const char webkitItemNewTitle[] = "Copy Link";
43
44class EWK2ContextMenuTest : public EWK2UnitTestBase {
45public:
46    static void checkBasicContextMenuItem(Ewk_Context_Menu_Item* item, Ewk_Context_Menu_Item_Type type, Ewk_Context_Menu_Item_Action action, const char* title, Eina_Bool checked, Eina_Bool enabled)
47    {
48        ASSERT_TRUE(item);
49
50        EXPECT_EQ(type, ewk_context_menu_item_type_get(item));
51        EXPECT_EQ(action, ewk_context_menu_item_action_get(item));
52        EXPECT_STREQ(title, ewk_context_menu_item_title_get(item));
53    EXPECT_EQ(checked, ewk_context_menu_item_checked_get(item));
54    EXPECT_EQ(enabled, ewk_context_menu_item_enabled_get(item));
55    }
56
57    static Eina_Bool customItemSelected(Ewk_View_Smart_Data*, Ewk_Context_Menu_Item* item)
58    {
59        checkBasicContextMenuItem(item, customItemType, static_cast<Ewk_Context_Menu_Item_Action>(customItemTag), customItemTitle, customItemChecked, customItemEnabled);
60
61        return true;
62    }
63
64    /**
65     * This callback receives context menu called upon link with items generated by WebKit2.
66     * Items have their properties modified, and one of items is selected.
67     */
68    static Eina_Bool testContextMenu(Ewk_View_Smart_Data*, Evas_Coord, Evas_Coord, Ewk_Context_Menu* contextMenu)
69    {
70        const Eina_List* list = ewk_context_menu_items_get(contextMenu);
71        EXPECT_EQ(4, eina_list_count(list));
72
73        Ewk_Context_Menu_Item* item = static_cast<Ewk_Context_Menu_Item*>(eina_list_nth(list, 0));
74        checkBasicContextMenuItem(item, EWK_ACTION_TYPE, EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK, webkitItemTitle1, false, true);
75
76        item = static_cast<Ewk_Context_Menu_Item*>(eina_list_nth(list, 1));
77        checkBasicContextMenuItem(item, EWK_ACTION_TYPE, EWK_CONTEXT_MENU_ITEM_TAG_OPEN_LINK_IN_NEW_WINDOW, webkitItemTitle2, false, true);
78        ewk_context_menu_item_enabled_set(item, false);
79        EXPECT_FALSE(ewk_context_menu_item_enabled_get(item));
80
81        item = static_cast<Ewk_Context_Menu_Item*>(eina_list_nth(list, 2));
82        checkBasicContextMenuItem(item, EWK_ACTION_TYPE, EWK_CONTEXT_MENU_ITEM_TAG_DOWNLOAD_LINK_TO_DISK, webkitItemTitle3, false, true);
83        ewk_context_menu_item_checked_set(item, true);
84        EXPECT_TRUE(ewk_context_menu_item_checked_get(item));
85
86        item = static_cast<Ewk_Context_Menu_Item*>(eina_list_nth(list, 3));
87        checkBasicContextMenuItem(item, EWK_ACTION_TYPE, EWK_CONTEXT_MENU_ITEM_TAG_COPY_LINK_TO_CLIPBOARD, webkitItemTitle4, false, true);
88        ewk_context_menu_item_title_set(item, webkitItemNewTitle);
89        EXPECT_STREQ(webkitItemNewTitle, ewk_context_menu_item_title_get(item));
90
91        // When context menu is created by WebKit, an item should have parent menu.
92        EXPECT_EQ(contextMenu, ewk_context_menu_item_parent_menu_get(item));
93
94        item = static_cast<Ewk_Context_Menu_Item*>(eina_list_nth(list, 0));
95
96        EXPECT_TRUE(ewk_context_menu_item_select(contextMenu, item));
97
98        return true;
99    }
100
101    /**
102     * This callback receives context menu called upon link with items generated by WebKit2.
103     * Received items are removed, then custom item is created and selected.
104     */
105    static Eina_Bool testContextMenuForRemoveAndAppend(Ewk_View_Smart_Data*, Evas_Coord, Evas_Coord, Ewk_Context_Menu* contextMenu)
106    {
107        const Eina_List* list = ewk_context_menu_items_get(contextMenu);
108        EXPECT_EQ(4, eina_list_count(list));
109
110        const Eina_List* listIterator;
111        void* data;
112        EINA_LIST_FOREACH(list, listIterator, data)
113            ewk_context_menu_item_remove(contextMenu, static_cast<Ewk_Context_Menu_Item*>(data));
114
115        list = ewk_context_menu_items_get(contextMenu);
116        EXPECT_EQ(0, eina_list_count(list));
117
118        Ewk_Context_Menu_Item* newItem = ewk_context_menu_item_new(customItemType, customItemTag, customItemTitle, customItemChecked, customItemEnabled);
119
120        // When context menu item is created using ewk_context_menu_item_new, it should not have parent menu.
121        EXPECT_EQ(0, ewk_context_menu_item_parent_menu_get(newItem));
122        ewk_context_menu_item_append(contextMenu, newItem);
123
124        // When context menu item is added to menu using ewk_context_menu_item_append, it should have parent menu.
125        EXPECT_EQ(contextMenu, ewk_context_menu_item_parent_menu_get(newItem));
126
127        // When non submenu type context menu item was created using ewk_context_menu_item_new, submenu should be 0.
128        EXPECT_EQ(0, ewk_context_menu_item_submenu_get(newItem));
129
130        EXPECT_TRUE(ewk_context_menu_item_select(contextMenu, newItem));
131
132        ewk_context_menu_hide(contextMenu);
133
134        return true;
135    }
136
137    /**
138     * This callback receives context menu called upon link with items generated by WebKit2.
139     * New submenus are created, one of submenu's item is selected.
140     */
141    static Eina_Bool testContextMenuForSubmenu(Ewk_View_Smart_Data*, Evas_Coord, Evas_Coord, Ewk_Context_Menu* contextMenu)
142    {
143        Eina_List* subMenuItemList = 0;
144        Ewk_Context_Menu_Item* subMenuItem1 = ewk_context_menu_item_new(customItemType, customItemTag, customItemTitle, customItemChecked, customItemEnabled);
145        Ewk_Context_Menu_Item* subMenuItem2 = ewk_context_menu_item_new(EWK_ACTION_TYPE, static_cast<Ewk_Context_Menu_Item_Action>(customItemTag + 1), "New SubMenu Item 2", false, true);
146        Ewk_Context_Menu_Item* subMenuItem3 = ewk_context_menu_item_new(EWK_ACTION_TYPE, static_cast<Ewk_Context_Menu_Item_Action>(customItemTag + 2), "New SubMenu Item 3", false, true);
147        subMenuItemList = eina_list_append(subMenuItemList, subMenuItem1);
148        subMenuItemList = eina_list_append(subMenuItemList, subMenuItem2);
149        subMenuItemList = eina_list_append(subMenuItemList, subMenuItem3);
150        Ewk_Context_Menu* subMenu = ewk_context_menu_new_with_items(subMenuItemList);
151
152        // When context menu is created using ewk_context_menu_new_with_items, items should have parent menu.
153        EXPECT_EQ(subMenu, ewk_context_menu_item_parent_menu_get(subMenuItem1));
154
155        Ewk_Context_Menu_Item* newItem = ewk_context_menu_item_new_with_submenu(EWK_CONTEXT_MENU_ITEM_BASE_APPLICATION_TAG, "New Custom Item", true, subMenu);
156        // When context menu item is created using ewk_context_menu_item_new_with_submenu, it should not have parent menu.
157        EXPECT_EQ(0, ewk_context_menu_item_parent_menu_get(newItem));
158        ewk_context_menu_item_append(contextMenu, newItem);
159
160        // Context menu received from ewk_context_menu_item_submenu_get should be the same as one used to create sub menu.
161        EXPECT_EQ(subMenu, ewk_context_menu_item_submenu_get(newItem));
162
163        // When context menu item is created using ewk_context_menu_item_new_with_submenu and added using ewk_context_menu_item_append it should have parent menu.
164        EXPECT_EQ(contextMenu, ewk_context_menu_item_parent_menu_get(newItem));
165
166        Ewk_Context_Menu* subMenu2 = ewk_context_menu_new();
167        Ewk_Context_Menu_Item* newItem2 = ewk_context_menu_item_new_with_submenu(EWK_CONTEXT_MENU_ITEM_BASE_APPLICATION_TAG, "New Custom Item 2", true, subMenu2);
168        ewk_context_menu_item_append(contextMenu, newItem2);
169
170        EXPECT_TRUE(ewk_context_menu_item_select(ewk_context_menu_item_parent_menu_get(subMenuItem1), subMenuItem1));
171
172        ewk_context_menu_hide(ewk_context_menu_item_parent_menu_get(subMenuItem1));
173
174        return true;
175    }
176
177    static Eina_Bool finishTest(Ewk_View_Smart_Data*)
178    {
179        testFinished = true;
180
181        return true;
182    }
183
184protected:
185    void showContextMenu()
186    {
187        mouseClick(10, 20, /*Right*/ 3);
188    }
189};
190
191TEST_F(EWK2ContextMenuTest, ewk_context_menu_item_select)
192{
193    const char* itemSelectHTML =
194        "<html>"
195        "<body><a href=http://www.google.com>Test Link</a></body>"
196        "</html>";
197
198    ewkViewClass()->context_menu_show = testContextMenu;
199
200    ewk_view_html_string_load(webView(), itemSelectHTML, "file:///", 0);
201    ASSERT_TRUE(waitUntilLoadFinished());
202    showContextMenu();
203    ASSERT_TRUE(waitUntilLoadFinished());
204}
205
206TEST_F(EWK2ContextMenuTest, ewk_context_menu_custom_items)
207{
208    const char* itemSelectHTML =
209        "<html>"
210        "<body><a href=http://www.google.com>Test Link</a></body>"
211        "</html>";
212
213    ewkViewClass()->custom_item_selected = customItemSelected;
214    ewkViewClass()->context_menu_show = testContextMenuForRemoveAndAppend;
215    ewkViewClass()->context_menu_hide = finishTest;
216
217    ewk_view_html_string_load(webView(), itemSelectHTML, "file:///", 0);
218    ASSERT_TRUE(waitUntilLoadFinished());
219    showContextMenu();
220    testFinished = false;
221    ASSERT_TRUE(waitUntilTrue(testFinished));
222
223    ewkViewClass()->context_menu_show = testContextMenuForSubmenu;
224    showContextMenu();
225    testFinished = false;
226    ASSERT_TRUE(waitUntilTrue(testFinished));
227}
228