diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp | 351 |
1 files changed, 296 insertions, 55 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp index a4d27a508..6b95a7fe4 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Igalia S.L. + * Copyright (C) 2012, 2014 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,12 +27,10 @@ #include <string.h> #include <webkit2/webkit2.h> #include <wtf/Vector.h> -#include <wtf/gobject/GRefPtr.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/CString.h> -static char* kTempDirectory; - class DownloadTest: public Test { public: MAKE_GLIB_TEST_FIXTURE(DownloadTest); @@ -56,6 +54,8 @@ public: { g_assert(webkit_download_get_destination(download)); g_assert_cmpstr(webkit_download_get_destination(download), ==, destination); + GRefPtr<GFile> file = adoptGRef(g_file_new_for_uri(destination)); + g_assert(g_file_query_exists(file.get(), nullptr)); test->createdDestination(download, destination); } @@ -72,6 +72,14 @@ public: static void failedCallback(WebKitDownload* download, GError* error, DownloadTest* test) { g_assert(error); + + const char* destinationURI = webkit_download_get_destination(download); + if (destinationURI) { + GUniquePtr<char> tempFileURI(g_strconcat(destinationURI, ".wkdownload", nullptr)); + GRefPtr<GFile> tempFile = adoptGRef(g_file_new_for_uri(tempFileURI.get())); + g_assert(!g_file_query_exists(tempFile.get(), nullptr)); + } + test->failed(download, error); } @@ -95,21 +103,23 @@ public: } DownloadTest() - : m_webContext(webkit_web_context_get_default()) - , m_mainLoop(g_main_loop_new(0, TRUE)) + : m_mainLoop(g_main_loop_new(nullptr, TRUE)) , m_downloadSize(0) + , m_allowOverwrite(false) { - g_signal_connect(m_webContext, "download-started", G_CALLBACK(downloadStartedCallback), this); + g_signal_connect(m_webContext.get(), "download-started", G_CALLBACK(downloadStartedCallback), this); } ~DownloadTest() { - g_signal_handlers_disconnect_matched(m_webContext, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + g_signal_handlers_disconnect_matched(m_webContext.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); g_main_loop_unref(m_mainLoop); } virtual void started(WebKitDownload* download) { + m_downloadSize = 0; + m_downloadEvents.clear(); m_downloadEvents.append(Started); } @@ -144,17 +154,21 @@ public: virtual void decideDestination(WebKitDownload* download, const gchar* suggestedFilename) { - GUniquePtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL)); + GUniquePtr<char> destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr)); GUniquePtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); webkit_download_set_destination(download, destinationURI.get()); } - WebKitDownload* downloadURIAndWaitUntilFinishes(const CString& requestURI) + GRefPtr<WebKitDownload> downloadURIAndWaitUntilFinishes(const CString& requestURI) { - WebKitDownload* download = webkit_web_context_download_uri(m_webContext, requestURI.data()); - assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download)); + GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(m_webContext.get(), requestURI.data())); + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); - WebKitURIRequest* request = webkit_download_get_request(download); + g_assert(!webkit_download_get_allow_overwrite(download.get())); + webkit_download_set_allow_overwrite(download.get(), m_allowOverwrite); + g_assert(webkit_download_get_allow_overwrite(download.get()) == m_allowOverwrite); + + WebKitURIRequest* request = webkit_download_get_request(download.get()); g_assert(request); ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI); @@ -174,19 +188,19 @@ public: g_file_delete(destFile.get(), 0, 0); } - WebKitWebContext* m_webContext; GMainLoop* m_mainLoop; Vector<DownloadEvent> m_downloadEvents; guint64 m_downloadSize; + bool m_allowOverwrite; }; -static void testDownloadLocalFile(DownloadTest* test, gconstpointer) +static GRefPtr<WebKitDownload> downloadLocalFileSuccessfully(DownloadTest* test, const char* filename) { - GUniquePtr<char> sourcePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + GUniquePtr<char> sourcePath(g_build_filename(Test::getResourcesDir().data(), filename, nullptr)); GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get())); GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0)); GUniquePtr<char> sourceURI(g_file_get_uri(source.get())); - GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(sourceURI.get())); + GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(sourceURI.get()); g_assert(!webkit_download_get_web_view(download.get())); Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; @@ -204,15 +218,50 @@ static void testDownloadLocalFile(DownloadTest* test, gconstpointer) g_assert_cmpint(test->m_downloadSize, ==, g_file_info_get_size(sourceInfo.get())); g_assert(webkit_download_get_destination(download.get())); g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); - test->checkDestinationAndDeleteFile(download.get(), "test.pdf"); + + return download; +} + +static void testDownloadLocalFile(DownloadTest* test, gconstpointer) +{ + static const char* filename = "test.pdf"; + GRefPtr<WebKitDownload> download = downloadLocalFileSuccessfully(test, filename); + test->checkDestinationAndDeleteFile(download.get(), filename); +} + +static void createFileAtDestination(const char* filename) +{ + GUniquePtr<char> path(g_build_filename(Test::dataDirectory(), filename, nullptr)); + GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get())); + GUniqueOutPtr<GError> error; + g_file_create(file.get(), G_FILE_CREATE_NONE, nullptr, &error.outPtr()); + g_assert(!error); + g_assert(g_file_query_exists(file.get(), nullptr)); +} + +static void testDownloadOverwriteDestinationAllowed(DownloadTest* test, gconstpointer) +{ + static const char* filename = "test.pdf"; + createFileAtDestination(filename); + + test->m_allowOverwrite = true; + GRefPtr<WebKitDownload> download = downloadLocalFileSuccessfully(test, filename); + test->checkDestinationAndDeleteFile(download.get(), filename); } class DownloadErrorTest: public DownloadTest { public: MAKE_GLIB_TEST_FIXTURE(DownloadErrorTest); + enum ExpectedError { + NetworkError, + DownloadCancelled, + InvalidDestination, + DestinationExists + }; + DownloadErrorTest() - : m_expectedError(WEBKIT_DOWNLOAD_ERROR_NETWORK) + : m_expectedError(NetworkError) { } @@ -223,7 +272,7 @@ public: void createdDestination(WebKitDownload* download, const char* destination) { - if (m_expectedError == WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER) + if (m_expectedError == DownloadCancelled) webkit_download_cancel(download); else g_assert_not_reached(); @@ -231,26 +280,65 @@ public: void failed(WebKitDownload* download, GError* error) { - g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, m_expectedError)); + g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, expectedErrorToWebKitDownloadError(m_expectedError))); DownloadTest::failed(download, error); } void decideDestination(WebKitDownload* download, const gchar* suggestedFilename) { - if (m_expectedError != WEBKIT_DOWNLOAD_ERROR_DESTINATION) { + if (m_expectedError != InvalidDestination) { DownloadTest::decideDestination(download, suggestedFilename); return; } webkit_download_set_destination(download, "file:///foo/bar"); } - WebKitDownloadError m_expectedError; + static WebKitDownloadError expectedErrorToWebKitDownloadError(ExpectedError expected) + { + switch (expected) { + case NetworkError: + return WEBKIT_DOWNLOAD_ERROR_NETWORK; + case DownloadCancelled: + return WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; + case InvalidDestination: + return WEBKIT_DOWNLOAD_ERROR_DESTINATION; + case DestinationExists: + return WEBKIT_DOWNLOAD_ERROR_DESTINATION; + default: + g_assert_not_reached(); + } + } + + ExpectedError m_expectedError; }; +static void testDownloadOverwriteDestinationDisallowed(DownloadErrorTest* test, gconstpointer) +{ + static const char* filename = "test.pdf"; + createFileAtDestination(filename); + + test->m_expectedError = DownloadErrorTest::DestinationExists; + GUniquePtr<char> sourcePath(g_build_filename(Test::getResourcesDir().data(), filename, nullptr)); + GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get())); + GUniquePtr<char> sourceURI(g_file_get_uri(source.get())); + GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(sourceURI.get()); + g_assert(!webkit_download_get_web_view(download.get())); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 4); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::Failed); + g_assert_cmpint(events[3], ==, DownloadTest::Finished); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 0); + + test->checkDestinationAndDeleteFile(download.get(), filename); +} + static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) { - test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK; - GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes("file:///foo/bar")); + test->m_expectedError = DownloadErrorTest::NetworkError; + GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes("file:///foo/bar"); g_assert(!webkit_download_get_web_view(download.get())); Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; @@ -261,11 +349,11 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) events.clear(); g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); - test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; - GUniquePtr<char> path(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL)); + test->m_expectedError = DownloadErrorTest::InvalidDestination; + GUniquePtr<char> path(g_build_filename(Test::getResourcesDir().data(), "test.pdf", nullptr)); GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get())); GUniquePtr<char> uri(g_file_get_uri(file.get())); - download = adoptGRef(test->downloadURIAndWaitUntilFinishes(uri.get())); + download = test->downloadURIAndWaitUntilFinishes(uri.get()); g_assert(!webkit_download_get_web_view(download.get())); g_assert_cmpint(events.size(), ==, 4); @@ -277,8 +365,8 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer) g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); test->checkDestinationAndDeleteFile(download.get(), "bar"); - test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; - download = adoptGRef(test->downloadURIAndWaitUntilFinishes(uri.get())); + test->m_expectedError = DownloadErrorTest::DownloadCancelled; + download = test->downloadURIAndWaitUntilFinishes(uri.get()); g_assert(!webkit_download_get_web_view(download.get())); g_assert_cmpint(events.size(), ==, 4); @@ -300,15 +388,17 @@ static void addContentDispositionHTTPHeaderToResponse(SoupMessage* message) soup_message_headers_append(message->response_headers, "Content-Disposition", contentDisposition.get()); } -static gboolean writeNextChunkIdle(SoupMessage* message) -{ - soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, "chunk", 5); - return FALSE; -} - static void writeNextChunk(SoupMessage* message) { - g_timeout_add(100, reinterpret_cast<GSourceFunc>(writeNextChunkIdle), message); + /* We need a big enough chunk for the sniffer to not block the load */ + static const char* chunk = "Testing!Testing!Testing!Testing!Testing!Testing!Testing!" + "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" + "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" + "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" + "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" + "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" + "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"; + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, chunk, strlen(chunk)); } static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) @@ -329,7 +419,10 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* return; } - GUniquePtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL)); + if (g_str_equal(path, "/unknown")) + path = "/test.pdf"; + + GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), path, nullptr)); char* contents; gsize contentsLength; if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) { @@ -346,7 +439,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char* static void testDownloadRemoteFile(DownloadTest* test, gconstpointer) { - GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf"))); + GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf")); g_assert(!webkit_download_get_web_view(download.get())); Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; @@ -364,13 +457,14 @@ static void testDownloadRemoteFile(DownloadTest* test, gconstpointer) g_assert(webkit_download_get_destination(download.get())); g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); - test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename); + GUniquePtr<char> expectedFilename(g_strdup_printf("%s.pdf", kServerSuggestedFilename)); + test->checkDestinationAndDeleteFile(download.get(), expectedFilename.get()); } static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer) { - test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK; - GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/foo"))); + test->m_expectedError = DownloadErrorTest::NetworkError; + GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/foo")); g_assert(!webkit_download_get_web_view(download.get())); Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; @@ -384,8 +478,8 @@ static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer) g_assert_cmpuint(webkit_uri_response_get_status_code(response), ==, 404); g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); - test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION; - download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf"))); + test->m_expectedError = DownloadErrorTest::InvalidDestination; + download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf")); g_assert(!webkit_download_get_web_view(download.get())); g_assert_cmpint(events.size(), ==, 4); @@ -397,8 +491,8 @@ static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer) g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1); test->checkDestinationAndDeleteFile(download.get(), "bar"); - test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER; - download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/cancel-after-destination"))); + test->m_expectedError = DownloadErrorTest::DownloadCancelled; + download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/cancel-after-destination")); g_assert(!webkit_download_get_web_view(download.get())); g_assert_cmpint(events.size(), ==, 4); @@ -422,6 +516,8 @@ public: { test->m_download = download; test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download)); + g_signal_connect(download, "decide-destination", G_CALLBACK(downloadDecideDestinationCallback), test); + g_signal_connect(download, "finished", G_CALLBACK(downloadFinishedCallback), test); test->quitMainLoop(); } @@ -444,8 +540,10 @@ public: static gboolean downloadDecideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, WebViewDownloadTest* test) { - GUniquePtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL)); + GUniquePtr<char> destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr)); GUniquePtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0)); + if (test->m_shouldDelayDecideDestination) + g_usleep(0.2 * G_USEC_PER_SEC); webkit_download_set_destination(download, destinationURI.get()); return TRUE; } @@ -457,17 +555,17 @@ public: void waitUntilDownloadFinished() { - g_signal_connect(m_download.get(), "decide-destination", G_CALLBACK(downloadDecideDestinationCallback), this); - g_signal_connect(m_download.get(), "finished", G_CALLBACK(downloadFinishedCallback), this); g_main_loop_run(m_mainLoop); } GRefPtr<WebKitDownload> m_download; + bool m_shouldDelayDecideDestination { false }; }; static void testWebViewDownloadURI(WebViewDownloadTest* test, gconstpointer) { GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_view_download_uri(test->m_webView, kServer->getURIForPath("/test.pdf").data())); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get())); test->waitUntilDownloadStarted(); g_assert(test->m_webView == webkit_download_get_web_view(download.get())); test->waitUntilDownloadFinished(); @@ -511,7 +609,28 @@ public: static void testPolicyResponseDownload(PolicyResponseDownloadTest* test, gconstpointer) { - // Test that a download started by the the policy checker contains the web view. + CString requestURI = kServer->getURIForPath("/test.pdf").data(); + // Delay the DecideDestination to ensure that the load is aborted before the network task has became a download. + // See https://bugs.webkit.org/show_bug.cgi?id=164220. + test->m_shouldDelayDecideDestination = true; + test->loadURI(requestURI.data()); + test->waitUntilDownloadStarted(); + + WebKitURIRequest* request = webkit_download_get_request(test->m_download.get()); + g_assert(request); + ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI); + + g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get())); + test->waitUntilDownloadFinished(); + + GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test->m_download.get()))); + GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), nullptr, nullptr)); + g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), >, 0); + g_file_delete(downloadFile.get(), nullptr, nullptr); +} + +static void testPolicyResponseDownloadCancel(PolicyResponseDownloadTest* test, gconstpointer) +{ CString requestURI = kServer->getURIForPath("/test.pdf").data(); test->loadURI(requestURI.data()); test->waitUntilDownloadStarted(); @@ -524,24 +643,146 @@ static void testPolicyResponseDownload(PolicyResponseDownloadTest* test, gconstp test->cancelDownloadAndWaitUntilFinished(); } +static void testDownloadMIMEType(DownloadTest* test, gconstpointer) +{ + GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/unknown")); + g_assert(!webkit_download_get_web_view(download.get())); + + Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents; + g_assert_cmpint(events.size(), ==, 5); + g_assert_cmpint(events[0], ==, DownloadTest::Started); + g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse); + g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination); + g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData); + g_assert_cmpint(events[4], ==, DownloadTest::Finished); + events.clear(); + + WebKitURIRequest* request = webkit_download_get_request(download.get()); + WEBKIT_IS_URI_REQUEST(request); + ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, kServer->getURIForPath("/unknown")); + + WebKitURIResponse* response = webkit_download_get_response(download.get()); + WEBKIT_IS_URI_RESPONSE(response); + g_assert_cmpstr(webkit_uri_response_get_mime_type(response), ==, "application/pdf"); + + g_assert(webkit_download_get_destination(download.get())); + g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1); + GUniquePtr<char> expectedFilename(g_strdup_printf("%s.pdf", kServerSuggestedFilename)); + test->checkDestinationAndDeleteFile(download.get(), expectedFilename.get()); +} + +static gboolean contextMenuCallback(WebKitWebView* webView, WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult* hitTestResult, WebViewDownloadTest* test) +{ + g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult)); + g_assert(webkit_hit_test_result_context_is_link(hitTestResult)); + GList* items = webkit_context_menu_get_items(contextMenu); + GRefPtr<WebKitContextMenuItem> contextMenuItem; + for (GList* l = items; l; l = g_list_next(l)) { + g_assert(WEBKIT_IS_CONTEXT_MENU_ITEM(l->data)); + auto* item = WEBKIT_CONTEXT_MENU_ITEM(l->data); + if (webkit_context_menu_item_get_stock_action(item) == WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK) { + contextMenuItem = item; + break; + } + } + g_assert(contextMenuItem.get()); + webkit_context_menu_remove_all(contextMenu); + webkit_context_menu_append(contextMenu, contextMenuItem.get()); + test->quitMainLoop(); + return FALSE; +} + +static void testContextMenuDownloadActions(WebViewDownloadTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + + static const char* linkHTMLFormat = "<html><body><a style='position:absolute; left:1; top:1' href='%s'>Download Me</a></body></html>"; + GUniquePtr<char> linkHTML(g_strdup_printf(linkHTMLFormat, kServer->getURIForPath("/test.pdf").data())); + test->loadHtml(linkHTML.get(), kServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); + + g_signal_connect(test->m_webView, "context-menu", G_CALLBACK(contextMenuCallback), test); + g_idle_add([](gpointer userData) -> gboolean { + auto* test = static_cast<WebViewDownloadTest*>(userData); + test->clickMouseButton(1, 1, 3); + return FALSE; + }, test); + g_main_loop_run(test->m_mainLoop); + + g_idle_add([](gpointer userData) -> gboolean { + auto* test = static_cast<WebViewDownloadTest*>(userData); + // Select and activate the context menu action. + test->keyStroke(GDK_KEY_Down); + test->keyStroke(GDK_KEY_Return); + return FALSE; + }, test); + test->waitUntilDownloadStarted(); + + g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get())); + test->waitUntilDownloadFinished(); + + GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test->m_download.get()))); + GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), nullptr, nullptr)); + g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), >, 0); + g_file_delete(downloadFile.get(), nullptr, nullptr); +} + +static void testBlobDownload(WebViewDownloadTest* test, gconstpointer) +{ + test->showInWindowAndWaitUntilMapped(); + + static const char* linkBlobHTML = + "<html><body>" + "<a id='downloadLink' style='position:absolute; left:1; top:1' download='foo.pdf'>Download Me</a>" + "<script>" + " blob = new Blob(['Hello world'], {type: 'text/plain'});" + " document.getElementById('downloadLink').href = window.URL.createObjectURL(blob);" + "</script>" + "</body></html>"; + test->loadHtml(linkBlobHTML, kServer->getURIForPath("/").data()); + test->waitUntilLoadFinished(); + + g_idle_add([](gpointer userData) -> gboolean { + auto* test = static_cast<WebViewDownloadTest*>(userData); + test->clickMouseButton(1, 1, 1); + return FALSE; + }, test); + test->waitUntilDownloadStarted(); + + g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get())); + test->waitUntilDownloadFinished(); + + GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test->m_download.get()))); + GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), nullptr, nullptr)); + GUniquePtr<char> downloadPath(g_file_get_path(downloadFile.get())); + GUniqueOutPtr<char> downloadContents; + gsize downloadContentsLength; + g_assert(g_file_get_contents(downloadPath.get(), &downloadContents.outPtr(), &downloadContentsLength, nullptr)); + g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), ==, downloadContentsLength); + g_assert_cmpstr(downloadContents.get(), ==, "Hello world"); + g_file_delete(downloadFile.get(), nullptr, nullptr); +} + void beforeAll() { kServer = new WebKitTestServer(); kServer->run(serverCallback); - kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0); - g_assert(kTempDirectory); - DownloadTest::add("Downloads", "local-file", testDownloadLocalFile); + DownloadTest::add("Downloads", "overwrite-destination-allowed", testDownloadOverwriteDestinationAllowed); + DownloadErrorTest::add("Downloads", "overwrite-destination-disallowed", testDownloadOverwriteDestinationDisallowed); DownloadErrorTest::add("Downloads", "local-file-error", testDownloadLocalFileError); DownloadTest::add("Downloads", "remote-file", testDownloadRemoteFile); DownloadErrorTest::add("Downloads", "remote-file-error", testDownloadRemoteFileError); WebViewDownloadTest::add("WebKitWebView", "download-uri", testWebViewDownloadURI); PolicyResponseDownloadTest::add("Downloads", "policy-decision-download", testPolicyResponseDownload); + PolicyResponseDownloadTest::add("Downloads", "policy-decision-download-cancel", testPolicyResponseDownloadCancel); + DownloadTest::add("Downloads", "mime-type", testDownloadMIMEType); + WebViewDownloadTest::add("Downloads", "contex-menu-download-actions", testContextMenuDownloadActions); + WebViewDownloadTest::add("Downloads", "blob-download", testBlobDownload); } void afterAll() { delete kServer; - g_rmdir(kTempDirectory); } |