2
* Copyright (C) 2012 Igalia S.L.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Library General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
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.
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.
22
#include "WebKitTestServer.h"
23
#include "WebViewTest.h"
24
#include <glib/gstdio.h>
26
#include <libsoup/soup.h>
28
#include <webkit2/webkit2.h>
29
#include <wtf/Vector.h>
30
#include <wtf/gobject/GOwnPtr.h>
31
#include <wtf/gobject/GRefPtr.h>
32
#include <wtf/text/CString.h>
34
static char* kTempDirectory;
36
class DownloadTest: public Test {
38
MAKE_GLIB_TEST_FIXTURE(DownloadTest);
49
static void receivedResponseCallback(WebKitDownload* download, GParamSpec*, DownloadTest* test)
51
g_assert(webkit_download_get_response(download));
52
test->receivedResponse(download);
55
static gboolean createdDestinationCallback(WebKitDownload* download, const gchar* destination, DownloadTest* test)
57
g_assert(webkit_download_get_destination(download));
58
g_assert_cmpstr(webkit_download_get_destination(download), ==, destination);
59
test->createdDestination(download, destination);
63
static gboolean receivedDataCallback(WebKitDownload* download, guint64 dataLength, DownloadTest* test)
65
test->receivedData(download, dataLength);
69
static gboolean finishedCallback(WebKitDownload* download, DownloadTest* test)
71
test->finished(download);
75
static gboolean failedCallback(WebKitDownload* download, GError* error, DownloadTest* test)
78
test->failed(download, error);
82
static gboolean decideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, DownloadTest* test)
84
g_assert(suggestedFilename);
85
test->decideDestination(download, suggestedFilename);
89
static void downloadStartedCallback(WebKitWebContext* context, WebKitDownload* download, DownloadTest* test)
91
g_assert(webkit_download_get_request(download));
92
test->started(download);
93
g_signal_connect(download, "notify::response", G_CALLBACK(receivedResponseCallback), test);
94
g_signal_connect(download, "created-destination", G_CALLBACK(createdDestinationCallback), test);
95
g_signal_connect(download, "received-data", G_CALLBACK(receivedDataCallback), test);
96
g_signal_connect(download, "finished", G_CALLBACK(finishedCallback), test);
97
g_signal_connect(download, "failed", G_CALLBACK(failedCallback), test);
98
g_signal_connect(download, "decide-destination", G_CALLBACK(decideDestinationCallback), test);
102
: m_webContext(webkit_web_context_get_default())
103
, m_mainLoop(g_main_loop_new(0, TRUE))
106
g_signal_connect(m_webContext, "download-started", G_CALLBACK(downloadStartedCallback), this);
111
g_signal_handlers_disconnect_matched(m_webContext, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
112
g_main_loop_unref(m_mainLoop);
115
virtual void started(WebKitDownload* download)
117
m_downloadEvents.append(Started);
120
virtual void receivedResponse(WebKitDownload* download)
122
m_downloadEvents.append(ReceivedResponse);
125
virtual void createdDestination(WebKitDownload* download, const char* destination)
127
m_downloadEvents.append(CreatedDestination);
130
virtual void receivedData(WebKitDownload* download, guint64 dataLength)
132
m_downloadSize += dataLength;
133
if (!m_downloadEvents.contains(ReceivedData))
134
m_downloadEvents.append(ReceivedData);
137
virtual void finished(WebKitDownload* download)
139
g_assert_cmpuint(m_downloadSize, ==, webkit_download_get_received_data_length(download));
140
m_downloadEvents.append(Finished);
141
g_main_loop_quit(m_mainLoop);
144
virtual void failed(WebKitDownload* download, GError* error)
146
m_downloadEvents.append(Failed);
149
virtual void decideDestination(WebKitDownload* download, const gchar* suggestedFilename)
151
GOwnPtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL));
152
GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0));
153
webkit_download_set_destination(download, destinationURI.get());
156
void waitUntilDownloadFinishes()
158
g_main_loop_run(m_mainLoop);
161
void checkDestinationAndDeleteFile(WebKitDownload* download, const char* expectedName)
163
if (!webkit_download_get_destination(download))
165
GRefPtr<GFile> destFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(download)));
166
GOwnPtr<char> destBasename(g_file_get_basename(destFile.get()));
167
g_assert_cmpstr(destBasename.get(), ==, expectedName);
169
g_file_delete(destFile.get(), 0, 0);
172
WebKitWebContext* m_webContext;
173
GMainLoop* m_mainLoop;
174
Vector<DownloadEvent> m_downloadEvents;
175
guint64 m_downloadSize;
178
static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
180
GOwnPtr<char> sourcePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL));
181
GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get()));
182
GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0));
183
GOwnPtr<char> sourceURI(g_file_get_uri(source.get()));
184
GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, sourceURI.get()));
185
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
186
test->waitUntilDownloadFinishes();
187
g_assert(!webkit_download_get_web_view(download.get()));
189
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
190
g_assert_cmpint(events.size(), ==, 5);
191
g_assert_cmpint(events[0], ==, DownloadTest::Started);
192
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
193
g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination);
194
g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData);
195
g_assert_cmpint(events[4], ==, DownloadTest::Finished);
197
WebKitURIRequest* request = webkit_download_get_request(download.get());
199
g_assert_cmpstr(webkit_uri_request_get_uri(request), ==, sourceURI.get());
201
g_assert_cmpint(test->m_downloadSize, ==, g_file_info_get_size(sourceInfo.get()));
202
g_assert(webkit_download_get_destination(download.get()));
203
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1);
204
test->checkDestinationAndDeleteFile(download.get(), "test.pdf");
207
class DownloadErrorTest: public DownloadTest {
209
MAKE_GLIB_TEST_FIXTURE(DownloadErrorTest);
212
: m_expectedError(WEBKIT_DOWNLOAD_ERROR_NETWORK)
216
void receivedResponse(WebKitDownload* download)
218
DownloadTest::receivedResponse(download);
219
if (m_expectedError == WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER)
220
webkit_download_cancel(download);
223
void createdDestination(WebKitDownload* download, const char* destination)
225
g_assert_not_reached();
228
void failed(WebKitDownload* download, GError* error)
230
g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, m_expectedError));
231
DownloadTest::failed(download, error);
234
void decideDestination(WebKitDownload* download, const gchar* suggestedFilename)
236
if (m_expectedError != WEBKIT_DOWNLOAD_ERROR_DESTINATION) {
237
DownloadTest::decideDestination(download, suggestedFilename);
240
webkit_download_set_destination(download, "file:///foo/bar");
243
WebKitDownloadError m_expectedError;
246
static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
248
test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK;
249
GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, "file:///foo/bar"));
250
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
251
test->waitUntilDownloadFinishes();
252
g_assert(!webkit_download_get_web_view(download.get()));
254
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
255
g_assert_cmpint(events.size(), ==, 3);
256
g_assert_cmpint(events[0], ==, DownloadTest::Started);
257
g_assert_cmpint(events[1], ==, DownloadTest::Failed);
258
g_assert_cmpint(events[2], ==, DownloadTest::Finished);
260
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
262
test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION;
263
GOwnPtr<char> path(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL));
264
GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get()));
265
GOwnPtr<char> uri(g_file_get_uri(file.get()));
266
download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get()));
267
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
268
test->waitUntilDownloadFinishes();
269
g_assert(!webkit_download_get_web_view(download.get()));
271
events = test->m_downloadEvents;
272
g_assert_cmpint(events.size(), ==, 4);
273
g_assert_cmpint(events[0], ==, DownloadTest::Started);
274
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
275
g_assert_cmpint(events[2], ==, DownloadTest::Failed);
276
g_assert_cmpint(events[3], ==, DownloadTest::Finished);
278
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
279
test->checkDestinationAndDeleteFile(download.get(), "bar");
281
test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
282
download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, uri.get()));
283
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
284
test->waitUntilDownloadFinishes();
285
g_assert(!webkit_download_get_web_view(download.get()));
287
events = test->m_downloadEvents;
288
g_assert_cmpint(events.size(), ==, 4);
289
g_assert_cmpint(events[0], ==, DownloadTest::Started);
290
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
291
g_assert_cmpint(events[2], ==, DownloadTest::Failed);
292
g_assert_cmpint(events[3], ==, DownloadTest::Finished);
294
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
295
test->checkDestinationAndDeleteFile(download.get(), "test.pdf");
298
static WebKitTestServer* kServer;
299
static const char* kServerSuggestedFilename = "webkit-downloaded-file";
301
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
303
if (message->method != SOUP_METHOD_GET) {
304
soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
308
GOwnPtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL));
310
gsize contentsLength;
311
if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) {
312
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
313
soup_message_body_complete(message->response_body);
317
soup_message_set_status(message, SOUP_STATUS_OK);
319
GOwnPtr<char> contentDisposition(g_strdup_printf("filename=%s", kServerSuggestedFilename));
320
soup_message_headers_append(message->response_headers, "Content-Disposition", contentDisposition.get());
321
soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength);
323
soup_message_body_complete(message->response_body);
326
static void testDownloadRemoteFile(DownloadTest* test, gconstpointer)
328
GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data()));
329
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
330
test->waitUntilDownloadFinishes();
331
g_assert(!webkit_download_get_web_view(download.get()));
333
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
334
g_assert_cmpint(events.size(), ==, 5);
335
g_assert_cmpint(events[0], ==, DownloadTest::Started);
336
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
337
g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination);
338
g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData);
339
g_assert_cmpint(events[4], ==, DownloadTest::Finished);
342
WebKitURIRequest* request = webkit_download_get_request(download.get());
344
CString requestURI = kServer->getURIForPath("/test.pdf");
345
g_assert_cmpstr(webkit_uri_request_get_uri(request), ==, requestURI.data());
347
g_assert(webkit_download_get_destination(download.get()));
348
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1);
349
test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename);
352
static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
354
test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK;
355
GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(test->m_webContext,
356
kServer->getURIForPath("/foo").data()));
357
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
358
test->waitUntilDownloadFinishes();
359
g_assert(!webkit_download_get_web_view(download.get()));
361
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
362
g_assert_cmpint(events.size(), ==, 4);
363
g_assert_cmpint(events[0], ==, DownloadTest::Started);
364
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
365
g_assert_cmpint(events[2], ==, DownloadTest::Failed);
366
g_assert_cmpint(events[3], ==, DownloadTest::Finished);
368
WebKitURIResponse* response = webkit_download_get_response(download.get());
369
g_assert_cmpuint(webkit_uri_response_get_status_code(response), ==, 404);
370
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
372
test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION;
373
download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data()));
374
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
375
test->waitUntilDownloadFinishes();
376
g_assert(!webkit_download_get_web_view(download.get()));
378
events = test->m_downloadEvents;
379
g_assert_cmpint(events.size(), ==, 4);
380
g_assert_cmpint(events[0], ==, DownloadTest::Started);
381
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
382
g_assert_cmpint(events[2], ==, DownloadTest::Failed);
383
g_assert_cmpint(events[3], ==, DownloadTest::Finished);
385
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
386
test->checkDestinationAndDeleteFile(download.get(), "bar");
388
test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
389
download = adoptGRef(webkit_web_context_download_uri(test->m_webContext, kServer->getURIForPath("/test.pdf").data()));
390
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
391
test->waitUntilDownloadFinishes();
392
g_assert(!webkit_download_get_web_view(download.get()));
394
events = test->m_downloadEvents;
395
g_assert_cmpint(events.size(), ==, 4);
396
g_assert_cmpint(events[0], ==, DownloadTest::Started);
397
g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
398
g_assert_cmpint(events[2], ==, DownloadTest::Failed);
399
g_assert_cmpint(events[3], ==, DownloadTest::Finished);
401
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
402
test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename);
405
class WebViewDownloadTest: public WebViewTest {
407
MAKE_GLIB_TEST_FIXTURE(WebViewDownloadTest);
409
static void downloadStartedCallback(WebKitWebContext* context, WebKitDownload* download, WebViewDownloadTest* test)
411
test->m_download = download;
412
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download));
413
test->quitMainLoop();
416
WebViewDownloadTest()
418
g_signal_connect(webkit_web_view_get_context(m_webView), "download-started", G_CALLBACK(downloadStartedCallback), this);
421
~WebViewDownloadTest()
423
g_signal_handlers_disconnect_matched(webkit_web_view_get_context(m_webView), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
426
void waitUntilDownloadStarted()
429
g_main_loop_run(m_mainLoop);
430
g_assert(m_download.get());
433
static gboolean downloadDecideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, WebViewDownloadTest* test)
435
GOwnPtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL));
436
GOwnPtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0));
437
webkit_download_set_destination(download, destinationURI.get());
441
static void downloadFinishedCallback(WebKitDownload* download, WebViewDownloadTest* test)
443
test->quitMainLoop();
446
void waitUntilDownloadFinished()
448
g_signal_connect(m_download.get(), "decide-destination", G_CALLBACK(downloadDecideDestinationCallback), this);
449
g_signal_connect(m_download.get(), "finished", G_CALLBACK(downloadFinishedCallback), this);
450
g_main_loop_run(m_mainLoop);
453
GRefPtr<WebKitDownload> m_download;
456
static void testWebViewDownloadURI(WebViewDownloadTest* test, gconstpointer)
458
GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_view_download_uri(test->m_webView, kServer->getURIForPath("/test.pdf").data()));
459
test->waitUntilDownloadStarted();
460
g_assert(test->m_webView == webkit_download_get_web_view(download.get()));
461
test->waitUntilDownloadFinished();
463
GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(download.get())));
464
GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0));
465
g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), >, 0);
466
g_file_delete(downloadFile.get(), 0, 0);
469
class PolicyResponseDownloadTest: public WebViewDownloadTest {
471
MAKE_GLIB_TEST_FIXTURE(PolicyResponseDownloadTest);
473
static gboolean decidePolicyCallback(WebKitWebView* webView, WebKitPolicyDecision* decision, WebKitPolicyDecisionType type, PolicyResponseDownloadTest* test)
475
if (type != WEBKIT_POLICY_DECISION_TYPE_RESPONSE)
478
webkit_policy_decision_download(decision);
482
PolicyResponseDownloadTest()
484
g_signal_connect(m_webView, "decide-policy", G_CALLBACK(decidePolicyCallback), this);
487
~PolicyResponseDownloadTest()
489
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
492
void cancelDownloadAndWaitUntilFinished()
494
webkit_download_cancel(m_download.get());
495
waitUntilDownloadFinished();
500
static void testPolicyResponseDownload(PolicyResponseDownloadTest* test, gconstpointer)
502
// Test that a download started by the the policy checker contains the web view.
503
test->loadURI(kServer->getURIForPath("/test.pdf").data());
504
test->waitUntilDownloadStarted();
505
g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get()));
506
test->cancelDownloadAndWaitUntilFinished();
511
kServer = new WebKitTestServer();
512
kServer->run(serverCallback);
514
kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
515
g_assert(kTempDirectory);
517
DownloadTest::add("Downloads", "local-file", testDownloadLocalFile);
518
DownloadErrorTest::add("Downloads", "local-file-error", testDownloadLocalFileError);
519
DownloadTest::add("Downloads", "remote-file", testDownloadRemoteFile);
520
DownloadErrorTest::add("Downloads", "remote-file-error", testDownloadRemoteFileError);
521
WebViewDownloadTest::add("WebKitWebView", "download-uri", testWebViewDownloadURI);
522
PolicyResponseDownloadTest::add("Downloads", "policy-decision-download", testPolicyResponseDownload);
528
g_rmdir(kTempDirectory);