1 | /* |
2 | * Copyright (C) 2012 Igalia S.L. |
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 | * Library General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Library General Public License |
15 | * along with this library; see the file COPYING.LIB. If not, write to |
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "config.h" |
21 | #include "WebViewTest.h" |
22 | #include <wtf/Vector.h> |
23 | #include <wtf/glib/GRefPtr.h> |
24 | |
25 | class : public WebViewTest { |
26 | public: |
27 | enum { |
28 | = 1 << 0, |
29 | = 1 << 1, |
30 | = 1 << 2 |
31 | }; |
32 | |
33 | void (GdkEvent* event) |
34 | { |
35 | g_assert_nonnull(event); |
36 | g_assert_cmpint(event->type, ==, m_expectedEventType); |
37 | |
38 | switch (m_expectedEventType) { |
39 | case GDK_BUTTON_PRESS: |
40 | g_assert_cmpint(event->button.button, ==, 3); |
41 | g_assert_cmpint(event->button.x, ==, m_menuPositionX); |
42 | g_assert_cmpint(event->button.y, ==, m_menuPositionY); |
43 | break; |
44 | case GDK_KEY_PRESS: |
45 | g_assert_cmpint(event->key.keyval, ==, GDK_KEY_Menu); |
46 | break; |
47 | case GDK_NOTHING: |
48 | // GDK_NOTHING means that the context menu was triggered by the |
49 | // popup-menu signal. We don't have anything to check here. |
50 | break; |
51 | default: |
52 | g_assert_not_reached(); |
53 | } |
54 | } |
55 | |
56 | static gboolean (WebKitWebView* webView, WebKitContextMenu* , GdkEvent* event, WebKitHitTestResult* hitTestResult, ContextMenuTest* test) |
57 | { |
58 | g_assert_true(WEBKIT_IS_CONTEXT_MENU(contextMenu)); |
59 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(contextMenu)); |
60 | test->checkContextMenuEvent(event); |
61 | g_assert_true(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult)); |
62 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(hitTestResult)); |
63 | |
64 | return test->contextMenu(contextMenu, event, hitTestResult); |
65 | } |
66 | |
67 | static void (WebKitWebView*, ContextMenuTest* test) |
68 | { |
69 | test->contextMenuDismissed(); |
70 | } |
71 | |
72 | () |
73 | : m_menuPositionX(0) |
74 | , m_menuPositionY(0) |
75 | , m_expectedEventType(GDK_BUTTON_PRESS) |
76 | { |
77 | g_signal_connect(m_webView, "context-menu" , G_CALLBACK(contextMenuCallback), this); |
78 | g_signal_connect(m_webView, "context-menu-dismissed" , G_CALLBACK(contextMenuDismissedCallback), this); |
79 | } |
80 | |
81 | () |
82 | { |
83 | g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); |
84 | } |
85 | |
86 | virtual bool (WebKitContextMenu*, GdkEvent*, WebKitHitTestResult*) = 0; |
87 | |
88 | virtual void () |
89 | { |
90 | quitMainLoop(); |
91 | } |
92 | |
93 | GtkMenu* () |
94 | { |
95 | GUniquePtr<GList> toplevels(gtk_window_list_toplevels()); |
96 | for (GList* iter = toplevels.get(); iter; iter = g_list_next(iter)) { |
97 | if (!GTK_IS_WINDOW(iter->data)) |
98 | continue; |
99 | |
100 | GtkWidget* child = gtk_bin_get_child(GTK_BIN(iter->data)); |
101 | if (!GTK_IS_MENU(child)) |
102 | continue; |
103 | |
104 | if (gtk_menu_get_attach_widget(GTK_MENU(child)) == GTK_WIDGET(m_webView)) |
105 | return GTK_MENU(child); |
106 | } |
107 | g_assert_not_reached(); |
108 | return 0; |
109 | } |
110 | |
111 | void (GtkAction* action, unsigned state) |
112 | { |
113 | if (state & Visible) |
114 | g_assert_true(gtk_action_get_visible(action)); |
115 | else |
116 | g_assert_false(gtk_action_get_visible(action)); |
117 | |
118 | if (state & Enabled) |
119 | g_assert_true(gtk_action_get_sensitive(action)); |
120 | else |
121 | g_assert_false(gtk_action_get_sensitive(action)); |
122 | |
123 | if (GTK_IS_TOGGLE_ACTION(action)) { |
124 | if (state & Checked) |
125 | g_assert_true(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))); |
126 | else |
127 | g_assert_false(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action))); |
128 | } |
129 | } |
130 | |
131 | GList* checkCurrentItemIsStockActionAndGetNext(GList* items, WebKitContextMenuAction stockAction, unsigned state) |
132 | { |
133 | g_assert_nonnull(items); |
134 | g_assert_true(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data)); |
135 | |
136 | WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data); |
137 | assertObjectIsDeletedWhenTestFinishes(G_OBJECT(item)); |
138 | |
139 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
140 | GtkAction* action = webkit_context_menu_item_get_action(item); |
141 | g_assert_true(GTK_IS_ACTION(action)); |
142 | G_GNUC_END_IGNORE_DEPRECATIONS; |
143 | |
144 | GAction* gAction = webkit_context_menu_item_get_gaction(item); |
145 | g_assert_true(G_IS_ACTION(gAction)); |
146 | |
147 | g_assert_cmpint(webkit_context_menu_item_get_stock_action(item), ==, stockAction); |
148 | |
149 | checkActionState(action, state); |
150 | |
151 | return g_list_next(items); |
152 | } |
153 | |
154 | GList* checkCurrentItemIsCustomActionAndGetNext(GList* items, const char* label, unsigned state) |
155 | { |
156 | g_assert_nonnull(items); |
157 | g_assert_true(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data)); |
158 | |
159 | WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data); |
160 | assertObjectIsDeletedWhenTestFinishes(G_OBJECT(item)); |
161 | |
162 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
163 | GtkAction* action = webkit_context_menu_item_get_action(item); |
164 | g_assert_true(GTK_IS_ACTION(action)); |
165 | G_GNUC_END_IGNORE_DEPRECATIONS; |
166 | |
167 | GAction* gAction = webkit_context_menu_item_get_gaction(item); |
168 | g_assert_true(G_IS_ACTION(gAction)); |
169 | g_assert_cmpstr(gtk_action_get_name(action), ==, g_action_get_name(gAction)); |
170 | g_assert_cmpint(gtk_action_get_sensitive(action), ==, g_action_get_enabled(gAction)); |
171 | if (GTK_IS_TOGGLE_ACTION(action)) { |
172 | g_assert_true(g_variant_type_equal(g_action_get_state_type(gAction), G_VARIANT_TYPE_BOOLEAN)); |
173 | GRefPtr<GVariant> state = adoptGRef(g_action_get_state(gAction)); |
174 | g_assert_cmpint(gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)), ==, g_variant_get_boolean(state.get())); |
175 | } else |
176 | g_assert_null(g_action_get_state_type(gAction)); |
177 | |
178 | g_assert_cmpint(webkit_context_menu_item_get_stock_action(item), ==, WEBKIT_CONTEXT_MENU_ACTION_CUSTOM); |
179 | g_assert_cmpstr(gtk_action_get_label(action), ==, label); |
180 | |
181 | checkActionState(action, state); |
182 | |
183 | return g_list_next(items); |
184 | } |
185 | |
186 | GList* checkCurrentItemIsSubMenuAndGetNext(GList* items, const char* label, unsigned state, GList** ) |
187 | { |
188 | g_assert_nonnull(items); |
189 | g_assert_true(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data)); |
190 | |
191 | WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data); |
192 | assertObjectIsDeletedWhenTestFinishes(G_OBJECT(item)); |
193 | |
194 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
195 | GtkAction* action = webkit_context_menu_item_get_action(item); |
196 | g_assert_true(GTK_IS_ACTION(action)); |
197 | g_assert_cmpstr(gtk_action_get_label(action), ==, label); |
198 | G_GNUC_END_IGNORE_DEPRECATIONS; |
199 | |
200 | GAction* gAction = webkit_context_menu_item_get_gaction(item); |
201 | g_assert_true(G_IS_ACTION(gAction)); |
202 | |
203 | checkActionState(action, state); |
204 | |
205 | WebKitContextMenu* = webkit_context_menu_item_get_submenu(item); |
206 | g_assert_true(WEBKIT_IS_CONTEXT_MENU(subMenu)); |
207 | if (subMenuIter) |
208 | *subMenuIter = webkit_context_menu_get_items(subMenu); |
209 | |
210 | return g_list_next(items); |
211 | } |
212 | |
213 | GList* checkCurrentItemIsSeparatorAndGetNext(GList* items) |
214 | { |
215 | g_assert_nonnull(items); |
216 | g_assert_true(WEBKIT_IS_CONTEXT_MENU_ITEM(items->data)); |
217 | |
218 | WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(items->data); |
219 | g_assert_true(webkit_context_menu_item_is_separator(item)); |
220 | |
221 | return g_list_next(items); |
222 | } |
223 | |
224 | static gboolean (ContextMenuTest* test) |
225 | { |
226 | test->clickMouseButton(test->m_menuPositionX, test->m_menuPositionY, 3); |
227 | return FALSE; |
228 | } |
229 | |
230 | void showContextMenuAtPositionAndWaitUntilFinished(int x, int y) |
231 | { |
232 | m_menuPositionX = x; |
233 | m_menuPositionY = y; |
234 | g_idle_add(reinterpret_cast<GSourceFunc>(doRightClickIdleCallback), this); |
235 | g_main_loop_run(m_mainLoop); |
236 | } |
237 | |
238 | void showContextMenuAndWaitUntilFinished() |
239 | { |
240 | m_expectedEventType = GDK_BUTTON_PRESS; |
241 | showContextMenuAtPositionAndWaitUntilFinished(0, 0); |
242 | } |
243 | |
244 | static gboolean (ContextMenuTest* test) |
245 | { |
246 | test->keyStroke(GDK_KEY_Escape); |
247 | return FALSE; |
248 | } |
249 | |
250 | void dismissContextMenuAndWaitUntilFinished() |
251 | { |
252 | g_idle_add(reinterpret_cast<GSourceFunc>(simulateEscKeyIdleCallback), this); |
253 | g_main_loop_run(m_mainLoop); |
254 | } |
255 | |
256 | static gboolean (ContextMenuTest* test) |
257 | { |
258 | test->emitPopupMenuSignal(); |
259 | return FALSE; |
260 | } |
261 | |
262 | void showContextMenuTriggeredByPopupEventAndWaitUntilFinished() |
263 | { |
264 | m_expectedEventType = GDK_NOTHING; |
265 | g_idle_add(reinterpret_cast<GSourceFunc>(emitPopupMenuSignalIdleCallback), this); |
266 | g_main_loop_run(m_mainLoop); |
267 | } |
268 | |
269 | static gboolean (ContextMenuTest* test) |
270 | { |
271 | test->keyStroke(GDK_KEY_Menu); |
272 | return FALSE; |
273 | } |
274 | |
275 | void showContextMenuTriggeredByContextMenuKeyAndWaitUntilFinished() |
276 | { |
277 | m_expectedEventType = GDK_KEY_PRESS; |
278 | g_idle_add(reinterpret_cast<GSourceFunc>(simulateMenuKeyIdleCallback), this); |
279 | g_main_loop_run(m_mainLoop); |
280 | } |
281 | |
282 | double ; |
283 | double ; |
284 | GdkEventType ; |
285 | }; |
286 | |
287 | class : public ContextMenuTest { |
288 | public: |
289 | MAKE_GLIB_TEST_FIXTURE(ContextMenuDefaultTest); |
290 | |
291 | enum { |
292 | , |
293 | , |
294 | , |
295 | , |
296 | , |
297 | , |
298 | , |
299 | |
300 | }; |
301 | |
302 | () |
303 | : m_expectedMenuType(Navigation) |
304 | { |
305 | } |
306 | |
307 | bool (WebKitContextMenu* , GdkEvent* event, WebKitHitTestResult* hitTestResult) |
308 | { |
309 | GList* iter = webkit_context_menu_get_items(contextMenu); |
310 | |
311 | switch (m_expectedMenuType) { |
312 | case Navigation: |
313 | g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult)); |
314 | g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult)); |
315 | g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult)); |
316 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
317 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
318 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK, Visible); |
319 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD, Visible); |
320 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP, Visible); |
321 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD, Visible | Enabled); |
322 | break; |
323 | case Link: |
324 | g_assert_true(webkit_hit_test_result_context_is_link(hitTestResult)); |
325 | g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult)); |
326 | g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult)); |
327 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
328 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
329 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled); |
330 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled); |
331 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled); |
332 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD, Visible | Enabled); |
333 | break; |
334 | case Image: |
335 | g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult)); |
336 | g_assert_true(webkit_hit_test_result_context_is_image(hitTestResult)); |
337 | g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult)); |
338 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
339 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
340 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW, Visible | Enabled); |
341 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK, Visible | Enabled); |
342 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD, Visible | Enabled); |
343 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD, Visible | Enabled); |
344 | break; |
345 | case LinkImage: |
346 | g_assert_true(webkit_hit_test_result_context_is_link(hitTestResult)); |
347 | g_assert_true(webkit_hit_test_result_context_is_image(hitTestResult)); |
348 | g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult)); |
349 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
350 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
351 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled); |
352 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled); |
353 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled); |
354 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD, Visible | Enabled); |
355 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
356 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW, Visible | Enabled); |
357 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK, Visible | Enabled); |
358 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD, Visible | Enabled); |
359 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD, Visible | Enabled); |
360 | break; |
361 | case Video: |
362 | g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult)); |
363 | g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult)); |
364 | g_assert_true(webkit_hit_test_result_context_is_media(hitTestResult)); |
365 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
366 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
367 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled); |
368 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible); |
369 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked); |
370 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP, Visible | Enabled); |
371 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN, Visible | Enabled); |
372 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
373 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_VIDEO_LINK_TO_CLIPBOARD, Visible | Enabled); |
374 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_VIDEO_IN_NEW_WINDOW, Visible | Enabled); |
375 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_VIDEO_TO_DISK, Visible | Enabled); |
376 | break; |
377 | case Audio: |
378 | g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult)); |
379 | g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult)); |
380 | g_assert_true(webkit_hit_test_result_context_is_media(hitTestResult)); |
381 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
382 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
383 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled); |
384 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible); |
385 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked); |
386 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_LOOP, Visible | Enabled); |
387 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_ENTER_VIDEO_FULLSCREEN, Visible); |
388 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
389 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_AUDIO_LINK_TO_CLIPBOARD, Visible | Enabled); |
390 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_AUDIO_IN_NEW_WINDOW, Visible | Enabled); |
391 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_AUDIO_TO_DISK, Visible | Enabled); |
392 | break; |
393 | case Editable: |
394 | g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult)); |
395 | g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult)); |
396 | g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult)); |
397 | g_assert_true(webkit_hit_test_result_context_is_editable(hitTestResult)); |
398 | g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult)); |
399 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_CUT, Visible); |
400 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible); |
401 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_PASTE, Visible | Enabled); |
402 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DELETE, Visible); |
403 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
404 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL, Visible | Enabled); |
405 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_INSERT_EMOJI, Visible | Enabled); |
406 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
407 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_UNICODE, Visible | Enabled); |
408 | break; |
409 | case Selection: |
410 | g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult)); |
411 | g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult)); |
412 | g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult)); |
413 | g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult)); |
414 | g_assert_true(webkit_hit_test_result_context_is_selection(hitTestResult)); |
415 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible | Enabled); |
416 | break; |
417 | default: |
418 | g_assert_not_reached(); |
419 | } |
420 | |
421 | if (webkit_settings_get_enable_developer_extras(webkit_web_view_get_settings(m_webView))) { |
422 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
423 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT, Visible | Enabled); |
424 | } |
425 | g_assert_null(iter); |
426 | |
427 | quitMainLoop(); |
428 | |
429 | return true; |
430 | } |
431 | |
432 | DefaultMenuType ; |
433 | }; |
434 | |
435 | static void (ContextMenuDefaultTest* test) |
436 | { |
437 | GUniquePtr<char> baseDir(g_strdup_printf("file://%s/" , Test::getResourcesDir().data())); |
438 | const char* linksHTML = |
439 | "<html><body>" |
440 | " <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>" |
441 | " <img style='position:absolute; left:1; top:10' src='blank.ico' width=5 height=5></img>" |
442 | " <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='blank.ico' width=5 height=5></img></a>" |
443 | " <input style='position:absolute; left:1; top:30' size='10'></input>" |
444 | " <video style='position:absolute; left:1; top:50' width='300' height='300' controls='controls' preload='none'><source src='silence.webm' type='video/webm' /></video>" |
445 | " <audio style='position:absolute; left:1; top:60' width='50' height='20' controls='controls' preload='none'><source src='track.ogg' type='audio/ogg' /></audio>" |
446 | " <p style='position:absolute; left:1; top:90' id='text_to_select'>Lorem ipsum.</p>" |
447 | " <script>" |
448 | " window.getSelection().removeAllRanges();" |
449 | " var select_range = document.createRange();" |
450 | " select_range.selectNodeContents(document.getElementById('text_to_select'));" |
451 | " window.getSelection().addRange(select_range);" |
452 | " </script>" |
453 | "</body></html>" ; |
454 | test->loadHtml(linksHTML, baseDir.get()); |
455 | test->waitUntilLoadFinished(); |
456 | } |
457 | |
458 | static void (ContextMenuDefaultTest* test, gconstpointer) |
459 | { |
460 | test->showInWindowAndWaitUntilMapped(); |
461 | |
462 | prepareContextMenuTestView(test); |
463 | |
464 | // Context menu for selection. |
465 | // This test should always be the first because any other click removes the selection. |
466 | test->m_expectedMenuType = ContextMenuDefaultTest::Selection; |
467 | test->showContextMenuAtPositionAndWaitUntilFinished(2, 115); |
468 | |
469 | // Context menu for document. |
470 | test->m_expectedMenuType = ContextMenuDefaultTest::Navigation; |
471 | test->showContextMenuAtPositionAndWaitUntilFinished(0, 0); |
472 | |
473 | // Context menu for link. |
474 | test->m_expectedMenuType = ContextMenuDefaultTest::Link; |
475 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 1); |
476 | |
477 | // Context menu for image. |
478 | test->m_expectedMenuType = ContextMenuDefaultTest::Image; |
479 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 10); |
480 | |
481 | // Enable developer extras now, so that inspector element |
482 | // will be shown in the default context menu. |
483 | webkit_settings_set_enable_developer_extras(webkit_web_view_get_settings(test->m_webView), TRUE); |
484 | |
485 | // Context menu for image link. |
486 | test->m_expectedMenuType = ContextMenuDefaultTest::LinkImage; |
487 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 20); |
488 | |
489 | // Context menu for video. |
490 | test->m_expectedMenuType = ContextMenuDefaultTest::Video; |
491 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 50); |
492 | |
493 | // Context menu for audio. |
494 | test->m_expectedMenuType = ContextMenuDefaultTest::Audio; |
495 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 60); |
496 | |
497 | // Context menu for editable. |
498 | test->m_expectedMenuType = ContextMenuDefaultTest::Editable; |
499 | test->showContextMenuAtPositionAndWaitUntilFinished(5, 35); |
500 | } |
501 | |
502 | static void (ContextMenuDefaultTest* test, gconstpointer) |
503 | { |
504 | test->showInWindowAndWaitUntilMapped(); |
505 | |
506 | prepareContextMenuTestView(test); |
507 | |
508 | test->m_expectedMenuType = ContextMenuDefaultTest::Selection; |
509 | test->showContextMenuTriggeredByPopupEventAndWaitUntilFinished(); |
510 | } |
511 | |
512 | static void (ContextMenuDefaultTest* test, gconstpointer) |
513 | { |
514 | test->showInWindowAndWaitUntilMapped(); |
515 | |
516 | prepareContextMenuTestView(test); |
517 | |
518 | test->m_expectedMenuType = ContextMenuDefaultTest::Selection; |
519 | test->showContextMenuTriggeredByContextMenuKeyAndWaitUntilFinished(); |
520 | } |
521 | |
522 | class : public ContextMenuTest { |
523 | public: |
524 | MAKE_GLIB_TEST_FIXTURE(ContextMenuCustomTest); |
525 | |
526 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult* hitTestResult) |
527 | { |
528 | // Append our custom item to the default menu. |
529 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
530 | if (m_action) |
531 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new(m_action.get())); |
532 | else if (m_gAction) |
533 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_gaction(m_gAction.get(), m_gActionTitle.data(), m_expectedTarget.get())); |
534 | G_GNUC_END_IGNORE_DEPRECATIONS; |
535 | quitMainLoop(); |
536 | |
537 | return false; |
538 | } |
539 | |
540 | GtkMenuItem* (GtkMenu* , const gchar* itemLabel) |
541 | { |
542 | GUniquePtr<GList> items(gtk_container_get_children(GTK_CONTAINER(menu))); |
543 | for (GList* iter = items.get(); iter; iter = g_list_next(iter)) { |
544 | GtkMenuItem* child = GTK_MENU_ITEM(iter->data); |
545 | if (g_str_equal(itemLabel, gtk_menu_item_get_label(child))) |
546 | return child; |
547 | } |
548 | g_assert_not_reached(); |
549 | return 0; |
550 | } |
551 | |
552 | void () |
553 | { |
554 | g_assert_nonnull(m_itemToActivateLabel); |
555 | GtkMenu* = getPopupMenu(); |
556 | GtkMenuItem* item = getMenuItem(menu, m_itemToActivateLabel); |
557 | gtk_menu_shell_activate_item(GTK_MENU_SHELL(menu), GTK_WIDGET(item), TRUE); |
558 | m_itemToActivateLabel = nullptr; |
559 | } |
560 | |
561 | static gboolean (gpointer userData) |
562 | { |
563 | ContextMenuCustomTest* test = static_cast<ContextMenuCustomTest*>(userData); |
564 | test->activateMenuItem(); |
565 | return FALSE; |
566 | } |
567 | |
568 | void activateCustomMenuItemAndWaitUntilActivated(const char* actionLabel) |
569 | { |
570 | m_activated = m_toggled = false; |
571 | m_itemToActivateLabel = actionLabel; |
572 | g_idle_add(activateMenuItemIdleCallback, this); |
573 | g_main_loop_run(m_mainLoop); |
574 | } |
575 | |
576 | void toggleCustomMenuItemAndWaitUntilToggled(const char* actionLabel) |
577 | { |
578 | activateCustomMenuItemAndWaitUntilActivated(actionLabel); |
579 | } |
580 | |
581 | static void (ContextMenuCustomTest* test, GVariant* target) |
582 | { |
583 | if (test->m_gAction) { |
584 | if (g_action_get_state_type(test->m_gAction.get())) { |
585 | GRefPtr<GVariant> state = adoptGRef(g_action_get_state(test->m_gAction.get())); |
586 | g_action_change_state(test->m_gAction.get(), g_variant_new_boolean(!g_variant_get_boolean(state.get()))); |
587 | } else { |
588 | test->m_activated = true; |
589 | if (test->m_expectedTarget) |
590 | g_assert_true(g_variant_equal(test->m_expectedTarget.get(), target)); |
591 | else |
592 | g_assert_null(target); |
593 | } |
594 | } else |
595 | test->m_activated = true; |
596 | } |
597 | |
598 | static void (ContextMenuCustomTest* test) |
599 | { |
600 | test->m_toggled = true; |
601 | } |
602 | |
603 | void (GtkAction* action) |
604 | { |
605 | m_action = action; |
606 | m_gAction = nullptr; |
607 | m_expectedTarget = nullptr; |
608 | if (GTK_IS_TOGGLE_ACTION(action)) |
609 | g_signal_connect_swapped(action, "toggled" , G_CALLBACK(actionToggledCallback), this); |
610 | else |
611 | g_signal_connect_swapped(action, "activate" , G_CALLBACK(actionActivatedCallback), this); |
612 | } |
613 | |
614 | void (GAction* action, const char* title, GVariant* target = nullptr) |
615 | { |
616 | m_gAction = action; |
617 | m_gActionTitle = title; |
618 | m_action = nullptr; |
619 | m_expectedTarget = target; |
620 | g_signal_connect_swapped(action, "activate" , G_CALLBACK(actionActivatedCallback), this); |
621 | if (g_action_get_state_type(action)) |
622 | g_signal_connect_swapped(action, "change-state" , G_CALLBACK(actionToggledCallback), this); |
623 | } |
624 | |
625 | GRefPtr<GtkAction> ; |
626 | GRefPtr<GAction> ; |
627 | CString ; |
628 | GRefPtr<GVariant> ; |
629 | const char* { nullptr }; |
630 | bool { false }; |
631 | bool { false }; |
632 | }; |
633 | |
634 | static void (ContextMenuCustomTest* test, gconstpointer) |
635 | { |
636 | test->showInWindowAndWaitUntilMapped(); |
637 | |
638 | test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>" , "file:///" ); |
639 | test->waitUntilLoadFinished(); |
640 | |
641 | // Create a custom menu item. |
642 | GRefPtr<GtkAction> action = adoptGRef(gtk_action_new("WebKitGTK+CustomAction" , "Custom _Action" , nullptr, nullptr)); |
643 | test->setAction(action.get()); |
644 | test->showContextMenuAndWaitUntilFinished(); |
645 | test->activateCustomMenuItemAndWaitUntilActivated(gtk_action_get_label(action.get())); |
646 | g_assert_true(test->m_activated); |
647 | g_assert_false(test->m_toggled); |
648 | |
649 | // Create a custom toggle menu item. |
650 | GRefPtr<GtkAction> toggleAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new("WebKitGTK+CustomToggleAction" , "Custom _Toggle Action" , nullptr, nullptr))); |
651 | test->setAction(toggleAction.get()); |
652 | test->showContextMenuAndWaitUntilFinished(); |
653 | test->toggleCustomMenuItemAndWaitUntilToggled(gtk_action_get_label(toggleAction.get())); |
654 | g_assert_false(test->m_activated); |
655 | g_assert_true(test->m_toggled); |
656 | |
657 | // Create a custom menu item using GAction. |
658 | GRefPtr<GAction> gAction = adoptGRef(G_ACTION(g_simple_action_new("WebKitGTK+CustomGAction" , nullptr))); |
659 | test->setAction(gAction.get(), "Custom _GAction" ); |
660 | test->showContextMenuAndWaitUntilFinished(); |
661 | test->activateCustomMenuItemAndWaitUntilActivated("Custom _GAction" ); |
662 | g_assert_true(test->m_activated); |
663 | g_assert_false(test->m_toggled); |
664 | |
665 | // Create a custom toggle menu item using GAction. |
666 | GRefPtr<GAction> toggleGAction = adoptGRef(G_ACTION(g_simple_action_new_stateful("WebKitGTK+CustomToggleGAction" , nullptr, g_variant_new_boolean(FALSE)))); |
667 | test->setAction(toggleGAction.get(), "Custom _Toggle GAction" ); |
668 | test->showContextMenuAndWaitUntilFinished(); |
669 | test->toggleCustomMenuItemAndWaitUntilToggled("Custom _Toggle GAction" ); |
670 | g_assert_false(test->m_activated); |
671 | g_assert_true(test->m_toggled); |
672 | |
673 | // Create a custom menu item using GAction with a target. |
674 | gAction = adoptGRef(G_ACTION(g_simple_action_new("WebKitGTK+CustomGActionWithTarget" , G_VARIANT_TYPE_STRING))); |
675 | test->setAction(gAction.get(), "Custom _GAction With Target" , g_variant_new_string("WebKitGTK+CustomGActionTarget" )); |
676 | test->showContextMenuAndWaitUntilFinished(); |
677 | test->activateCustomMenuItemAndWaitUntilActivated("Custom _GAction With Target" ); |
678 | g_assert_true(test->m_activated); |
679 | } |
680 | |
681 | class : public ContextMenuTest { |
682 | public: |
683 | MAKE_GLIB_TEST_FIXTURE(ContextMenuCustomFullTest); |
684 | |
685 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult*) |
686 | { |
687 | // Clear proposed menu and build our own. |
688 | webkit_context_menu_remove_all(contextMenu); |
689 | g_assert_cmpint(webkit_context_menu_get_n_items(contextMenu), ==, 0); |
690 | |
691 | // Add actions from stock. |
692 | webkit_context_menu_prepend(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_GO_BACK)); |
693 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD)); |
694 | webkit_context_menu_insert(contextMenu, webkit_context_menu_item_new_separator(), 2); |
695 | |
696 | // Add custom actions. |
697 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
698 | GRefPtr<GtkAction> action = adoptGRef(gtk_action_new("WebKitGTK+CustomAction" , "Custom _Action" , nullptr, nullptr)); |
699 | gtk_action_set_sensitive(action.get(), FALSE); |
700 | webkit_context_menu_insert(contextMenu, webkit_context_menu_item_new(action.get()), -1); |
701 | GRefPtr<GtkAction> toggleAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new("WebKitGTK+CustomToggleAction" , "Custom _Toggle Action" , nullptr, nullptr))); |
702 | gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(toggleAction.get()), TRUE); |
703 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new(toggleAction.get())); |
704 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator()); |
705 | GRefPtr<GAction> gAction = adoptGRef(G_ACTION(g_simple_action_new("WebKitGTK+CustomGAction" , nullptr))); |
706 | g_simple_action_set_enabled(G_SIMPLE_ACTION(gAction.get()), FALSE); |
707 | webkit_context_menu_insert(contextMenu, webkit_context_menu_item_new_from_gaction(gAction.get(), "Custom _GAction" , nullptr), -1); |
708 | GRefPtr<GAction> toggleGAction = adoptGRef(G_ACTION(g_simple_action_new_stateful("WebKitGTK+CustomToggleGAction" , nullptr, g_variant_new_boolean(TRUE)))); |
709 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_gaction(toggleGAction.get(), "Custom T_oggle GAction" , nullptr)); |
710 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator()); |
711 | G_GNUC_END_IGNORE_DEPRECATIONS; |
712 | |
713 | // Add a submenu. |
714 | GRefPtr<WebKitContextMenu> = adoptGRef(webkit_context_menu_new()); |
715 | assertObjectIsDeletedWhenTestFinishes(G_OBJECT(subMenu.get())); |
716 | webkit_context_menu_insert(subMenu.get(), webkit_context_menu_item_new_from_stock_action_with_label(WEBKIT_CONTEXT_MENU_ACTION_STOP, "Stop Load" ), 0); |
717 | webkit_context_menu_insert(subMenu.get(), webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_RELOAD), -1); |
718 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_with_submenu("Load options" , subMenu.get())); |
719 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator()); |
720 | |
721 | // Move Load submenu before custom actions. |
722 | webkit_context_menu_move_item(contextMenu, webkit_context_menu_last(contextMenu), 3); |
723 | webkit_context_menu_move_item(contextMenu, webkit_context_menu_last(contextMenu), 3); |
724 | |
725 | // If last item is a separator, remove it. |
726 | if (webkit_context_menu_item_is_separator(webkit_context_menu_last(contextMenu))) |
727 | webkit_context_menu_remove(contextMenu, webkit_context_menu_last(contextMenu)); |
728 | |
729 | // Check the menu. |
730 | GList* iter = webkit_context_menu_get_items(contextMenu); |
731 | |
732 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK, Visible | Enabled); |
733 | iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD, Visible | Enabled); |
734 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
735 | |
736 | GList* = 0; |
737 | iter = checkCurrentItemIsSubMenuAndGetNext(iter, "Load options" , Visible | Enabled, &subMenuIter); |
738 | subMenuIter = checkCurrentItemIsStockActionAndGetNext(subMenuIter, WEBKIT_CONTEXT_MENU_ACTION_STOP, Visible | Enabled); |
739 | subMenuIter = checkCurrentItemIsStockActionAndGetNext(subMenuIter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD, Visible | Enabled); |
740 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
741 | |
742 | iter = checkCurrentItemIsCustomActionAndGetNext(iter, "Custom _Action" , Visible); |
743 | iter = checkCurrentItemIsCustomActionAndGetNext(iter, "Custom _Toggle Action" , Visible | Enabled | Checked); |
744 | iter = checkCurrentItemIsSeparatorAndGetNext(iter); |
745 | iter = checkCurrentItemIsCustomActionAndGetNext(iter, "Custom _GAction" , Visible); |
746 | iter = checkCurrentItemIsCustomActionAndGetNext(iter, "Custom T_oggle GAction" , Visible | Enabled | Checked); |
747 | g_assert_null(iter); |
748 | |
749 | quitMainLoop(); |
750 | |
751 | return true; |
752 | } |
753 | }; |
754 | |
755 | static void (ContextMenuCustomFullTest* test, gconstpointer) |
756 | { |
757 | test->showInWindowAndWaitUntilMapped(); |
758 | |
759 | test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>" , "file:///" ); |
760 | test->waitUntilLoadFinished(); |
761 | |
762 | test->showContextMenuAndWaitUntilFinished(); |
763 | } |
764 | |
765 | class : public ContextMenuTest { |
766 | public: |
767 | MAKE_GLIB_TEST_FIXTURE(ContextMenuDisabledTest); |
768 | |
769 | enum { |
770 | , |
771 | |
772 | }; |
773 | |
774 | static gboolean (GtkWidget*, GdkEvent* event, ContextMenuDisabledTest* test) |
775 | { |
776 | if (event->button.button != 3) |
777 | return FALSE; |
778 | return test->rightButtonPressed(); |
779 | } |
780 | |
781 | () |
782 | : m_disableMode(IgnoreClicks) |
783 | { |
784 | g_signal_connect(m_webView, "button-press-event" , G_CALLBACK(buttonPressEventCallback), this); |
785 | } |
786 | |
787 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult*) |
788 | { |
789 | if (m_disableMode == IgnoreClicks) |
790 | g_assert_not_reached(); |
791 | else |
792 | quitMainLoop(); |
793 | |
794 | return true; |
795 | } |
796 | |
797 | bool () |
798 | { |
799 | if (m_disableMode == IgnoreClicks) { |
800 | quitMainLoopAfterProcessingPendingEvents(); |
801 | return true; |
802 | } |
803 | return false; |
804 | } |
805 | |
806 | DisableMode ; |
807 | }; |
808 | |
809 | static void (ContextMenuDisabledTest* test, gconstpointer) |
810 | { |
811 | test->showInWindowAndWaitUntilMapped(); |
812 | |
813 | test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>" , "file:///" ); |
814 | test->waitUntilLoadFinished(); |
815 | |
816 | test->m_disableMode = ContextMenuDisabledTest::IgnoreDefaultMenu; |
817 | test->showContextMenuAndWaitUntilFinished(); |
818 | |
819 | test->m_disableMode = ContextMenuDisabledTest::IgnoreClicks; |
820 | test->showContextMenuAndWaitUntilFinished(); |
821 | } |
822 | |
823 | class : public ContextMenuTest { |
824 | public: |
825 | MAKE_GLIB_TEST_FIXTURE(ContextMenuSubmenuTest); |
826 | |
827 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult*) |
828 | { |
829 | size_t = webkit_context_menu_get_n_items(contextMenu); |
830 | GRefPtr<WebKitContextMenu> = adoptGRef(webkit_context_menu_new()); |
831 | webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_with_submenu("SubMenuItem" , subMenu.get())); |
832 | g_assert_cmpuint(webkit_context_menu_get_n_items(contextMenu), ==, menuSize + 1); |
833 | |
834 | GRefPtr<WebKitContextMenu> = adoptGRef(webkit_context_menu_new()); |
835 | GRefPtr<WebKitContextMenuItem> item = webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK); |
836 | |
837 | // Add submenu to newly created item. |
838 | g_assert_null(webkit_context_menu_item_get_submenu(item.get())); |
839 | webkit_context_menu_item_set_submenu(item.get(), subMenu2.get()); |
840 | g_assert_true(webkit_context_menu_item_get_submenu(item.get()) == subMenu2.get()); |
841 | |
842 | // Replace the submenu. |
843 | webkit_context_menu_item_set_submenu(item.get(), 0); |
844 | g_assert_null(webkit_context_menu_item_get_submenu(item.get())); |
845 | |
846 | // Try to add a submenu already added to another item. |
847 | removeLogFatalFlag(G_LOG_LEVEL_WARNING); |
848 | webkit_context_menu_item_set_submenu(item.get(), subMenu.get()); |
849 | addLogFatalFlag(G_LOG_LEVEL_WARNING); |
850 | g_assert_null(webkit_context_menu_item_get_submenu(item.get())); |
851 | |
852 | // A removed submenu shouldn't have a parent. |
853 | webkit_context_menu_item_set_submenu(item.get(), subMenu2.get()); |
854 | g_assert_true(webkit_context_menu_item_get_submenu(item.get()) == subMenu2.get()); |
855 | |
856 | quitMainLoop(); |
857 | |
858 | return true; |
859 | } |
860 | }; |
861 | |
862 | static void (ContextMenuSubmenuTest* test, gconstpointer) |
863 | { |
864 | test->showInWindowAndWaitUntilMapped(); |
865 | |
866 | test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>" , "file:///" ); |
867 | test->waitUntilLoadFinished(); |
868 | |
869 | test->showContextMenuAndWaitUntilFinished(); |
870 | } |
871 | |
872 | class : public ContextMenuTest { |
873 | public: |
874 | MAKE_GLIB_TEST_FIXTURE(ContextMenuDismissedTest); |
875 | |
876 | () |
877 | : m_dismissed(false) |
878 | { |
879 | } |
880 | |
881 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult*) |
882 | { |
883 | quitMainLoop(); |
884 | // Show the default context menu. |
885 | return false; |
886 | } |
887 | |
888 | void () |
889 | { |
890 | m_dismissed = true; |
891 | ContextMenuTest::contextMenuDismissed(); |
892 | } |
893 | |
894 | void showContextMenuAndWaitUntilDismissed() |
895 | { |
896 | showContextMenuAndWaitUntilFinished(); |
897 | dismissContextMenuAndWaitUntilFinished(); |
898 | } |
899 | |
900 | bool ; |
901 | }; |
902 | |
903 | static void (ContextMenuDismissedTest* test, gconstpointer) |
904 | { |
905 | test->showInWindowAndWaitUntilMapped(); |
906 | |
907 | test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>" , "file:///" ); |
908 | test->waitUntilLoadFinished(); |
909 | |
910 | test->showContextMenuAndWaitUntilDismissed(); |
911 | g_assert_true(test->m_dismissed); |
912 | } |
913 | |
914 | class : public ContextMenuTest { |
915 | public: |
916 | MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionTest); |
917 | |
918 | void (GVariant* userData) |
919 | { |
920 | m_actions.clear(); |
921 | if (!userData) |
922 | return; |
923 | |
924 | GVariantIter iter; |
925 | g_variant_iter_init(&iter, userData); |
926 | m_actions.reserveInitialCapacity(g_variant_iter_n_children(&iter)); |
927 | |
928 | uint32_t item; |
929 | while (g_variant_iter_next(&iter, "u" , &item)) |
930 | m_actions.uncheckedAppend(static_cast<WebKitContextMenuAction>(item)); |
931 | } |
932 | |
933 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult*) |
934 | { |
935 | deserializeContextMenuFromUserData(webkit_context_menu_get_user_data(menu)); |
936 | GList* items = webkit_context_menu_get_items(menu); |
937 | g_assert_cmpuint(g_list_length(items), ==, m_actions.size()); |
938 | |
939 | unsigned actionIndex = 0; |
940 | for (GList* it = items; it; it = g_list_next(it)) { |
941 | WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(it->data); |
942 | g_assert_cmpuint(webkit_context_menu_item_get_stock_action(item), ==, m_actions[actionIndex++]); |
943 | } |
944 | |
945 | quitMainLoop(); |
946 | |
947 | return true; |
948 | } |
949 | |
950 | Vector<WebKitContextMenuAction> ; |
951 | }; |
952 | |
953 | static void (ContextMenuWebExtensionTest* test, gconstpointer) |
954 | { |
955 | test->showInWindowAndWaitUntilMapped(); |
956 | test->loadHtml("<html><body>WebKitGTK+ Context menu tests<br>" |
957 | "<a style='position:absolute; left:1; top:10' href='http://www.webkitgtk.org'>WebKitGTK+ Website</a></body></html>" , |
958 | "ContextMenuTestDefault" ); |
959 | test->waitUntilLoadFinished(); |
960 | |
961 | // Default context menu. |
962 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 1); |
963 | g_assert_cmpuint(test->m_actions.size(), ==, 4); |
964 | g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK); |
965 | g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD); |
966 | g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP); |
967 | g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD); |
968 | |
969 | // Link menu. |
970 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 11); |
971 | g_assert_cmpuint(test->m_actions.size(), ==, 4); |
972 | g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK); |
973 | g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW); |
974 | g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK); |
975 | g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD); |
976 | |
977 | // Custom menu. |
978 | test->loadHtml("<html><body></body></html>" , "ContextMenuTestCustom" ); |
979 | test->waitUntilLoadFinished(); |
980 | test->showContextMenuAndWaitUntilFinished(); |
981 | g_assert_cmpuint(test->m_actions.size(), ==, 4); |
982 | g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP); |
983 | g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD); |
984 | g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION); |
985 | g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT); |
986 | |
987 | // Menu cleared by the web process. |
988 | test->loadHtml("<html><body></body></html>" , "ContextMenuTestClear" ); |
989 | test->waitUntilLoadFinished(); |
990 | test->showContextMenuAndWaitUntilFinished(); |
991 | g_assert_cmpuint(test->m_actions.size(), ==, 0); |
992 | } |
993 | |
994 | class : public ContextMenuTest { |
995 | public: |
996 | MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionNodeTest); |
997 | |
998 | struct { |
999 | enum { |
1000 | = 0, |
1001 | = 1, |
1002 | = 3 |
1003 | }; |
1004 | typedef unsigned ; |
1005 | |
1006 | CString ; |
1007 | Type ; |
1008 | CString ; |
1009 | CString ; |
1010 | }; |
1011 | |
1012 | void (GVariant* userData) |
1013 | { |
1014 | GVariantIter iter; |
1015 | g_variant_iter_init(&iter, userData); |
1016 | |
1017 | const char* key; |
1018 | GVariant* value; |
1019 | while (g_variant_iter_next(&iter, "{&sv}" , &key, &value)) { |
1020 | if (!strcmp(key, "Name" ) && g_variant_classify(value) == G_VARIANT_CLASS_STRING) |
1021 | m_node.name = g_variant_get_string(value, nullptr); |
1022 | else if (!strcmp(key, "Type" ) && g_variant_classify(value) == G_VARIANT_CLASS_UINT32) |
1023 | m_node.type = g_variant_get_uint32(value); |
1024 | else if (!strcmp(key, "Contents" ) && g_variant_classify(value) == G_VARIANT_CLASS_STRING) |
1025 | m_node.contents = g_variant_get_string(value, nullptr); |
1026 | else if (!strcmp(key, "Parent" ) && g_variant_classify(value) == G_VARIANT_CLASS_STRING) |
1027 | m_node.parentName = g_variant_get_string(value, nullptr); |
1028 | g_variant_unref(value); |
1029 | } |
1030 | } |
1031 | |
1032 | bool (WebKitContextMenu* , GdkEvent*, WebKitHitTestResult*) |
1033 | { |
1034 | deserializeNodeFromUserData(webkit_context_menu_get_user_data(menu)); |
1035 | quitMainLoop(); |
1036 | |
1037 | return true; |
1038 | } |
1039 | |
1040 | Node ; |
1041 | }; |
1042 | |
1043 | static void (ContextMenuWebExtensionNodeTest* test, gconstpointer) |
1044 | { |
1045 | test->showInWindowAndWaitUntilMapped(); |
1046 | test->loadHtml("<html><body><p style='position:absolute; left:1; top:1'>WebKitGTK+ Context menu tests</p><br>" |
1047 | "<a style='position:absolute; left:1; top:100' href='http://www.webkitgtk.org'>WebKitGTK+ Website</a></body></html>" , |
1048 | "ContextMenuTestNode" ); |
1049 | test->waitUntilLoadFinished(); |
1050 | |
1051 | test->showContextMenuAtPositionAndWaitUntilFinished(0, 0); |
1052 | g_assert_cmpstr(test->m_node.name.data(), ==, "HTML" ); |
1053 | g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeElement); |
1054 | g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Context menu testsWebKitGTK+ Website" ); |
1055 | g_assert_cmpstr(test->m_node.parentName.data(), ==, "#document" ); |
1056 | |
1057 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 20); |
1058 | g_assert_cmpstr(test->m_node.name.data(), ==, "#text" ); |
1059 | g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText); |
1060 | g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Context menu tests" ); |
1061 | g_assert_cmpstr(test->m_node.parentName.data(), ==, "P" ); |
1062 | |
1063 | // Link menu. |
1064 | test->showContextMenuAtPositionAndWaitUntilFinished(1, 101); |
1065 | g_assert_cmpstr(test->m_node.name.data(), ==, "#text" ); |
1066 | g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText); |
1067 | g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Website" ); |
1068 | g_assert_cmpstr(test->m_node.parentName.data(), ==, "A" ); |
1069 | } |
1070 | |
1071 | void beforeAll() |
1072 | { |
1073 | ContextMenuDefaultTest::add("WebKitWebView" , "default-menu" , testContextMenuDefaultMenu); |
1074 | ContextMenuDefaultTest::add("WebKitWebView" , "context-menu-key" , testContextMenuKey); |
1075 | ContextMenuDefaultTest::add("WebKitWebView" , "popup-event-signal" , testPopupEventSignal); |
1076 | ContextMenuCustomTest::add("WebKitWebView" , "populate-menu" , testContextMenuPopulateMenu); |
1077 | ContextMenuCustomFullTest::add("WebKitWebView" , "custom-menu" , testContextMenuCustomMenu); |
1078 | ContextMenuDisabledTest::add("WebKitWebView" , "disable-menu" , testContextMenuDisableMenu); |
1079 | ContextMenuSubmenuTest::add("WebKitWebView" , "submenu" , testContextMenuSubMenu); |
1080 | ContextMenuDismissedTest::add("WebKitWebView" , "menu-dismissed" , testContextMenuDismissed); |
1081 | ContextMenuWebExtensionTest::add("WebKitWebPage" , "context-menu" , testContextMenuWebExtensionMenu); |
1082 | ContextMenuWebExtensionNodeTest::add("WebKitWebPage" , "context-menu-node" , testContextMenuWebExtensionNode); |
1083 | } |
1084 | |
1085 | void afterAll() |
1086 | { |
1087 | } |
1088 | |