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