1/*
2 * Copyright (C) 2011 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/HashSet.h>
23#include <wtf/RunLoop.h>
24#include <wtf/glib/GRefPtr.h>
25#include <wtf/text/StringHash.h>
26
27static const char* kAlertDialogMessage = "WebKitGTK+ alert dialog message";
28static const char* kConfirmDialogMessage = "WebKitGTK+ confirm dialog message";
29static const char* kPromptDialogMessage = "WebKitGTK+ prompt dialog message";
30static const char* kPromptDialogReturnedText = "WebKitGTK+ prompt dialog returned text";
31static const char* kBeforeUnloadConfirmDialogMessage = "WebKitGTK+ beforeunload dialog message";
32
33class UIClientTest: public WebViewTest {
34public:
35 MAKE_GLIB_TEST_FIXTURE(UIClientTest);
36
37 enum WebViewEvents {
38 Create,
39 ReadyToShow,
40 RunAsModal,
41 Close
42 };
43
44 class WindowProperties {
45 public:
46 WindowProperties()
47 : m_isNull(true)
48 , m_toolbarVisible(true)
49 , m_statusbarVisible(true)
50 , m_scrollbarsVisible(true)
51 , m_menubarVisible(true)
52 , m_locationbarVisible(true)
53 , m_resizable(true)
54 , m_fullscreen(false)
55 {
56#if PLATFORM(GTK)
57 memset(&m_geometry, 0, sizeof(GdkRectangle));
58#endif
59 }
60
61 WindowProperties(WebKitWindowProperties* windowProperties)
62 : m_isNull(false)
63 , m_toolbarVisible(webkit_window_properties_get_toolbar_visible(windowProperties))
64 , m_statusbarVisible(webkit_window_properties_get_statusbar_visible(windowProperties))
65 , m_scrollbarsVisible(webkit_window_properties_get_scrollbars_visible(windowProperties))
66 , m_menubarVisible(webkit_window_properties_get_menubar_visible(windowProperties))
67 , m_locationbarVisible(webkit_window_properties_get_locationbar_visible(windowProperties))
68 , m_resizable(webkit_window_properties_get_resizable(windowProperties))
69 , m_fullscreen(webkit_window_properties_get_fullscreen(windowProperties))
70 {
71#if PLATFORM(GTK)
72 webkit_window_properties_get_geometry(windowProperties, &m_geometry);
73#endif
74 }
75
76 WindowProperties(cairo_rectangle_int_t* geometry, bool toolbarVisible, bool statusbarVisible, bool scrollbarsVisible, bool menubarVisible, bool locationbarVisible, bool resizable, bool fullscreen)
77 : m_isNull(false)
78 , m_geometry(*geometry)
79 , m_toolbarVisible(toolbarVisible)
80 , m_statusbarVisible(statusbarVisible)
81 , m_scrollbarsVisible(scrollbarsVisible)
82 , m_menubarVisible(menubarVisible)
83 , m_locationbarVisible(locationbarVisible)
84 , m_resizable(resizable)
85 , m_fullscreen(fullscreen)
86 {
87 }
88
89 bool isNull() const { return m_isNull; }
90
91 void assertEqual(const WindowProperties& other) const
92 {
93#if PLATFORM(GTK)
94 g_assert_cmpint(m_geometry.x, ==, other.m_geometry.x);
95 g_assert_cmpint(m_geometry.y, ==, other.m_geometry.y);
96 g_assert_cmpint(m_geometry.width, ==, other.m_geometry.width);
97 g_assert_cmpint(m_geometry.height, ==, other.m_geometry.height);
98#endif
99 g_assert_cmpint(static_cast<int>(m_toolbarVisible), ==, static_cast<int>(other.m_toolbarVisible));
100 g_assert_cmpint(static_cast<int>(m_statusbarVisible), ==, static_cast<int>(other.m_statusbarVisible));
101 g_assert_cmpint(static_cast<int>(m_scrollbarsVisible), ==, static_cast<int>(other.m_scrollbarsVisible));
102 g_assert_cmpint(static_cast<int>(m_menubarVisible), ==, static_cast<int>(other.m_menubarVisible));
103 g_assert_cmpint(static_cast<int>(m_locationbarVisible), ==, static_cast<int>(other.m_locationbarVisible));
104 g_assert_cmpint(static_cast<int>(m_resizable), ==, static_cast<int>(other.m_resizable));
105 g_assert_cmpint(static_cast<int>(m_fullscreen), ==, static_cast<int>(other.m_fullscreen));
106 }
107
108 private:
109 bool m_isNull;
110
111 cairo_rectangle_int_t m_geometry;
112
113 bool m_toolbarVisible;
114 bool m_statusbarVisible;
115 bool m_scrollbarsVisible;
116 bool m_menubarVisible;
117 bool m_locationbarVisible;
118
119 bool m_resizable;
120 bool m_fullscreen;
121 };
122
123 static void windowPropertiesNotifyCallback(GObject*, GParamSpec* paramSpec, UIClientTest* test)
124 {
125 test->m_windowPropertiesChanged.add(g_param_spec_get_name(paramSpec));
126 }
127
128 static WebKitWebView* viewCreateCallback(WebKitWebView* webView, WebKitNavigationAction* navigation, UIClientTest* test)
129 {
130 return test->viewCreate(webView, navigation);
131 }
132
133 static void viewReadyToShowCallback(WebKitWebView* webView, UIClientTest* test)
134 {
135 test->viewReadyToShow(webView);
136 }
137
138 static void viewCloseCallback(WebKitWebView* webView, UIClientTest* test)
139 {
140 test->viewClose(webView);
141 }
142
143 void scriptAlert(WebKitScriptDialog* dialog)
144 {
145 switch (m_scriptDialogType) {
146 case WEBKIT_SCRIPT_DIALOG_ALERT:
147 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kAlertDialogMessage);
148 break;
149 case WEBKIT_SCRIPT_DIALOG_CONFIRM:
150 g_assert_true(m_scriptDialogConfirmed);
151 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, "confirmed");
152
153 break;
154 case WEBKIT_SCRIPT_DIALOG_PROMPT:
155 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kPromptDialogReturnedText);
156 break;
157 case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
158 g_assert_not_reached();
159 break;
160 }
161
162 if (m_delayedScriptDialogs) {
163 webkit_script_dialog_ref(dialog);
164 RunLoop::main().dispatch([this, dialog] {
165 webkit_script_dialog_close(dialog);
166 webkit_script_dialog_unref(dialog);
167 g_main_loop_quit(m_mainLoop);
168 });
169 } else
170 g_main_loop_quit(m_mainLoop);
171 }
172
173 void scriptConfirm(WebKitScriptDialog* dialog)
174 {
175 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kConfirmDialogMessage);
176 m_scriptDialogConfirmed = !m_scriptDialogConfirmed;
177 webkit_script_dialog_confirm_set_confirmed(dialog, m_scriptDialogConfirmed);
178 }
179
180 void scriptPrompt(WebKitScriptDialog* dialog)
181 {
182 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kPromptDialogMessage);
183 g_assert_cmpstr(webkit_script_dialog_prompt_get_default_text(dialog), ==, "default");
184 webkit_script_dialog_prompt_set_text(dialog, kPromptDialogReturnedText);
185 }
186
187 void scriptBeforeUnloadConfirm(WebKitScriptDialog* dialog)
188 {
189 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kBeforeUnloadConfirmDialogMessage);
190 m_scriptDialogConfirmed = true;
191 webkit_script_dialog_confirm_set_confirmed(dialog, m_scriptDialogConfirmed);
192 }
193
194 static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, UIClientTest* test)
195 {
196 switch (webkit_script_dialog_get_dialog_type(dialog)) {
197 case WEBKIT_SCRIPT_DIALOG_ALERT:
198 test->scriptAlert(dialog);
199 break;
200 case WEBKIT_SCRIPT_DIALOG_CONFIRM:
201 test->scriptConfirm(dialog);
202 break;
203 case WEBKIT_SCRIPT_DIALOG_PROMPT:
204 test->scriptPrompt(dialog);
205 break;
206 case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
207 test->scriptBeforeUnloadConfirm(dialog);
208 break;
209 }
210
211 return TRUE;
212 }
213
214 static void mouseTargetChanged(WebKitWebView*, WebKitHitTestResult* hitTestResult, guint modifiers, UIClientTest* test)
215 {
216 g_assert_true(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
217 test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(hitTestResult));
218
219 test->m_mouseTargetHitTestResult = hitTestResult;
220 test->m_mouseTargetModifiers = modifiers;
221 g_main_loop_quit(test->m_mainLoop);
222 }
223
224 static gboolean permissionRequested(WebKitWebView*, WebKitPermissionRequest* request, UIClientTest* test)
225 {
226 g_assert_true(WEBKIT_IS_PERMISSION_REQUEST(request));
227 test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
228
229 if (test->m_verifyMediaTypes && WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) {
230 WebKitUserMediaPermissionRequest* userMediaRequest = WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request);
231 g_assert_true(webkit_user_media_permission_is_for_audio_device(userMediaRequest) == test->m_expectedAudioMedia);
232 g_assert_true(webkit_user_media_permission_is_for_video_device(userMediaRequest) == test->m_expectedVideoMedia);
233 }
234
235 if (test->m_allowPermissionRequests)
236 webkit_permission_request_allow(request);
237 else
238 webkit_permission_request_deny(request);
239
240 return TRUE;
241 }
242
243 static void permissionResultMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, UIClientTest* test)
244 {
245 test->m_permissionResult.reset(WebViewTest::javascriptResultToCString(javascriptResult));
246 g_main_loop_quit(test->m_mainLoop);
247 }
248
249 UIClientTest()
250 : m_scriptDialogType(WEBKIT_SCRIPT_DIALOG_ALERT)
251 , m_scriptDialogConfirmed(true)
252 , m_allowPermissionRequests(false)
253 , m_verifyMediaTypes(false)
254 , m_expectedAudioMedia(false)
255 , m_expectedVideoMedia(false)
256 , m_mouseTargetModifiers(0)
257 {
258 webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
259 g_signal_connect(m_webView, "create", G_CALLBACK(viewCreateCallback), this);
260 g_signal_connect(m_webView, "script-dialog", G_CALLBACK(scriptDialog), this);
261 g_signal_connect(m_webView, "mouse-target-changed", G_CALLBACK(mouseTargetChanged), this);
262 g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequested), this);
263 webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "permission");
264 g_signal_connect(m_userContentManager.get(), "script-message-received::permission", G_CALLBACK(permissionResultMessageReceivedCallback), this);
265 }
266
267 ~UIClientTest()
268 {
269 g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
270 g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
271 webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "permission");
272 }
273
274 static void tryWebViewCloseCallback(UIClientTest* test)
275 {
276 g_main_loop_quit(test->m_mainLoop);
277 }
278
279 void tryCloseAndWaitUntilClosed()
280 {
281 gulong handler = g_signal_connect_swapped(m_webView, "close", G_CALLBACK(tryWebViewCloseCallback), this);
282 // Use an idle because webkit_web_view_try_close can emit the close signal in the
283 // current run loop iteration.
284 g_idle_add([](gpointer data) -> gboolean {
285 webkit_web_view_try_close(WEBKIT_WEB_VIEW(data));
286 return G_SOURCE_REMOVE;
287 }, m_webView);
288 g_main_loop_run(m_mainLoop);
289 g_signal_handler_disconnect(m_webView, handler);
290 }
291
292 void waitUntilMainLoopFinishes()
293 {
294 g_main_loop_run(m_mainLoop);
295 }
296
297 const char* waitUntilPermissionResultMessageReceived()
298 {
299 m_permissionResult = nullptr;
300 g_main_loop_run(m_mainLoop);
301 return m_permissionResult.get();
302 }
303
304 void setExpectedWindowProperties(const WindowProperties& windowProperties)
305 {
306 m_windowProperties = windowProperties;
307 }
308
309 WebKitHitTestResult* moveMouseAndWaitUntilMouseTargetChanged(int x, int y, unsigned mouseModifiers = 0)
310 {
311 mouseMoveTo(x, y, mouseModifiers);
312 g_main_loop_run(m_mainLoop);
313 return m_mouseTargetHitTestResult.get();
314 }
315
316 void simulateUserInteraction()
317 {
318 runJavaScriptAndWaitUntilFinished("document.getElementById('testInput').focus()", nullptr);
319 // FIXME: Implement keyStroke in WPE.
320#if PLATFORM(GTK)
321 keyStroke(GDK_KEY_a);
322 keyStroke(GDK_KEY_b);
323 while (gtk_events_pending())
324 gtk_main_iteration();
325#endif
326 }
327
328 virtual WebKitWebView* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
329 {
330 g_assert_true(webView == m_webView);
331 g_assert_nonnull(navigation);
332
333 auto* newWebView = Test::createWebView(webkit_web_view_get_context(webView));
334#if PLATFORM(GTK)
335 g_object_ref_sink(newWebView);
336#endif
337
338 m_webViewEvents.append(Create);
339
340 WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(WEBKIT_WEB_VIEW(newWebView));
341 g_assert_nonnull(windowProperties);
342 assertObjectIsDeletedWhenTestFinishes(G_OBJECT(windowProperties));
343 m_windowPropertiesChanged.clear();
344
345 g_signal_connect(windowProperties, "notify", G_CALLBACK(windowPropertiesNotifyCallback), this);
346 g_signal_connect(newWebView, "ready-to-show", G_CALLBACK(viewReadyToShowCallback), this);
347 g_signal_connect(newWebView, "close", G_CALLBACK(viewCloseCallback), this);
348
349 return WEBKIT_WEB_VIEW(newWebView);
350 }
351
352 virtual void viewReadyToShow(WebKitWebView* webView)
353 {
354 g_assert_true(webView != m_webView);
355
356 WebKitWindowProperties* windowProperties = webkit_web_view_get_window_properties(webView);
357 g_assert_nonnull(windowProperties);
358 if (!m_windowProperties.isNull())
359 WindowProperties(windowProperties).assertEqual(m_windowProperties);
360
361 m_webViewEvents.append(ReadyToShow);
362 }
363
364 virtual void viewClose(WebKitWebView* webView)
365 {
366 g_assert_true(webView != m_webView);
367
368 m_webViewEvents.append(Close);
369 g_object_unref(webView);
370
371 g_main_loop_quit(m_mainLoop);
372 }
373
374 Vector<WebViewEvents> m_webViewEvents;
375 WebKitScriptDialogType m_scriptDialogType;
376 bool m_scriptDialogConfirmed;
377 bool m_delayedScriptDialogs { false };
378 bool m_allowPermissionRequests;
379 gboolean m_verifyMediaTypes;
380 gboolean m_expectedAudioMedia;
381 gboolean m_expectedVideoMedia;
382 WindowProperties m_windowProperties;
383 HashSet<WTF::String> m_windowPropertiesChanged;
384 GRefPtr<WebKitHitTestResult> m_mouseTargetHitTestResult;
385 unsigned m_mouseTargetModifiers;
386 GUniquePtr<char> m_permissionResult;
387};
388
389static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer)
390{
391 test->loadHtml("<html><body onLoad=\"window.open().close();\"></html>", 0);
392 test->waitUntilMainLoopFinishes();
393
394 Vector<UIClientTest::WebViewEvents>& events = test->m_webViewEvents;
395 g_assert_cmpint(events.size(), ==, 3);
396 g_assert_cmpint(events[0], ==, UIClientTest::Create);
397 g_assert_cmpint(events[1], ==, UIClientTest::ReadyToShow);
398 g_assert_cmpint(events[2], ==, UIClientTest::Close);
399}
400
401#if PLATFORM(GTK)
402class CreateNavigationDataTest: public UIClientTest {
403public:
404 MAKE_GLIB_TEST_FIXTURE(CreateNavigationDataTest);
405
406 CreateNavigationDataTest()
407 : m_navigation(nullptr)
408 {
409 }
410
411 ~CreateNavigationDataTest()
412 {
413 clearNavigation();
414 }
415
416 void clearNavigation()
417 {
418 if (m_navigation)
419 webkit_navigation_action_free(m_navigation);
420 m_navigation = nullptr;
421 }
422
423 WebKitWebView* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
424 {
425 g_assert_nonnull(navigation);
426 g_assert_null(m_navigation);
427 m_navigation = webkit_navigation_action_copy(navigation);
428 g_main_loop_quit(m_mainLoop);
429 return nullptr;
430 }
431
432 void loadHTML(const char* html)
433 {
434 clearNavigation();
435 WebViewTest::loadHtml(html, nullptr);
436 }
437
438 void clickAndWaitUntilMainLoopFinishes(int x, int y)
439 {
440 clearNavigation();
441 clickMouseButton(x, y, 1);
442 g_main_loop_run(m_mainLoop);
443 }
444
445 WebKitNavigationAction* m_navigation;
446};
447
448static void testWebViewCreateNavigationData(CreateNavigationDataTest* test, gconstpointer)
449{
450#if PLATFORM(GTK)
451 test->showInWindowAndWaitUntilMapped();
452#endif
453
454 test->loadHTML(
455 "<html><body>"
456 "<input style=\"position:absolute; left:0; top:0; margin:0; padding:0\" type=\"button\" value=\"click to show a popup\" onclick=\"window.open('data:foo');\"/>"
457 "<a style=\"position:absolute; left:20; top:20;\" href=\"data:bar\" target=\"_blank\">popup link</a>"
458 "</body></html>");
459 test->waitUntilLoadFinished();
460
461 // Click on a button.
462 test->clickAndWaitUntilMainLoopFinishes(5, 5);
463 g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:foo");
464 g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
465 // FIXME: This should be button 1.
466 g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0);
467 g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
468 g_assert_true(webkit_navigation_action_is_user_gesture(test->m_navigation));
469
470 // Click on a link.
471 test->clickAndWaitUntilMainLoopFinishes(21, 21);
472 g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:bar");
473 g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_LINK_CLICKED);
474 g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 1);
475 g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
476 g_assert_true(webkit_navigation_action_is_user_gesture(test->m_navigation));
477
478 // No user interaction.
479 test->loadHTML("<html><body onLoad=\"window.open();\"></html>");
480 test->waitUntilMainLoopFinishes();
481
482 g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "about:blank");
483 g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
484 g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0);
485 g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
486 g_assert_false(webkit_navigation_action_is_user_gesture(test->m_navigation));
487}
488#endif // PLATFORM(GTK)
489
490#if PLATFORM(GTK)
491static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType)
492{
493 GtkFileFilterInfo filterInfo;
494 filterInfo.contains = GTK_FILE_FILTER_MIME_TYPE;
495 filterInfo.mime_type = mimeType;
496 return gtk_file_filter_filter(filter, &filterInfo);
497}
498#endif
499
500class ModalDialogsTest: public UIClientTest {
501public:
502 MAKE_GLIB_TEST_FIXTURE(ModalDialogsTest);
503
504 static void dialogRunAsModalCallback(WebKitWebView* webView, ModalDialogsTest* test)
505 {
506 g_assert_true(webView != test->m_webView);
507 test->m_webViewEvents.append(RunAsModal);
508 }
509
510 WebKitWebView* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
511 {
512 g_assert_true(webView == m_webView);
513
514 auto* newWebView = UIClientTest::viewCreate(webView, navigation);
515 g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(dialogRunAsModalCallback), this);
516 return newWebView;
517 }
518
519 void viewReadyToShow(WebKitWebView* webView)
520 {
521 g_assert_true(webView != m_webView);
522 m_webViewEvents.append(ReadyToShow);
523 }
524};
525
526static void testWebViewAllowModalDialogs(ModalDialogsTest* test, gconstpointer)
527{
528 WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
529 webkit_settings_set_allow_modal_dialogs(settings, TRUE);
530
531 test->loadHtml("<html><body onload=\"window.showModalDialog('data:text/html,<html><body/><script>window.close();</script></html>')\"></body></html>", 0);
532 test->waitUntilMainLoopFinishes();
533
534 Vector<UIClientTest::WebViewEvents>& events = test->m_webViewEvents;
535 g_assert_cmpint(events.size(), ==, 4);
536 g_assert_cmpint(events[0], ==, UIClientTest::Create);
537 g_assert_cmpint(events[1], ==, UIClientTest::ReadyToShow);
538 g_assert_cmpint(events[2], ==, UIClientTest::RunAsModal);
539 g_assert_cmpint(events[3], ==, UIClientTest::Close);
540}
541
542static void testWebViewDisallowModalDialogs(ModalDialogsTest* test, gconstpointer)
543{
544 WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
545 webkit_settings_set_allow_modal_dialogs(settings, FALSE);
546
547 test->loadHtml("<html><body onload=\"window.showModalDialog('data:text/html,<html><body/><script>window.close();</script></html>')\"></body></html>", 0);
548 // We need to use a timeout here because the viewClose() function
549 // won't ever be called as the dialog won't be created.
550 test->wait(1);
551
552 Vector<UIClientTest::WebViewEvents>& events = test->m_webViewEvents;
553 g_assert_cmpint(events.size(), ==, 0);
554}
555
556static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer)
557{
558#if PLATFORM(GTK)
559 test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
560#endif
561
562 static const char* htmlOnLoadFormat = "<html><body onLoad=\"%s\"></body></html>";
563 static const char* jsAlertFormat = "alert('%s')";
564 static const char* jsConfirmFormat = "do { confirmed = confirm('%s'); } while (!confirmed); alert('confirmed');";
565 static const char* jsPromptFormat = "alert(prompt('%s', 'default'));";
566#if PLATFORM(GTK)
567 static const char* htmlOnBeforeUnloadFormat =
568 "<html><body onbeforeunload=\"return beforeUnloadHandler();\"><input id=\"testInput\" type=\"text\"></input><script>function beforeUnloadHandler() { return \"%s\"; }</script></body></html>";
569#endif
570
571 for (unsigned i = 0; i <= 1; ++i) {
572 test->m_delayedScriptDialogs = !!i;
573
574 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT;
575 GUniquePtr<char> alertDialogMessage(g_strdup_printf(jsAlertFormat, kAlertDialogMessage));
576 GUniquePtr<char> alertHTML(g_strdup_printf(htmlOnLoadFormat, alertDialogMessage.get()));
577 test->loadHtml(alertHTML.get(), nullptr);
578 test->waitUntilMainLoopFinishes();
579 webkit_web_view_stop_loading(test->m_webView);
580 test->waitUntilLoadFinished();
581
582 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM;
583 GUniquePtr<char> confirmDialogMessage(g_strdup_printf(jsConfirmFormat, kConfirmDialogMessage));
584 GUniquePtr<char> confirmHTML(g_strdup_printf(htmlOnLoadFormat, confirmDialogMessage.get()));
585 test->loadHtml(confirmHTML.get(), nullptr);
586 test->waitUntilMainLoopFinishes();
587 webkit_web_view_stop_loading(test->m_webView);
588 test->waitUntilLoadFinished();
589
590 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT;
591 GUniquePtr<char> promptDialogMessage(g_strdup_printf(jsPromptFormat, kPromptDialogMessage));
592 GUniquePtr<char> promptHTML(g_strdup_printf(htmlOnLoadFormat, promptDialogMessage.get()));
593 test->loadHtml(promptHTML.get(), nullptr);
594 test->waitUntilMainLoopFinishes();
595 webkit_web_view_stop_loading(test->m_webView);
596 test->waitUntilLoadFinished();
597 }
598
599 test->m_delayedScriptDialogs = false;
600
601 // FIXME: implement simulateUserInteraction in WPE.
602#if PLATFORM(GTK)
603 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM;
604 GUniquePtr<char> beforeUnloadDialogHTML(g_strdup_printf(htmlOnBeforeUnloadFormat, kBeforeUnloadConfirmDialogMessage));
605 test->loadHtml(beforeUnloadDialogHTML.get(), nullptr);
606 test->waitUntilLoadFinished();
607
608 // Reload should trigger onbeforeunload.
609#if 0
610 test->simulateUserInteraction();
611 // FIXME: reloading HTML data doesn't emit finished load event.
612 // See https://bugs.webkit.org/show_bug.cgi?id=139089.
613 test->m_scriptDialogConfirmed = false;
614 webkit_web_view_reload(test->m_webView);
615 test->waitUntilLoadFinished();
616 g_assert_true(test->m_scriptDialogConfirmed);
617#endif
618
619 // Navigation should trigger onbeforeunload.
620 test->simulateUserInteraction();
621 test->m_scriptDialogConfirmed = false;
622 test->loadHtml("<html></html>", nullptr);
623 test->waitUntilLoadFinished();
624 g_assert_true(test->m_scriptDialogConfirmed);
625
626 // Try close should trigger onbeforeunload.
627 test->m_scriptDialogConfirmed = false;
628 test->loadHtml(beforeUnloadDialogHTML.get(), nullptr);
629 test->waitUntilLoadFinished();
630 test->simulateUserInteraction();
631 test->tryCloseAndWaitUntilClosed();
632 g_assert_true(test->m_scriptDialogConfirmed);
633
634 // Try close on a page with no unload handlers should not trigger onbeforeunload,
635 // but should actually close the page.
636 test->m_scriptDialogConfirmed = false;
637 test->loadHtml("<html><body></body></html>", nullptr);
638 test->waitUntilLoadFinished();
639 // We got a onbeforeunload of the previous page.
640 g_assert_true(test->m_scriptDialogConfirmed);
641 test->m_scriptDialogConfirmed = false;
642 test->tryCloseAndWaitUntilClosed();
643 g_assert_false(test->m_scriptDialogConfirmed);
644#endif // PLATFORM(GTK)
645}
646
647static void testWebViewWindowProperties(UIClientTest* test, gconstpointer)
648{
649 static const char* windowProrpertiesString = "left=100,top=150,width=400,height=400,location=no,menubar=no,status=no,toolbar=no,scrollbars=no";
650 cairo_rectangle_int_t geometry = { 100, 150, 400, 400 };
651 test->setExpectedWindowProperties(UIClientTest::WindowProperties(&geometry, false, false, false, false, false, true, false));
652
653 GUniquePtr<char> htmlString(g_strdup_printf("<html><body onLoad=\"window.open('', '', '%s').close();\"></body></html>", windowProrpertiesString));
654 test->loadHtml(htmlString.get(), 0);
655 test->waitUntilMainLoopFinishes();
656
657 static const char* propertiesChanged[] = {
658#if PLATFORM(GTK)
659 "geometry",
660#endif
661 "locationbar-visible", "menubar-visible", "statusbar-visible", "toolbar-visible", "scrollbars-visible"
662 };
663 for (size_t i = 0; i < G_N_ELEMENTS(propertiesChanged); ++i)
664 g_assert_true(test->m_windowPropertiesChanged.contains(propertiesChanged[i]));
665
666 Vector<UIClientTest::WebViewEvents>& events = test->m_webViewEvents;
667 g_assert_cmpint(events.size(), ==, 3);
668 g_assert_cmpint(events[0], ==, UIClientTest::Create);
669 g_assert_cmpint(events[1], ==, UIClientTest::ReadyToShow);
670 g_assert_cmpint(events[2], ==, UIClientTest::Close);
671}
672
673#if PLATFORM(GTK)
674static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
675{
676 test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
677
678 const char* linksHoveredHTML =
679 "<html><head>"
680 " <script>"
681 " window.onload = function () {"
682 " window.getSelection().removeAllRanges();"
683 " var select_range = document.createRange();"
684 " select_range.selectNodeContents(document.getElementById('text_to_select'));"
685 " window.getSelection().addRange(select_range);"
686 " }"
687 " </script>"
688 "</head><body>"
689 " <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>"
690 " <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>"
691 " <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>"
692 " <input style='position:absolute; left:1; top:30' size='10'></input>"
693 " <video style='position:absolute; left:1; top:100' width='300' height='300' controls='controls' preload='none'><source src='movie.ogg' type='video/ogg' /></video>"
694 " <p style='position:absolute; left:1; top:120' id='text_to_select'>Lorem ipsum.</p>"
695 "</body></html>";
696
697 test->loadHtml(linksHoveredHTML, "file:///");
698 test->waitUntilLoadFinished();
699
700 // Move over link.
701 WebKitHitTestResult* hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(1, 1);
702 g_assert_true(webkit_hit_test_result_context_is_link(hitTestResult));
703 g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult));
704 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
705 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
706 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
707 g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/");
708 g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Title");
709 g_assert_cmpstr(webkit_hit_test_result_get_link_label(hitTestResult), ==, "WebKitGTK+ Website");
710 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
711
712 // Move out of the link.
713 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(0, 0);
714 g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult));
715 g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult));
716 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
717 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
718 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
719 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
720
721 // Move over image with GDK_CONTROL_MASK.
722 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(1, 10, GDK_CONTROL_MASK);
723 g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult));
724 g_assert_true(webkit_hit_test_result_context_is_image(hitTestResult));
725 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
726 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
727 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
728 g_assert_false(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
729 g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef");
730 g_assert_true(test->m_mouseTargetModifiers & GDK_CONTROL_MASK);
731
732 // Move over image link.
733 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(1, 20);
734 g_assert_true(webkit_hit_test_result_context_is_link(hitTestResult));
735 g_assert_true(webkit_hit_test_result_context_is_image(hitTestResult));
736 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
737 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
738 g_assert_false(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
739 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
740 g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/logo");
741 g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef");
742 g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Logo");
743 g_assert_false(webkit_hit_test_result_get_link_label(hitTestResult));
744 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
745
746 // Move over media.
747 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(1, 100);
748 g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult));
749 g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult));
750 g_assert_true(webkit_hit_test_result_context_is_media(hitTestResult));
751 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
752 g_assert_false(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
753 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
754 g_assert_cmpstr(webkit_hit_test_result_get_media_uri(hitTestResult), ==, "file:///movie.ogg");
755 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
756
757 // Mover over input.
758 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(5, 35);
759 g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult));
760 g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult));
761 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
762 g_assert_false(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
763 g_assert_true(webkit_hit_test_result_context_is_editable(hitTestResult));
764 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
765 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
766
767 // Move over scrollbar.
768 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(gtk_widget_get_allocated_width(GTK_WIDGET(test->m_webView)) - 4, 5);
769 g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult));
770 g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult));
771 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
772 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
773 g_assert_true(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
774 g_assert_false(webkit_hit_test_result_context_is_selection(hitTestResult));
775 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
776
777 // Move over selection.
778 hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(2, 145);
779 g_assert_false(webkit_hit_test_result_context_is_link(hitTestResult));
780 g_assert_false(webkit_hit_test_result_context_is_image(hitTestResult));
781 g_assert_false(webkit_hit_test_result_context_is_media(hitTestResult));
782 g_assert_false(webkit_hit_test_result_context_is_editable(hitTestResult));
783 g_assert_false(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
784 g_assert_true(webkit_hit_test_result_context_is_selection(hitTestResult));
785 g_assert_cmpuint(test->m_mouseTargetModifiers, ==, 0);
786}
787#endif // PLATFORM(GTK)
788
789static void testWebViewGeolocationPermissionRequests(UIClientTest* test, gconstpointer)
790{
791 // Some versions of geoclue give a runtime warning because it tries
792 // to register the error quark twice. See https://bugs.webkit.org/show_bug.cgi?id=89858.
793 // Make warnings non-fatal for this test to make it pass.
794 test->removeLogFatalFlag(G_LOG_LEVEL_WARNING);
795#if PLATFORM(GTK)
796 test->showInWindowAndWaitUntilMapped();
797#endif
798 static const char* geolocationRequestHTML =
799 "<html>"
800 " <script>"
801 " function runTest()"
802 " {"
803 " navigator.geolocation.getCurrentPosition(function(p) { window.webkit.messageHandlers.permission.postMessage('OK'); },"
804 " function(e) { window.webkit.messageHandlers.permission.postMessage(e.code.toString()); });"
805 " }"
806 " </script>"
807 " <body onload='runTest();'></body>"
808 "</html>";
809
810 // Geolocation is not allowed from insecure connections like HTTP,
811 // POSITION_UNAVAILABLE ('2') is returned in that case without even
812 // asking the API layer.
813 test->m_allowPermissionRequests = false;
814 test->loadHtml(geolocationRequestHTML, "http://foo.com/bar");
815 const gchar* result = test->waitUntilPermissionResultMessageReceived();
816 g_assert_cmpstr(result, ==, "2");
817
818 // Test denying a permission request. PERMISSION_DENIED ('1') is
819 // returned in this case.
820 test->m_allowPermissionRequests = false;
821 test->loadHtml(geolocationRequestHTML, "https://foo.com/bar");
822 result = test->waitUntilPermissionResultMessageReceived();
823 g_assert_cmpstr(result, ==, "1");
824
825 // Test allowing a permission request. Result should be different
826 // to PERMISSION_DENIED ('1').
827 test->m_allowPermissionRequests = true;
828 test->loadHtml(geolocationRequestHTML, "https://foo.com/bar");
829 result = test->waitUntilPermissionResultMessageReceived();
830 g_assert_cmpstr(result, !=, "1");
831 test->addLogFatalFlag(G_LOG_LEVEL_WARNING);
832}
833
834#if ENABLE(MEDIA_STREAM)
835static void testWebViewUserMediaEnumerateDevicesPermissionCheck(UIClientTest* test, gconstpointer)
836{
837 WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
838 gboolean enabled = webkit_settings_get_enable_media_stream(settings);
839 webkit_settings_set_enable_media_stream(settings, TRUE);
840
841#if PLATFORM(GTK)
842 test->showInWindowAndWaitUntilMapped();
843#endif
844 static const char* userMediaRequestHTML =
845 "<html>"
846 " <script>"
847 " function runTest()"
848 " {"
849 " navigator.mediaDevices.enumerateDevices().then("
850 " function(devices) { "
851 " devices.forEach(function(device) {"
852 " if (device.label) document.title = \"OK\";"
853 " else document.title = \"Permission denied\";"
854 " })"
855 " })"
856 " }"
857 " </script>"
858 " <body onload='runTest();'></body>"
859 "</html>";
860
861 test->m_verifyMediaTypes = TRUE;
862
863 // Test denying a permission request.
864 test->m_allowPermissionRequests = false;
865 test->loadHtml(userMediaRequestHTML, nullptr);
866 test->waitUntilTitleChangedTo("Permission denied");
867
868 // Test allowing a permission request.
869 test->m_allowPermissionRequests = true;
870 test->loadHtml(userMediaRequestHTML, nullptr);
871 test->waitUntilTitleChangedTo("OK");
872
873 webkit_settings_set_enable_media_stream(settings, enabled);
874}
875
876static void testWebViewUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
877{
878 WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
879 gboolean enabled = webkit_settings_get_enable_media_stream(settings);
880 webkit_settings_set_enable_media_stream(settings, TRUE);
881
882#if PLATFORM(GTK)
883 test->showInWindowAndWaitUntilMapped();
884#endif
885 static const char* userMediaRequestHTML =
886 "<html>"
887 " <script>"
888 " function runTest()"
889 " {"
890 " navigator.webkitGetUserMedia({audio: true, video: true},"
891 " function(s) { document.title = \"OK\" },"
892 " function(e) { document.title = e.name });"
893 " }"
894 " </script>"
895 " <body onload='runTest();'></body>"
896 "</html>";
897
898 test->m_verifyMediaTypes = TRUE;
899 test->m_expectedAudioMedia = TRUE;
900 test->m_expectedVideoMedia = TRUE;
901
902 // Test denying a permission request.
903 test->m_allowPermissionRequests = false;
904 test->loadHtml(userMediaRequestHTML, nullptr);
905 test->waitUntilTitleChangedTo("PermissionDeniedError");
906
907 // Test allowing a permission request.
908 test->m_allowPermissionRequests = true;
909 test->loadHtml(userMediaRequestHTML, nullptr);
910 test->waitUntilTitleChangedTo("OK");
911
912 webkit_settings_set_enable_media_stream(settings, enabled);
913}
914
915static void testWebViewAudioOnlyUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
916{
917 WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
918 gboolean enabled = webkit_settings_get_enable_media_stream(settings);
919 webkit_settings_set_enable_media_stream(settings, TRUE);
920
921#if PLATFORM(GTK)
922 test->showInWindowAndWaitUntilMapped();
923#endif
924 static const char* userMediaRequestHTML =
925 "<html>"
926 " <script>"
927 " function runTest()"
928 " {"
929 " navigator.webkitGetUserMedia({audio: true, video: false},"
930 " function(s) { document.title = \"OK\" },"
931 " function(e) { document.title = e.name });"
932 " }"
933 " </script>"
934 " <body onload='runTest();'></body>"
935 "</html>";
936
937 test->m_verifyMediaTypes = TRUE;
938 test->m_expectedAudioMedia = TRUE;
939 test->m_expectedVideoMedia = FALSE;
940
941 // Test denying a permission request.
942 test->m_allowPermissionRequests = false;
943 test->loadHtml(userMediaRequestHTML, nullptr);
944 test->waitUntilTitleChangedTo("PermissionDeniedError");
945
946 webkit_settings_set_enable_media_stream(settings, enabled);
947}
948#endif // ENABLE(MEDIA_STREAM)
949
950#if PLATFORM(GTK)
951class FileChooserTest: public UIClientTest {
952public:
953 MAKE_GLIB_TEST_FIXTURE(FileChooserTest);
954
955 FileChooserTest()
956 {
957 g_signal_connect(m_webView, "run-file-chooser", G_CALLBACK(runFileChooserCallback), this);
958 }
959
960 static gboolean runFileChooserCallback(WebKitWebView*, WebKitFileChooserRequest* request, FileChooserTest* test)
961 {
962 test->runFileChooser(request);
963 return TRUE;
964 }
965
966 void runFileChooser(WebKitFileChooserRequest* request)
967 {
968 assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
969 m_fileChooserRequest = request;
970 g_main_loop_quit(m_mainLoop);
971 }
972
973 WebKitFileChooserRequest* clickMouseButtonAndWaitForFileChooserRequest(int x, int y)
974 {
975 clickMouseButton(x, y);
976 g_main_loop_run(m_mainLoop);
977 return m_fileChooserRequest.get();
978 }
979
980private:
981 GRefPtr<WebKitFileChooserRequest> m_fileChooserRequest;
982};
983
984static void testWebViewFileChooserRequest(FileChooserTest* test, gconstpointer)
985{
986#if PLATFORM(GTK)
987 test->showInWindowAndWaitUntilMapped();
988#endif
989 static const char* fileChooserHTMLFormat = "<html><body><input style='position:absolute;left:0;top:0;margin:0;padding:0' type='file' %s/></body></html>";
990
991 // Multiple selections not allowed, no MIME filtering.
992 GUniquePtr<char> simpleFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, ""));
993 test->loadHtml(simpleFileUploadHTML.get(), 0);
994 test->waitUntilLoadFinished();
995 WebKitFileChooserRequest* fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5);
996 g_assert_false(webkit_file_chooser_request_get_select_multiple(fileChooserRequest));
997
998 const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest);
999 g_assert_null(mimeTypes);
1000#if PLATFORM(GTK)
1001 GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest);
1002 g_assert_null(filter);
1003#endif
1004 const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest);
1005 g_assert_null(selectedFiles);
1006 webkit_file_chooser_request_cancel(fileChooserRequest);
1007
1008 // Multiple selections allowed, no MIME filtering, some pre-selected files.
1009 GUniquePtr<char> multipleSelectionFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "multiple"));
1010 test->loadHtml(multipleSelectionFileUploadHTML.get(), 0);
1011 test->waitUntilLoadFinished();
1012 fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5);
1013 g_assert_true(webkit_file_chooser_request_get_select_multiple(fileChooserRequest));
1014
1015 mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest);
1016 g_assert_null(mimeTypes);
1017#if PLATFORM(GTK)
1018 filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest);
1019 g_assert_null(filter);
1020#endif
1021 selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest);
1022 g_assert_null(selectedFiles);
1023
1024 // Select some files.
1025 const gchar* filesToSelect[4] = { "/foo", "/foo/bar", "/foo/bar/baz", 0 };
1026 webkit_file_chooser_request_select_files(fileChooserRequest, filesToSelect);
1027
1028 // Check the files that have been just selected.
1029 selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest);
1030 g_assert_nonnull(selectedFiles);
1031 g_assert_cmpstr(selectedFiles[0], ==, "/foo");
1032 g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar");
1033 g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz");
1034 g_assert_null(selectedFiles[3]);
1035
1036 // Perform another request to check if the list of files selected
1037 // in the previous step appears now as part of the new request.
1038 fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5);
1039 selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest);
1040 g_assert_nonnull(selectedFiles);
1041 g_assert_cmpstr(selectedFiles[0], ==, "/foo");
1042 g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar");
1043 g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz");
1044 g_assert_null(selectedFiles[3]);
1045 webkit_file_chooser_request_cancel(fileChooserRequest);
1046
1047 // Multiple selections not allowed, only accept images, audio and video files..
1048 GUniquePtr<char> mimeFilteredFileUploadHTML(g_strdup_printf(fileChooserHTMLFormat, "accept='audio/*,video/*,image/*'"));
1049 test->loadHtml(mimeFilteredFileUploadHTML.get(), 0);
1050 test->waitUntilLoadFinished();
1051 fileChooserRequest = test->clickMouseButtonAndWaitForFileChooserRequest(5, 5);
1052 g_assert_false(webkit_file_chooser_request_get_select_multiple(fileChooserRequest));
1053
1054 mimeTypes = webkit_file_chooser_request_get_mime_types(fileChooserRequest);
1055 g_assert_nonnull(mimeTypes);
1056 g_assert_cmpstr(mimeTypes[0], ==, "audio/*");
1057 g_assert_cmpstr(mimeTypes[1], ==, "video/*");
1058 g_assert_cmpstr(mimeTypes[2], ==, "image/*");
1059 g_assert_null(mimeTypes[3]);
1060
1061#if PLATFORM(GTK)
1062 filter = webkit_file_chooser_request_get_mime_types_filter(fileChooserRequest);
1063 g_assert_true(GTK_IS_FILE_FILTER(filter));
1064 g_assert_true(checkMimeTypeForFilter(filter, "audio/*"));
1065 g_assert_true(checkMimeTypeForFilter(filter, "video/*"));
1066 g_assert_true(checkMimeTypeForFilter(filter, "image/*"));
1067#endif
1068
1069 selectedFiles = webkit_file_chooser_request_get_selected_files(fileChooserRequest);
1070 g_assert_null(selectedFiles);
1071 webkit_file_chooser_request_cancel(fileChooserRequest);
1072}
1073#endif // PLATFORM(GTK)
1074
1075#if PLATFORM(GTK)
1076class ColorChooserTest: public WebViewTest {
1077public:
1078 MAKE_GLIB_TEST_FIXTURE(ColorChooserTest);
1079
1080 static gboolean runColorChooserCallback(WebKitWebView*, WebKitColorChooserRequest* request, ColorChooserTest* test)
1081 {
1082 test->runColorChooser(request);
1083 return TRUE;
1084 }
1085
1086 static void requestFinishedCallback(WebKitColorChooserRequest* request, ColorChooserTest* test)
1087 {
1088 g_assert_true(test->m_request.get() == request);
1089 test->m_request = nullptr;
1090 if (g_main_loop_is_running(test->m_mainLoop))
1091 g_main_loop_quit(test->m_mainLoop);
1092 }
1093
1094 ColorChooserTest()
1095 {
1096 g_signal_connect(m_webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), this);
1097 }
1098
1099 void runColorChooser(WebKitColorChooserRequest* request)
1100 {
1101 g_assert_true(WEBKIT_IS_COLOR_CHOOSER_REQUEST(request));
1102 assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
1103 m_request = request;
1104 g_signal_connect(request, "finished", G_CALLBACK(requestFinishedCallback), this);
1105 g_main_loop_quit(m_mainLoop);
1106 }
1107
1108 void finishRequest()
1109 {
1110 g_assert_nonnull(m_request.get());
1111 webkit_color_chooser_request_finish(m_request.get());
1112 g_assert_null(m_request);
1113 }
1114
1115 void cancelRequest()
1116 {
1117 g_assert_nonnull(m_request.get());
1118 webkit_color_chooser_request_cancel(m_request.get());
1119 g_assert_null(m_request);
1120 }
1121
1122 WebKitColorChooserRequest* clickMouseButtonAndWaitForColorChooserRequest(int x, int y)
1123 {
1124 clickMouseButton(x, y);
1125 g_main_loop_run(m_mainLoop);
1126 g_assert_nonnull(m_request.get());
1127 return m_request.get();
1128 }
1129
1130private:
1131 GRefPtr<WebKitColorChooserRequest> m_request;
1132};
1133
1134static void testWebViewColorChooserRequest(ColorChooserTest* test, gconstpointer)
1135{
1136 static const char* colorChooserHTMLFormat = "<html><body><input style='position:absolute;left:1;top:1;margin:0;padding:0;width:45;height:25' type='color' %s/></body></html>";
1137 test->showInWindowAndWaitUntilMapped();
1138
1139 GUniquePtr<char> defaultColorHTML(g_strdup_printf(colorChooserHTMLFormat, ""));
1140 test->loadHtml(defaultColorHTML.get(), nullptr);
1141 test->waitUntilLoadFinished();
1142 WebKitColorChooserRequest* request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5);
1143
1144 // Default color is black (#000000).
1145 GdkRGBA rgba1;
1146 GdkRGBA rgba2 = { 0., 0., 0., 1. };
1147 webkit_color_chooser_request_get_rgba(request, &rgba1);
1148 g_assert_true(gdk_rgba_equal(&rgba1, &rgba2));
1149
1150 // Set a different color.
1151 rgba2.green = 1;
1152 webkit_color_chooser_request_set_rgba(request, &rgba2);
1153 webkit_color_chooser_request_get_rgba(request, &rgba1);
1154 g_assert_true(gdk_rgba_equal(&rgba1, &rgba2));
1155
1156 GdkRectangle rect;
1157 webkit_color_chooser_request_get_element_rectangle(request, &rect);
1158 g_assert_cmpint(rect.x, == , 1);
1159 g_assert_cmpint(rect.y, == , 1);
1160 g_assert_cmpint(rect.width, == , 45);
1161 g_assert_cmpint(rect.height, == , 25);
1162
1163 test->finishRequest();
1164
1165 // Use an initial color.
1166 GUniquePtr<char> initialColorHTML(g_strdup_printf(colorChooserHTMLFormat, "value='#FF00FF'"));
1167 test->loadHtml(initialColorHTML.get(), nullptr);
1168 test->waitUntilLoadFinished();
1169 request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5);
1170
1171 webkit_color_chooser_request_get_rgba(request, &rgba1);
1172 GdkRGBA rgba3 = { 1., 0., 1., 1. };
1173 g_assert_true(gdk_rgba_equal(&rgba1, &rgba3));
1174
1175 test->cancelRequest();
1176}
1177#endif // PLATFORM(GTK)
1178
1179void beforeAll()
1180{
1181 UIClientTest::add("WebKitWebView", "create-ready-close", testWebViewCreateReadyClose);
1182 // FIXME: Implement mouse clicks in WPE.
1183#if PLATFORM(GTK)
1184 CreateNavigationDataTest::add("WebKitWebView", "create-navigation-data", testWebViewCreateNavigationData);
1185#endif
1186 ModalDialogsTest::add("WebKitWebView", "allow-modal-dialogs", testWebViewAllowModalDialogs);
1187 ModalDialogsTest::add("WebKitWebView", "disallow-modal-dialogs", testWebViewDisallowModalDialogs);
1188 UIClientTest::add("WebKitWebView", "javascript-dialogs", testWebViewJavaScriptDialogs);
1189 UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties);
1190 // FIXME: Implement mouse move in WPE.
1191#if PLATFORM(GTK)
1192 UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget);
1193#endif
1194 UIClientTest::add("WebKitWebView", "geolocation-permission-requests", testWebViewGeolocationPermissionRequests);
1195#if ENABLE(MEDIA_STREAM)
1196 UIClientTest::add("WebKitWebView", "usermedia-enumeratedevices-permission-check", testWebViewUserMediaEnumerateDevicesPermissionCheck);
1197 UIClientTest::add("WebKitWebView", "usermedia-permission-requests", testWebViewUserMediaPermissionRequests);
1198 UIClientTest::add("WebKitWebView", "audio-usermedia-permission-request", testWebViewAudioOnlyUserMediaPermissionRequests);
1199#endif
1200 // FIXME: Implement mouse click in WPE.
1201#if PLATFORM(GTK)
1202 FileChooserTest::add("WebKitWebView", "file-chooser-request", testWebViewFileChooserRequest);
1203#endif
1204#if PLATFORM(GTK)
1205 ColorChooserTest::add("WebKitWebView", "color-chooser-request", testWebViewColorChooserRequest);
1206#endif
1207}
1208
1209void afterAll()
1210{
1211}
1212