diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp | 561 |
1 files changed, 528 insertions, 33 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp index 334f8dafe..4e3d1d7e7 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Igalia S.L. + * Copyright (C) 2014 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,38 +19,153 @@ */ #include "config.h" +#include "WebKitTestServer.h" #include "WebViewTest.h" #include <JavaScriptCore/JSStringRef.h> #include <JavaScriptCore/JSValueRef.h> #include <glib/gstdio.h> -#include <wtf/gobject/GRefPtr.h> +#include <wtf/glib/GRefPtr.h> -static void testWebViewDefaultContext(WebViewTest* test, gconstpointer) +class IsPlayingAudioWebViewTest : public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(IsPlayingAudioWebViewTest); + + static void isPlayingAudioChanged(GObject*, GParamSpec*, IsPlayingAudioWebViewTest* test) + { + g_signal_handlers_disconnect_by_func(test->m_webView, reinterpret_cast<void*>(isPlayingAudioChanged), test); + g_main_loop_quit(test->m_mainLoop); + } + + void waitUntilIsPlayingAudioChanged() + { + g_signal_connect(m_webView, "notify::is-playing-audio", G_CALLBACK(isPlayingAudioChanged), this); + g_main_loop_run(m_mainLoop); + } +}; + +static WebKitTestServer* gServer; + +static void testWebViewWebContext(WebViewTest* test, gconstpointer) { - g_assert(webkit_web_view_get_context(test->m_webView) == webkit_web_context_get_default()); + g_assert(webkit_web_view_get_context(test->m_webView) == test->m_webContext.get()); + g_assert(webkit_web_context_get_default() != test->m_webContext.get()); // Check that a web view created with g_object_new has the default context. - GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL)); + GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, nullptr)); g_assert(webkit_web_view_get_context(webView.get()) == webkit_web_context_get_default()); + + // Check that a web view created with a related view has the related view context. + webView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(test->m_webView)); + g_assert(webkit_web_view_get_context(webView.get()) == test->m_webContext.get()); + + // Check that a web context given as construct parameter is ignored if a related view is also provided. + webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, + "web-context", webkit_web_context_get_default(), "related-view", test->m_webView, nullptr)); + g_assert(webkit_web_view_get_context(webView.get()) == test->m_webContext.get()); +} + +static void testWebViewWebContextLifetime(WebViewTest* test, gconstpointer) +{ + WebKitWebContext* webContext = webkit_web_context_new(); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webContext)); + + GtkWidget* webView = webkit_web_view_new_with_context(webContext); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView)); + + g_object_ref_sink(webView); + g_object_unref(webContext); + + // Check that the web view still has a valid context. + WebKitWebContext* tmpContext = webkit_web_view_get_context(WEBKIT_WEB_VIEW(webView)); + g_assert_true(WEBKIT_IS_WEB_CONTEXT(tmpContext)); + g_object_unref(webView); + + WebKitWebContext* webContext2 = webkit_web_context_new(); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webContext2)); + + GtkWidget* webView2 = webkit_web_view_new_with_context(webContext2); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView2)); + + g_object_ref_sink(webView2); + g_object_unref(webView2); + + // Check that the context is still valid. + g_assert_true(WEBKIT_IS_WEB_CONTEXT(webContext2)); + g_object_unref(webContext2); +} + +static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test) +{ + if (loadEvent != WEBKIT_LOAD_FINISHED) + return; + g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test); + test->quitMainLoop(); +} + +static void testWebViewEphemeral(WebViewTest* test, gconstpointer) +{ + g_assert(!webkit_web_view_is_ephemeral(test->m_webView)); + g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(test->m_webView))); + auto* manager = webkit_web_context_get_website_data_manager(test->m_webContext.get()); + g_assert(!webkit_website_data_manager_is_ephemeral(manager)); + g_assert(webkit_web_view_get_website_data_manager(test->m_webView) == manager); + webkit_website_data_manager_clear(manager, WEBKIT_WEBSITE_DATA_DISK_CACHE, 0, nullptr, [](GObject* manager, GAsyncResult* result, gpointer userData) { + webkit_website_data_manager_clear_finish(WEBKIT_WEBSITE_DATA_MANAGER(manager), result, nullptr); + static_cast<WebViewTest*>(userData)->quitMainLoop(); + }, test); + g_main_loop_run(test->m_mainLoop); + + // A WebView on a non ephemeral context can be ephemeral. + GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, + "web-context", webkit_web_view_get_context(test->m_webView), + "is-ephemeral", TRUE, + nullptr)); + g_assert(webkit_web_view_is_ephemeral(webView.get())); + g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get()))); + g_assert(webkit_web_view_get_website_data_manager(webView.get()) != manager); + + g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test); + webkit_web_view_load_uri(webView.get(), gServer->getURIForPath("/").data()); + g_main_loop_run(test->m_mainLoop); + + // Disk cache delays the storing of initial resources for 1 second to avoid + // affecting early page load. So, wait 1 second here to make sure resources + // have already been stored. + test->wait(1); + + webkit_website_data_manager_fetch(manager, WEBKIT_WEBSITE_DATA_DISK_CACHE, nullptr, [](GObject* manager, GAsyncResult* result, gpointer userData) { + auto* test = static_cast<WebViewTest*>(userData); + g_assert(!webkit_website_data_manager_fetch_finish(WEBKIT_WEBSITE_DATA_MANAGER(manager), result, nullptr)); + test->quitMainLoop(); + }, test); + g_main_loop_run(test->m_mainLoop); } static void testWebViewCustomCharset(WebViewTest* test, gconstpointer) { + test->loadURI(gServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); g_assert(!webkit_web_view_get_custom_charset(test->m_webView)); webkit_web_view_set_custom_charset(test->m_webView, "utf8"); + // Changing the charset reloads the page, so wait until reloaded. + test->waitUntilLoadFinished(); g_assert_cmpstr(webkit_web_view_get_custom_charset(test->m_webView), ==, "utf8"); - // Go back to the default charset. - webkit_web_view_set_custom_charset(test->m_webView, 0); + + // Go back to the default charset and wait until reloaded. + webkit_web_view_set_custom_charset(test->m_webView, nullptr); + test->waitUntilLoadFinished(); g_assert(!webkit_web_view_get_custom_charset(test->m_webView)); } static void testWebViewSettings(WebViewTest* test, gconstpointer) { WebKitSettings* defaultSettings = webkit_web_view_get_settings(test->m_webView); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(defaultSettings)); g_assert(defaultSettings); g_assert(webkit_settings_get_enable_javascript(defaultSettings)); GRefPtr<WebKitSettings> newSettings = adoptGRef(webkit_settings_new()); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings.get())); g_object_set(G_OBJECT(newSettings.get()), "enable-javascript", FALSE, NULL); webkit_web_view_set_settings(test->m_webView, newSettings.get()); @@ -63,10 +179,15 @@ static void testWebViewSettings(WebViewTest* test, gconstpointer) g_assert(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView2.get())) == settings); GRefPtr<WebKitSettings> newSettings2 = adoptGRef(webkit_settings_new()); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings2.get())); webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView2.get()), newSettings2.get()); settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView2.get())); g_assert(settings == newSettings2.get()); g_assert(webkit_settings_get_enable_javascript(settings)); + + GRefPtr<GtkWidget> webView3 = webkit_web_view_new_with_settings(newSettings2.get()); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView3.get())); + g_assert(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView3.get())) == newSettings2.get()); } static void testWebViewZoomLevel(WebViewTest* test, gconstpointer) @@ -407,7 +528,7 @@ static void testWebViewSave(SaveWebViewTest* test, gconstpointer) gchar buffer[512] = { 0 }; gssize readBytes = 0; gssize totalBytesFromStream = 0; - while (readBytes = g_input_stream_read(test->m_inputStream.get(), &buffer, 512, 0, &error.outPtr())) { + while ((readBytes = g_input_stream_read(test->m_inputStream.get(), &buffer, 512, 0, &error.outPtr()))) { g_assert(!error); totalBytesFromStream += readBytes; } @@ -417,28 +538,7 @@ static void testWebViewSave(SaveWebViewTest* test, gconstpointer) g_assert_cmpint(g_file_info_get_size(fileInfo.get()), ==, totalBytesFromStream); } -static void testWebViewMode(WebViewTest* test, gconstpointer) -{ - static const char* indexHTML = "<html><body><p>Test Web View Mode</p></body></html>"; - - // Web mode. - g_assert_cmpuint(webkit_web_view_get_view_mode(test->m_webView), ==, WEBKIT_VIEW_MODE_WEB); - test->loadHtml(indexHTML, 0); - test->waitUntilLoadFinished(); - WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.body.textContent;", 0); - GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); - g_assert_cmpstr(valueString.get(), ==, "Test Web View Mode"); - - // Source mode. - webkit_web_view_set_view_mode(test->m_webView, WEBKIT_VIEW_MODE_SOURCE); - test->loadHtml(indexHTML, 0); - test->waitUntilLoadFinished(); - javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.body.textContent;", 0); - valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); - g_assert_cmpstr(valueString.get(), ==, indexHTML); -} - -// To test page visibility API. Currently only 'visible' and 'hidden' states are implemented fully in WebCore. +// To test page visibility API. Currently only 'visible', 'hidden' and 'prerender' states are implemented fully in WebCore. // See also http://www.w3.org/TR/2011/WD-page-visibility-20110602/ and https://developers.google.com/chrome/whitepapers/pagevisibility static void testWebViewPageVisibility(WebViewTest* test, gconstpointer) { @@ -453,7 +553,7 @@ static void testWebViewPageVisibility(WebViewTest* test, gconstpointer) "</body></html>", 0); - // Wait untill the page is loaded. Initial visibility should be 'hidden'. + // Wait until the page is loaded. Initial visibility should be 'prerender'. test->waitUntilLoadFinished(); GUniqueOutPtr<GError> error; @@ -461,7 +561,7 @@ static void testWebViewPageVisibility(WebViewTest* test, gconstpointer) g_assert(javascriptResult); g_assert(!error.get()); GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); - g_assert_cmpstr(valueString.get(), ==, "hidden"); + g_assert_cmpstr(valueString.get(), ==, "prerender"); javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.hidden;", &error.outPtr()); g_assert(javascriptResult); @@ -564,15 +664,404 @@ static void testWebViewSnapshot(SnapshotWebViewTest* test, gconstpointer) g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, cairo_image_surface_get_width(surface2)); g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, cairo_image_surface_get_height(surface2)); g_assert(!Test::cairoSurfacesEqual(surface1, surface2)); + + // Get a snpashot with a transparent background, the result must be different. + surface2 = test->getSnapshotAndWaitUntilReady(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND); + g_assert_cmpuint(cairo_surface_get_type(surface2), ==, CAIRO_SURFACE_TYPE_IMAGE); + g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, cairo_image_surface_get_width(surface2)); + g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, cairo_image_surface_get_height(surface2)); + g_assert(!Test::cairoSurfacesEqual(surface1, surface2)); cairo_surface_destroy(surface1); // Test that cancellation works. g_assert(test->getSnapshotAndCancel()); } +class NotificationWebViewTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(NotificationWebViewTest, setup, teardown); + + static void setup() + { + WebViewTest::shouldInitializeWebViewInConstructor = false; + } + + static void teardown() + { + WebViewTest::shouldInitializeWebViewInConstructor = true; + } + + enum NotificationEvent { + None, + Permission, + Shown, + Clicked, + OnClicked, + Closed, + OnClosed, + }; + + static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest *request, NotificationWebViewTest* test) + { + g_assert(WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST(request)); + g_assert(test->m_isExpectingPermissionRequest); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request)); + + test->m_event = Permission; + + webkit_permission_request_allow(request); + + g_main_loop_quit(test->m_mainLoop); + + return TRUE; + } + + static gboolean notificationClosedCallback(WebKitNotification* notification, NotificationWebViewTest* test) + { + g_assert(test->m_notification == notification); + test->m_notification = nullptr; + test->m_event = Closed; + if (g_main_loop_is_running(test->m_mainLoop)) + g_main_loop_quit(test->m_mainLoop); + return TRUE; + } + + static gboolean notificationClickedCallback(WebKitNotification* notification, NotificationWebViewTest* test) + { + g_assert(test->m_notification == notification); + test->m_event = Clicked; + return TRUE; + } + + static gboolean showNotificationCallback(WebKitWebView*, WebKitNotification* notification, NotificationWebViewTest* test) + { + g_assert(!test->m_notification); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(notification)); + test->m_notification = notification; + g_signal_connect(notification, "closed", G_CALLBACK(notificationClosedCallback), test); + g_signal_connect(notification, "clicked", G_CALLBACK(notificationClickedCallback), test); + test->m_event = Shown; + g_main_loop_quit(test->m_mainLoop); + return TRUE; + } + + static void notificationsMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, NotificationWebViewTest* test) + { + GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); + + if (g_str_equal(valueString.get(), "clicked")) + test->m_event = OnClicked; + else if (g_str_equal(valueString.get(), "closed")) + test->m_event = OnClosed; + + g_main_loop_quit(test->m_mainLoop); + } + + void initialize() + { + initializeWebView(); + g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), this); + g_signal_connect(m_webView, "show-notification", G_CALLBACK(showNotificationCallback), this); + webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "notifications"); + g_signal_connect(m_userContentManager.get(), "script-message-received::notifications", G_CALLBACK(notificationsMessageReceivedCallback), this); + } + + ~NotificationWebViewTest() + { + 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(), "notifications"); + } + + bool hasPermission() + { + auto* result = runJavaScriptAndWaitUntilFinished("Notification.permission;", nullptr); + g_assert(result); + GUniquePtr<char> value(javascriptResultToCString(result)); + return !g_strcmp0(value.get(), "granted"); + } + + void requestPermissionAndWaitUntilGiven() + { + m_event = None; + m_isExpectingPermissionRequest = true; + webkit_web_view_run_javascript(m_webView, "Notification.requestPermission();", nullptr, nullptr, nullptr); + g_main_loop_run(m_mainLoop); + } + + void requestNotificationAndWaitUntilShown(const char* title, const char* body) + { + m_event = None; + + GUniquePtr<char> jscode(g_strdup_printf("n = new Notification('%s', { body: '%s'});", title, body)); + webkit_web_view_run_javascript(m_webView, jscode.get(), nullptr, nullptr, nullptr); + + g_main_loop_run(m_mainLoop); + } + + void requestNotificationAndWaitUntilShown(const char* title, const char* body, const char* tag) + { + m_event = None; + + GUniquePtr<char> jscode(g_strdup_printf("n = new Notification('%s', { body: '%s', tag: '%s'});", title, body, tag)); + webkit_web_view_run_javascript(m_webView, jscode.get(), nullptr, nullptr, nullptr); + + g_main_loop_run(m_mainLoop); + } + + void clickNotificationAndWaitUntilClicked() + { + m_event = None; + runJavaScriptAndWaitUntilFinished("n.onclick = function() { window.webkit.messageHandlers.notifications.postMessage('clicked'); }", nullptr); + webkit_notification_clicked(m_notification); + g_assert(m_event == Clicked); + g_main_loop_run(m_mainLoop); + } + + void closeNotificationAndWaitUntilClosed() + { + m_event = None; + webkit_web_view_run_javascript(m_webView, "n.close()", nullptr, nullptr, nullptr); + g_main_loop_run(m_mainLoop); + } + + void closeNotificationAndWaitUntilOnClosed() + { + g_assert(m_notification); + m_event = None; + runJavaScriptAndWaitUntilFinished("n.onclose = function() { window.webkit.messageHandlers.notifications.postMessage('closed'); }", nullptr); + webkit_notification_close(m_notification); + g_assert(m_event == Closed); + g_main_loop_run(m_mainLoop); + } + + NotificationEvent m_event { None }; + WebKitNotification* m_notification { nullptr }; + bool m_isExpectingPermissionRequest { false }; + bool m_hasPermission { false }; +}; + +static void testWebViewNotification(NotificationWebViewTest* test, gconstpointer) +{ + test->initialize(); + + // Notifications don't work with local or special schemes. + test->loadURI(gServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); + g_assert(!test->hasPermission()); + + test->requestPermissionAndWaitUntilGiven(); + g_assert(test->m_event == NotificationWebViewTest::Permission); + g_assert(test->hasPermission()); + + static const char* title = "This is a notification"; + static const char* body = "This is the body."; + static const char* tag = "This is the tag."; + test->requestNotificationAndWaitUntilShown(title, body, tag); + + g_assert(test->m_event == NotificationWebViewTest::Shown); + g_assert(test->m_notification); + g_assert_cmpstr(webkit_notification_get_title(test->m_notification), ==, title); + g_assert_cmpstr(webkit_notification_get_body(test->m_notification), ==, body); + g_assert_cmpstr(webkit_notification_get_tag(test->m_notification), ==, tag); + + test->clickNotificationAndWaitUntilClicked(); + g_assert(test->m_event == NotificationWebViewTest::OnClicked); + + test->closeNotificationAndWaitUntilClosed(); + g_assert(test->m_event == NotificationWebViewTest::Closed); + + test->requestNotificationAndWaitUntilShown(title, body); + g_assert(test->m_event == NotificationWebViewTest::Shown); + g_assert_cmpstr(webkit_notification_get_tag(test->m_notification), ==, nullptr); + + test->closeNotificationAndWaitUntilOnClosed(); + g_assert(test->m_event == NotificationWebViewTest::OnClosed); + + // The first notification should be closed automatically because the tag is + // the same. It will crash in showNotificationCallback on failure. + test->requestNotificationAndWaitUntilShown(title, body, tag); + test->requestNotificationAndWaitUntilShown(title, body, tag); + g_assert(test->m_event == NotificationWebViewTest::Shown); + + // Notification should be closed when navigating to a different webpage. + test->loadURI(gServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); + g_assert(test->m_event == NotificationWebViewTest::Closed); +} + +static void setInitialNotificationPermissionsAllowedCallback(WebKitWebContext* context, NotificationWebViewTest* test) +{ + GUniquePtr<char> baseURI(soup_uri_to_string(gServer->baseURI(), FALSE)); + GList* allowedOrigins = g_list_prepend(nullptr, webkit_security_origin_new_for_uri(baseURI.get())); + webkit_web_context_initialize_notification_permissions(test->m_webContext.get(), allowedOrigins, nullptr); + g_list_free_full(allowedOrigins, reinterpret_cast<GDestroyNotify>(webkit_security_origin_unref)); +} + +static void setInitialNotificationPermissionsDisallowedCallback(WebKitWebContext* context, NotificationWebViewTest* test) +{ + GUniquePtr<char> baseURI(soup_uri_to_string(gServer->baseURI(), FALSE)); + GList* disallowedOrigins = g_list_prepend(nullptr, webkit_security_origin_new_for_uri(baseURI.get())); + webkit_web_context_initialize_notification_permissions(test->m_webContext.get(), nullptr, disallowedOrigins); + g_list_free_full(disallowedOrigins, reinterpret_cast<GDestroyNotify>(webkit_security_origin_unref)); +} + +static void testWebViewNotificationInitialPermissionAllowed(NotificationWebViewTest* test, gconstpointer) +{ + g_signal_connect(test->m_webContext.get(), "initialize-notification-permissions", G_CALLBACK(setInitialNotificationPermissionsAllowedCallback), test); + test->initialize(); + + test->loadURI(gServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); + g_assert(test->hasPermission()); + + test->requestNotificationAndWaitUntilShown("This is a notification", "This is the body."); + g_assert(test->m_event == NotificationWebViewTest::Shown); +} + +static void testWebViewNotificationInitialPermissionDisallowed(NotificationWebViewTest* test, gconstpointer) +{ + g_signal_connect(test->m_webContext.get(), "initialize-notification-permissions", G_CALLBACK(setInitialNotificationPermissionsDisallowedCallback), test); + test->initialize(); + + test->loadURI(gServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); + g_assert(!test->hasPermission()); +} + +static void testWebViewIsPlayingAudio(IsPlayingAudioWebViewTest* test, gconstpointer) +{ + // The web view must be realized for the video to start playback and + // trigger changes in WebKitWebView::is-playing-audio. + test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); + + // Initially, web views should always report no audio being played. + g_assert(!webkit_web_view_is_playing_audio(test->m_webView)); + + GUniquePtr<char> resourcePath(g_build_filename(Test::getResourcesDir(Test::WebKit2Resources).data(), "file-with-video.html", nullptr)); + GUniquePtr<char> resourceURL(g_filename_to_uri(resourcePath.get(), nullptr, nullptr)); + webkit_web_view_load_uri(test->m_webView, resourceURL.get()); + test->waitUntilLoadFinished(); + g_assert(!webkit_web_view_is_playing_audio(test->m_webView)); + + test->runJavaScriptAndWaitUntilFinished("playVideo();", nullptr); + if (!webkit_web_view_is_playing_audio(test->m_webView)) + test->waitUntilIsPlayingAudioChanged(); + g_assert(webkit_web_view_is_playing_audio(test->m_webView)); + + // Pause the video, and check again. + test->runJavaScriptAndWaitUntilFinished("document.getElementById('test-video').pause();", nullptr); + if (webkit_web_view_is_playing_audio(test->m_webView)) + test->waitUntilIsPlayingAudioChanged(); + g_assert(!webkit_web_view_is_playing_audio(test->m_webView)); +} + +static void testWebViewBackgroundColor(WebViewTest* test, gconstpointer) +{ + // White is the default background. + GdkRGBA rgba; + webkit_web_view_get_background_color(test->m_webView, &rgba); + g_assert_cmpfloat(rgba.red, ==, 1); + g_assert_cmpfloat(rgba.green, ==, 1); + g_assert_cmpfloat(rgba.blue, ==, 1); + g_assert_cmpfloat(rgba.alpha, ==, 1); + + // Set a different (semi-transparent red). + rgba.red = 1; + rgba.green = 0; + rgba.blue = 0; + rgba.alpha = 0.5; + webkit_web_view_set_background_color(test->m_webView, &rgba); + g_assert_cmpfloat(rgba.red, ==, 1); + g_assert_cmpfloat(rgba.green, ==, 0); + g_assert_cmpfloat(rgba.blue, ==, 0); + g_assert_cmpfloat(rgba.alpha, ==, 0.5); + + // The actual rendering can't be tested using unit tests, use + // MiniBrowser --bg-color="<color-value>" for manually testing this API. +} + +static void testWebViewPreferredSize(WebViewTest* test, gconstpointer) +{ + test->loadHtml("<html style='width: 325px; height: 615px'></html>", nullptr); + test->waitUntilLoadFinished(); + test->showInWindowAndWaitUntilMapped(); + GtkRequisition minimunSize, naturalSize; + gtk_widget_get_preferred_size(GTK_WIDGET(test->m_webView), &minimunSize, &naturalSize); + g_assert_cmpint(minimunSize.width, ==, 0); + g_assert_cmpint(minimunSize.height, ==, 0); + g_assert_cmpint(naturalSize.width, ==, 325); + g_assert_cmpint(naturalSize.height, ==, 615); +} + +class WebViewTitleTest: public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(WebViewTitleTest); + + static void titleChangedCallback(WebKitWebView* view, GParamSpec*, WebViewTitleTest* test) + { + test->m_webViewTitles.append(webkit_web_view_get_title(view)); + } + + WebViewTitleTest() + { + g_signal_connect(m_webView, "notify::title", G_CALLBACK(titleChangedCallback), this); + } + + Vector<CString> m_webViewTitles; +}; + +static void testWebViewTitleChange(WebViewTitleTest* test, gconstpointer) +{ + g_assert_cmpint(test->m_webViewTitles.size(), ==, 0); + + test->loadHtml("<head><title>Page Title</title></head>", nullptr); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_webViewTitles.size(), ==, 1); + g_assert_cmpstr(test->m_webViewTitles[0].data(), ==, "Page Title"); + + test->loadHtml("<head><title>Another Page Title</title></head>", nullptr); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_webViewTitles.size(), ==, 3); + /* Page title should be immediately unset when loading a new page. */ + g_assert_cmpstr(test->m_webViewTitles[1].data(), ==, ""); + g_assert_cmpstr(test->m_webViewTitles[2].data(), ==, "Another Page Title"); + + test->loadHtml("<p>This page has no title!</p>", nullptr); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_webViewTitles.size(), ==, 4); + g_assert_cmpstr(test->m_webViewTitles[3].data(), ==, ""); + + test->loadHtml("<script>document.title = 'one'; document.title = 'two'; document.title = 'three';</script>", nullptr); + test->waitUntilLoadFinished(); + g_assert_cmpint(test->m_webViewTitles.size(), ==, 7); + g_assert_cmpstr(test->m_webViewTitles[4].data(), ==, "one"); + g_assert_cmpstr(test->m_webViewTitles[5].data(), ==, "two"); + g_assert_cmpstr(test->m_webViewTitles[6].data(), ==, "three"); +} + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + if (message->method != SOUP_METHOD_GET) { + soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + if (g_str_equal(path, "/")) { + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_complete(message->response_body); + } else + soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); +} + void beforeAll() { - WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext); + gServer = new WebKitTestServer(); + gServer->run(serverCallback); + + WebViewTest::add("WebKitWebView", "web-context", testWebViewWebContext); + WebViewTest::add("WebKitWebView", "web-context-lifetime", testWebViewWebContextLifetime); + WebViewTest::add("WebKitWebView", "ephemeral", testWebViewEphemeral); WebViewTest::add("WebKitWebView", "custom-charset", testWebViewCustomCharset); WebViewTest::add("WebKitWebView", "settings", testWebViewSettings); WebViewTest::add("WebKitWebView", "zoom-level", testWebViewZoomLevel); @@ -581,9 +1070,15 @@ void beforeAll() WebViewTest::add("WebKitWebView", "can-show-mime-type", testWebViewCanShowMIMEType); FormClientTest::add("WebKitWebView", "submit-form", testWebViewSubmitForm); SaveWebViewTest::add("WebKitWebView", "save", testWebViewSave); - WebViewTest::add("WebKitWebView", "view-mode", testWebViewMode); SnapshotWebViewTest::add("WebKitWebView", "snapshot", testWebViewSnapshot); WebViewTest::add("WebKitWebView", "page-visibility", testWebViewPageVisibility); + NotificationWebViewTest::add("WebKitWebView", "notification", testWebViewNotification); + NotificationWebViewTest::add("WebKitWebView", "notification-initial-permission-allowed", testWebViewNotificationInitialPermissionAllowed); + NotificationWebViewTest::add("WebKitWebView", "notification-initial-permission-disallowed", testWebViewNotificationInitialPermissionDisallowed); + IsPlayingAudioWebViewTest::add("WebKitWebView", "is-playing-audio", testWebViewIsPlayingAudio); + WebViewTest::add("WebKitWebView", "background-color", testWebViewBackgroundColor); + WebViewTest::add("WebKitWebView", "preferred-size", testWebViewPreferredSize); + WebViewTitleTest::add("WebKitWebView", "title-change", testWebViewTitleChange); } void afterAll() |