diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp | 469 |
1 files changed, 443 insertions, 26 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp index d24edc601..4c44039cc 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp @@ -20,13 +20,14 @@ #include "config.h" #include "WebViewTest.h" #include <wtf/HashSet.h> -#include <wtf/gobject/GRefPtr.h> +#include <wtf/glib/GRefPtr.h> #include <wtf/text/StringHash.h> static const char* kAlertDialogMessage = "WebKitGTK+ alert dialog message"; static const char* kConfirmDialogMessage = "WebKitGTK+ confirm dialog message"; static const char* kPromptDialogMessage = "WebKitGTK+ prompt dialog message"; static const char* kPromptDialogReturnedText = "WebKitGTK+ prompt dialog returned text"; +static const char* kBeforeUnloadConfirmDialogMessage = "WebKitGTK+ beforeunload dialog message"; class UIClientTest: public WebViewTest { public: @@ -117,9 +118,9 @@ public: test->m_windowPropertiesChanged.add(g_param_spec_get_name(paramSpec)); } - static GtkWidget* viewCreateCallback(WebKitWebView* webView, UIClientTest* test) + static GtkWidget* viewCreateCallback(WebKitWebView* webView, WebKitNavigationAction* navigation, UIClientTest* test) { - return test->viewCreate(webView); + return test->viewCreate(webView, navigation); } static void viewReadyToShowCallback(WebKitWebView* webView, UIClientTest* test) @@ -146,6 +147,9 @@ public: case WEBKIT_SCRIPT_DIALOG_PROMPT: g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kPromptDialogReturnedText); break; + case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: + g_assert_not_reached(); + break; } g_main_loop_quit(m_mainLoop); @@ -165,6 +169,13 @@ public: webkit_script_dialog_prompt_set_text(dialog, kPromptDialogReturnedText); } + void scriptBeforeUnloadConfirm(WebKitScriptDialog* dialog) + { + g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kBeforeUnloadConfirmDialogMessage); + m_scriptDialogConfirmed = true; + webkit_script_dialog_confirm_set_confirmed(dialog, m_scriptDialogConfirmed); + } + static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, UIClientTest* test) { switch (webkit_script_dialog_get_dialog_type(dialog)) { @@ -177,6 +188,9 @@ public: case WEBKIT_SCRIPT_DIALOG_PROMPT: test->scriptPrompt(dialog); break; + case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: + test->scriptBeforeUnloadConfirm(dialog); + break; } return TRUE; @@ -197,6 +211,12 @@ public: g_assert(WEBKIT_IS_PERMISSION_REQUEST(request)); test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + if (test->m_verifyMediaTypes && WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) { + WebKitUserMediaPermissionRequest* userMediaRequest = WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request); + g_assert(webkit_user_media_permission_is_for_audio_device(userMediaRequest) == test->m_expectedAudioMedia); + g_assert(webkit_user_media_permission_is_for_video_device(userMediaRequest) == test->m_expectedVideoMedia); + } + if (test->m_allowPermissionRequests) webkit_permission_request_allow(request); else @@ -205,10 +225,19 @@ public: return TRUE; } + static void permissionResultMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, UIClientTest* test) + { + test->m_permissionResult.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_main_loop_quit(test->m_mainLoop); + } + UIClientTest() : m_scriptDialogType(WEBKIT_SCRIPT_DIALOG_ALERT) , m_scriptDialogConfirmed(true) , m_allowPermissionRequests(false) + , m_verifyMediaTypes(false) + , m_expectedAudioMedia(false) + , m_expectedVideoMedia(false) , m_mouseTargetModifiers(0) { webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE); @@ -216,11 +245,33 @@ public: g_signal_connect(m_webView, "script-dialog", G_CALLBACK(scriptDialog), this); g_signal_connect(m_webView, "mouse-target-changed", G_CALLBACK(mouseTargetChanged), this); g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequested), this); + webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "permission"); + g_signal_connect(m_userContentManager.get(), "script-message-received::permission", G_CALLBACK(permissionResultMessageReceivedCallback), this); } ~UIClientTest() { g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "permission"); + } + + static void tryWebViewCloseCallback(UIClientTest* test) + { + g_main_loop_quit(test->m_mainLoop); + } + + void tryCloseAndWaitUntilClosed() + { + gulong handler = g_signal_connect_swapped(m_webView, "close", G_CALLBACK(tryWebViewCloseCallback), this); + // Use an idle because webkit_web_view_try_close can emit the close signal in the + // current run loop iteration. + g_idle_add([](gpointer data) -> gboolean { + webkit_web_view_try_close(WEBKIT_WEB_VIEW(data)); + return G_SOURCE_REMOVE; + }, m_webView); + g_main_loop_run(m_mainLoop); + g_signal_handler_disconnect(m_webView, handler); } void waitUntilMainLoopFinishes() @@ -228,6 +279,13 @@ public: g_main_loop_run(m_mainLoop); } + const char* waitUntilPermissionResultMessageReceived() + { + m_permissionResult = nullptr; + g_main_loop_run(m_mainLoop); + return m_permissionResult.get(); + } + void setExpectedWindowProperties(const WindowProperties& windowProperties) { m_windowProperties = windowProperties; @@ -240,9 +298,19 @@ public: return m_mouseTargetHitTestResult.get(); } - virtual GtkWidget* viewCreate(WebKitWebView* webView) + void simulateUserInteraction() + { + runJavaScriptAndWaitUntilFinished("document.getElementById('testInput').focus()", nullptr); + keyStroke(GDK_KEY_a); + keyStroke(GDK_KEY_b); + while (gtk_events_pending()) + gtk_main_iteration(); + } + + virtual GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation) { g_assert(webView == m_webView); + g_assert(navigation); GtkWidget* newWebView = webkit_web_view_new_with_context(webkit_web_view_get_context(webView)); g_object_ref_sink(newWebView); @@ -287,10 +355,14 @@ public: WebKitScriptDialogType m_scriptDialogType; bool m_scriptDialogConfirmed; bool m_allowPermissionRequests; + gboolean m_verifyMediaTypes; + gboolean m_expectedAudioMedia; + gboolean m_expectedVideoMedia; WindowProperties m_windowProperties; HashSet<WTF::String> m_windowPropertiesChanged; GRefPtr<WebKitHitTestResult> m_mouseTargetHitTestResult; unsigned m_mouseTargetModifiers; + GUniquePtr<char> m_permissionResult; }; static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer) @@ -305,6 +377,91 @@ static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer) g_assert_cmpint(events[2], ==, UIClientTest::Close); } +class CreateNavigationDataTest: public UIClientTest { +public: + MAKE_GLIB_TEST_FIXTURE(CreateNavigationDataTest); + + CreateNavigationDataTest() + : m_navigation(nullptr) + { + } + + ~CreateNavigationDataTest() + { + clearNavigation(); + } + + void clearNavigation() + { + if (m_navigation) + webkit_navigation_action_free(m_navigation); + m_navigation = nullptr; + } + + GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation) + { + g_assert(navigation); + g_assert(!m_navigation); + m_navigation = webkit_navigation_action_copy(navigation); + g_main_loop_quit(m_mainLoop); + return nullptr; + } + + void loadHTML(const char* html) + { + clearNavigation(); + WebViewTest::loadHtml(html, nullptr); + } + + void clickAndWaitUntilMainLoopFinishes(int x, int y) + { + clearNavigation(); + clickMouseButton(x, y, 1); + g_main_loop_run(m_mainLoop); + } + + WebKitNavigationAction* m_navigation; +}; + +static void testWebViewCreateNavigationData(CreateNavigationDataTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + + test->loadHTML( + "<html><body>" + "<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');\"/>" + "<a style=\"position:absolute; left:20; top:20;\" href=\"data:bar\" target=\"_blank\">popup link</a>" + "</body></html>"); + test->waitUntilLoadFinished(); + + // Click on a button. + test->clickAndWaitUntilMainLoopFinishes(5, 5); + g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:foo"); + g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER); + // FIXME: This should be button 1. + g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0); + g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0); + g_assert(webkit_navigation_action_is_user_gesture(test->m_navigation)); + + // Click on a link. + test->clickAndWaitUntilMainLoopFinishes(21, 21); + g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:bar"); + g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_LINK_CLICKED); + g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 1); + g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0); + g_assert(webkit_navigation_action_is_user_gesture(test->m_navigation)); + + // No user interaction. + test->loadHTML("<html><body onLoad=\"window.open();\"></html>"); + test->waitUntilMainLoopFinishes(); + + g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, ""); + g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER); + g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0); + g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0); + g_assert(!webkit_navigation_action_is_user_gesture(test->m_navigation)); +} + static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType) { GtkFileFilterInfo filterInfo; @@ -323,11 +480,11 @@ public: test->m_webViewEvents.append(RunAsModal); } - GtkWidget* viewCreate(WebKitWebView* webView) + GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation) { g_assert(webView == m_webView); - GtkWidget* newWebView = UIClientTest::viewCreate(webView); + GtkWidget* newWebView = UIClientTest::viewCreate(webView, navigation); g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(dialogRunAsModalCallback), this); return newWebView; } @@ -371,28 +528,80 @@ static void testWebViewDisallowModalDialogs(ModalDialogsTest* test, gconstpointe static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer) { + test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); + static const char* htmlOnLoadFormat = "<html><body onLoad=\"%s\"></body></html>"; static const char* jsAlertFormat = "alert('%s')"; static const char* jsConfirmFormat = "do { confirmed = confirm('%s'); } while (!confirmed); alert('confirmed');"; static const char* jsPromptFormat = "alert(prompt('%s', 'default'));"; + static const char* htmlOnBeforeUnloadFormat = + "<html><body onbeforeunload=\"return beforeUnloadHandler();\"><input id=\"testInput\" type=\"text\"></input><script>function beforeUnloadHandler() { return \"%s\"; }</script></body></html>"; test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT; GUniquePtr<char> alertDialogMessage(g_strdup_printf(jsAlertFormat, kAlertDialogMessage)); GUniquePtr<char> alertHTML(g_strdup_printf(htmlOnLoadFormat, alertDialogMessage.get())); test->loadHtml(alertHTML.get(), 0); test->waitUntilMainLoopFinishes(); + webkit_web_view_stop_loading(test->m_webView); + test->waitUntilLoadFinished(); test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM; GUniquePtr<char> confirmDialogMessage(g_strdup_printf(jsConfirmFormat, kConfirmDialogMessage)); GUniquePtr<char> confirmHTML(g_strdup_printf(htmlOnLoadFormat, confirmDialogMessage.get())); test->loadHtml(confirmHTML.get(), 0); test->waitUntilMainLoopFinishes(); + webkit_web_view_stop_loading(test->m_webView); + test->waitUntilLoadFinished(); test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT; GUniquePtr<char> promptDialogMessage(g_strdup_printf(jsPromptFormat, kPromptDialogMessage)); GUniquePtr<char> promptHTML(g_strdup_printf(htmlOnLoadFormat, promptDialogMessage.get())); test->loadHtml(promptHTML.get(), 0); test->waitUntilMainLoopFinishes(); + webkit_web_view_stop_loading(test->m_webView); + test->waitUntilLoadFinished(); + + test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM; + GUniquePtr<char> beforeUnloadDialogHTML(g_strdup_printf(htmlOnBeforeUnloadFormat, kBeforeUnloadConfirmDialogMessage)); + test->loadHtml(beforeUnloadDialogHTML.get(), nullptr); + test->waitUntilLoadFinished(); + + // Reload should trigger onbeforeunload. +#if 0 + test->simulateUserInteraction(); + // FIXME: reloading HTML data doesn't emit finished load event. + // See https://bugs.webkit.org/show_bug.cgi?id=139089. + test->m_scriptDialogConfirmed = false; + webkit_web_view_reload(test->m_webView); + test->waitUntilLoadFinished(); + g_assert(test->m_scriptDialogConfirmed); +#endif + + // Navigation should trigger onbeforeunload. + test->simulateUserInteraction(); + test->m_scriptDialogConfirmed = false; + test->loadHtml("<html></html>", nullptr); + test->waitUntilLoadFinished(); + g_assert(test->m_scriptDialogConfirmed); + + // Try close should trigger onbeforeunload. + test->m_scriptDialogConfirmed = false; + test->loadHtml(beforeUnloadDialogHTML.get(), nullptr); + test->waitUntilLoadFinished(); + test->simulateUserInteraction(); + test->tryCloseAndWaitUntilClosed(); + g_assert(test->m_scriptDialogConfirmed); + + // Try close on a page with no unload handlers should not trigger onbeforeunload, + // but should actually close the page. + test->m_scriptDialogConfirmed = false; + test->loadHtml("<html><body></body></html>", nullptr); + test->waitUntilLoadFinished(); + // We got a onbeforeunload of the previous page. + g_assert(test->m_scriptDialogConfirmed); + test->m_scriptDialogConfirmed = false; + test->tryCloseAndWaitUntilClosed(); + g_assert(!test->m_scriptDialogConfirmed); } static void testWebViewWindowProperties(UIClientTest* test, gconstpointer) @@ -423,13 +632,22 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); const char* linksHoveredHTML = - "<html><body>" + "<html><head>" + " <script>" + " window.onload = function () {" + " window.getSelection().removeAllRanges();" + " var select_range = document.createRange();" + " select_range.selectNodeContents(document.getElementById('text_to_select'));" + " window.getSelection().addRange(select_range);" + " }" + " </script>" + "</head><body>" " <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>" " <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>" " <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='0xdeadbeef' width=5 height=5></img></a>" " <input style='position:absolute; left:1; top:30' size='10'></input>" - " <div style='position:absolute; left:1; top:50; width:30; height:30; overflow:scroll'> </div>" " <video style='position:absolute; left:1; top:100' width='300' height='300' controls='controls' preload='none'><source src='movie.ogg' type='video/ogg' /></video>" + " <p style='position:absolute; left:1; top:120' id='text_to_select'>Lorem ipsum.</p>" "</body></html>"; test->loadHtml(linksHoveredHTML, "file:///"); @@ -441,6 +659,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) g_assert(!webkit_hit_test_result_context_is_image(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/"); g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Title"); g_assert_cmpstr(webkit_hit_test_result_get_link_label(hitTestResult), ==, "WebKitGTK+ Website"); @@ -452,6 +671,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) g_assert(!webkit_hit_test_result_context_is_image(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert(!test->m_mouseTargetModifiers); // Move over image with GDK_CONTROL_MASK. @@ -460,6 +680,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) g_assert(webkit_hit_test_result_context_is_image(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult)); g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef"); g_assert(test->m_mouseTargetModifiers & GDK_CONTROL_MASK); @@ -471,6 +692,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/logo"); g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef"); g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Logo"); @@ -484,6 +706,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) g_assert(webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert_cmpstr(webkit_hit_test_result_get_media_uri(hitTestResult), ==, "file:///movie.ogg"); g_assert(!test->m_mouseTargetModifiers); @@ -494,19 +717,32 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer) g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult)); g_assert(webkit_hit_test_result_context_is_editable(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert(!test->m_mouseTargetModifiers); // Move over scrollbar. - hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(5, 75); + hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(gtk_widget_get_allocated_width(GTK_WIDGET(test->m_webView)) - 4, 5); g_assert(!webkit_hit_test_result_context_is_link(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_image(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); g_assert(webkit_hit_test_result_context_is_scrollbar(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult)); + g_assert(!test->m_mouseTargetModifiers); + + // Move over selection. + hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(2, 145); + g_assert(!webkit_hit_test_result_context_is_link(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_image(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_media(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult)); + g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult)); + g_assert(webkit_hit_test_result_context_is_selection(hitTestResult)); g_assert(!test->m_mouseTargetModifiers); + } -static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer) +static void testWebViewGeolocationPermissionRequests(UIClientTest* test, gconstpointer) { // Some versions of geoclue give a runtime warning because it tries // to register the error quark twice. See https://bugs.webkit.org/show_bug.cgi?id=89858. @@ -518,35 +754,108 @@ static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer) " <script>" " function runTest()" " {" - " navigator.geolocation.getCurrentPosition(function(p) { document.title = \"OK\" }," - " function(e) { document.title = e.code });" + " navigator.geolocation.getCurrentPosition(function(p) { window.webkit.messageHandlers.permission.postMessage('OK'); }," + " function(e) { window.webkit.messageHandlers.permission.postMessage(e.code.toString()); });" " }" " </script>" " <body onload='runTest();'></body>" "</html>"; - // Test denying a permission request. + // Geolocation is not allowed from insecure connections like HTTP, + // POSITION_UNAVAILABLE ('2') is returned in that case without even + // asking the API layer. test->m_allowPermissionRequests = false; - test->loadHtml(geolocationRequestHTML, 0); - test->waitUntilTitleChanged(); + test->loadHtml(geolocationRequestHTML, "http://foo.com/bar"); + const gchar* result = test->waitUntilPermissionResultMessageReceived(); + g_assert_cmpstr(result, ==, "2"); - // According to the Geolocation API specification, '1' is the - // error code returned for the PERMISSION_DENIED error. - // http://dev.w3.org/geo/api/spec-source.html#position_error_interface - const gchar* result = webkit_web_view_get_title(test->m_webView); + // Test denying a permission request. PERMISSION_DENIED ('1') is + // returned in this case. + test->m_allowPermissionRequests = false; + test->loadHtml(geolocationRequestHTML, "https://foo.com/bar"); + result = test->waitUntilPermissionResultMessageReceived(); g_assert_cmpstr(result, ==, "1"); - // Test allowing a permission request. + // Test allowing a permission request. Result should be different + // to PERMISSION_DENIED ('1'). test->m_allowPermissionRequests = true; - test->loadHtml(geolocationRequestHTML, 0); - test->waitUntilTitleChanged(); - - // Check that we did not get the PERMISSION_DENIED error now. - result = webkit_web_view_get_title(test->m_webView); + test->loadHtml(geolocationRequestHTML, "https://foo.com/bar"); + result = test->waitUntilPermissionResultMessageReceived(); g_assert_cmpstr(result, !=, "1"); test->addLogFatalFlag(G_LOG_LEVEL_WARNING); } +#if ENABLE(MEDIA_STREAM) +static void testWebViewUserMediaPermissionRequests(UIClientTest* test, gconstpointer) +{ + WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView); + gboolean enabled = webkit_settings_get_enable_media_stream(settings); + webkit_settings_set_enable_media_stream(settings, TRUE); + + test->showInWindowAndWaitUntilMapped(); + static const char* userMediaRequestHTML = + "<html>" + " <script>" + " function runTest()" + " {" + " navigator.webkitGetUserMedia({audio: true, video: true}," + " function(s) { document.title = \"OK\" }," + " function(e) { document.title = e.name });" + " }" + " </script>" + " <body onload='runTest();'></body>" + "</html>"; + + test->m_verifyMediaTypes = TRUE; + test->m_expectedAudioMedia = TRUE; + test->m_expectedVideoMedia = TRUE; + + // Test denying a permission request. + test->m_allowPermissionRequests = false; + test->loadHtml(userMediaRequestHTML, nullptr); + test->waitUntilTitleChangedTo("PermissionDeniedError"); + + // Test allowing a permission request. + test->m_allowPermissionRequests = true; + test->loadHtml(userMediaRequestHTML, nullptr); + test->waitUntilTitleChangedTo("OK"); + + webkit_settings_set_enable_media_stream(settings, enabled); +} + +static void testWebViewAudioOnlyUserMediaPermissionRequests(UIClientTest* test, gconstpointer) +{ + WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView); + gboolean enabled = webkit_settings_get_enable_media_stream(settings); + webkit_settings_set_enable_media_stream(settings, TRUE); + + test->showInWindowAndWaitUntilMapped(); + static const char* userMediaRequestHTML = + "<html>" + " <script>" + " function runTest()" + " {" + " navigator.webkitGetUserMedia({audio: true, video: false}," + " function(s) { document.title = \"OK\" }," + " function(e) { document.title = e.name });" + " }" + " </script>" + " <body onload='runTest();'></body>" + "</html>"; + + test->m_verifyMediaTypes = TRUE; + test->m_expectedAudioMedia = TRUE; + test->m_expectedVideoMedia = FALSE; + + // Test denying a permission request. + test->m_allowPermissionRequests = false; + test->loadHtml(userMediaRequestHTML, nullptr); + test->waitUntilTitleChangedTo("PermissionDeniedError"); + + webkit_settings_set_enable_media_stream(settings, enabled); +} +#endif // ENABLE(MEDIA_STREAM) + class FileChooserTest: public UIClientTest { public: MAKE_GLIB_TEST_FIXTURE(FileChooserTest); @@ -662,16 +971,124 @@ static void testWebViewFileChooserRequest(FileChooserTest* test, gconstpointer) webkit_file_chooser_request_cancel(fileChooserRequest); } +class ColorChooserTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(ColorChooserTest); + + static gboolean runColorChooserCallback(WebKitWebView*, WebKitColorChooserRequest* request, ColorChooserTest* test) + { + test->runColorChooser(request); + return TRUE; + } + + static void requestFinishedCallback(WebKitColorChooserRequest* request, ColorChooserTest* test) + { + g_assert(test->m_request.get() == request); + test->m_request = nullptr; + if (g_main_loop_is_running(test->m_mainLoop)) + g_main_loop_quit(test->m_mainLoop); + } + + ColorChooserTest() + { + g_signal_connect(m_webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), this); + } + + void runColorChooser(WebKitColorChooserRequest* request) + { + g_assert(WEBKIT_IS_COLOR_CHOOSER_REQUEST(request)); + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + m_request = request; + g_signal_connect(request, "finished", G_CALLBACK(requestFinishedCallback), this); + g_main_loop_quit(m_mainLoop); + } + + void finishRequest() + { + g_assert(m_request.get()); + webkit_color_chooser_request_finish(m_request.get()); + g_assert(!m_request); + } + + void cancelRequest() + { + g_assert(m_request.get()); + webkit_color_chooser_request_cancel(m_request.get()); + g_assert(!m_request); + } + + WebKitColorChooserRequest* clickMouseButtonAndWaitForColorChooserRequest(int x, int y) + { + clickMouseButton(x, y); + g_main_loop_run(m_mainLoop); + g_assert(m_request.get()); + return m_request.get(); + } + +private: + GRefPtr<WebKitColorChooserRequest> m_request; +}; + +static void testWebViewColorChooserRequest(ColorChooserTest* test, gconstpointer) +{ + 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>"; + test->showInWindowAndWaitUntilMapped(); + + GUniquePtr<char> defaultColorHTML(g_strdup_printf(colorChooserHTMLFormat, "")); + test->loadHtml(defaultColorHTML.get(), nullptr); + test->waitUntilLoadFinished(); + WebKitColorChooserRequest* request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5); + + // Default color is black (#000000). + GdkRGBA rgba1; + GdkRGBA rgba2 = { 0., 0., 0., 1. }; + webkit_color_chooser_request_get_rgba(request, &rgba1); + g_assert(gdk_rgba_equal(&rgba1, &rgba2)); + + // Set a different color. + rgba2.green = 1; + webkit_color_chooser_request_set_rgba(request, &rgba2); + webkit_color_chooser_request_get_rgba(request, &rgba1); + g_assert(gdk_rgba_equal(&rgba1, &rgba2)); + + GdkRectangle rect; + webkit_color_chooser_request_get_element_rectangle(request, &rect); + g_assert_cmpint(rect.x, == , 1); + g_assert_cmpint(rect.y, == , 1); + g_assert_cmpint(rect.width, == , 45); + g_assert_cmpint(rect.height, == , 25); + + test->finishRequest(); + + // Use an initial color. + GUniquePtr<char> initialColorHTML(g_strdup_printf(colorChooserHTMLFormat, "value='#FF00FF'")); + test->loadHtml(initialColorHTML.get(), nullptr); + test->waitUntilLoadFinished(); + request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5); + + webkit_color_chooser_request_get_rgba(request, &rgba1); + GdkRGBA rgba3 = { 1., 0., 1., 1. }; + g_assert(gdk_rgba_equal(&rgba1, &rgba3)); + + test->cancelRequest(); +} + void beforeAll() { UIClientTest::add("WebKitWebView", "create-ready-close", testWebViewCreateReadyClose); + CreateNavigationDataTest::add("WebKitWebView", "create-navigation-data", testWebViewCreateNavigationData); ModalDialogsTest::add("WebKitWebView", "allow-modal-dialogs", testWebViewAllowModalDialogs); ModalDialogsTest::add("WebKitWebView", "disallow-modal-dialogs", testWebViewDisallowModalDialogs); UIClientTest::add("WebKitWebView", "javascript-dialogs", testWebViewJavaScriptDialogs); UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties); UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget); - UIClientTest::add("WebKitWebView", "permission-requests", testWebViewPermissionRequests); + UIClientTest::add("WebKitWebView", "geolocation-permission-requests", testWebViewGeolocationPermissionRequests); +#if ENABLE(MEDIA_STREAM) + UIClientTest::add("WebKitWebView", "usermedia-permission-requests", testWebViewUserMediaPermissionRequests); + UIClientTest::add("WebKitWebView", "audio-usermedia-permission-request", testWebViewAudioOnlyUserMediaPermissionRequests); +#endif FileChooserTest::add("WebKitWebView", "file-chooser-request", testWebViewFileChooserRequest); + ColorChooserTest::add("WebKitWebView", "color-chooser-request", testWebViewColorChooserRequest); } void afterAll() |