1/*
2 * Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2,1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "autotoolsconfig.h"
21#include <errno.h>
22#include <unistd.h>
23#include <glib/gstdio.h>
24#include <webkit/webkit.h>
25
26GMainLoop* loop;
27char* temporaryFilename = NULL;
28WebKitDownload* theDownload = NULL;
29
30static void
31test_webkit_download_create(void)
32{
33    WebKitNetworkRequest* request;
34    WebKitDownload* download;
35    const gchar* uri = "http://example.com";
36    gchar* tmpDir;
37
38    request = webkit_network_request_new(uri);
39    download = webkit_download_new(request);
40    g_object_unref(request);
41    g_assert_cmpstr(webkit_download_get_uri(download), ==, uri);
42    g_assert(webkit_download_get_network_request(download) == request);
43    g_assert(g_strrstr(uri, webkit_download_get_suggested_filename(download)));
44    g_assert(webkit_download_get_status(download) == WEBKIT_DOWNLOAD_STATUS_CREATED);
45    g_assert(!webkit_download_get_total_size(download));
46    g_assert(!webkit_download_get_current_size(download));
47    g_assert(!webkit_download_get_progress(download));
48    g_assert(!webkit_download_get_elapsed_time(download));
49    tmpDir = g_filename_to_uri(g_get_tmp_dir(), NULL, NULL);
50    webkit_download_set_destination_uri(download, tmpDir);
51    g_assert_cmpstr(tmpDir, ==, webkit_download_get_destination_uri(download));;
52    g_free(tmpDir);
53    g_object_unref(download);
54}
55
56static gboolean
57navigation_policy_decision_requested_cb(WebKitWebView* web_view,
58                                        WebKitWebFrame* web_frame,
59                                        WebKitNetworkRequest* request,
60                                        WebKitWebNavigationAction* action,
61                                        WebKitWebPolicyDecision* decision,
62                                        gpointer data)
63{
64    webkit_web_policy_decision_download(decision);
65    return TRUE;
66}
67
68static void
69notify_status_cb(GObject* object, GParamSpec* pspec, gpointer data)
70{
71    WebKitDownload* download = WEBKIT_DOWNLOAD(object);
72    switch (webkit_download_get_status(download)) {
73    case WEBKIT_DOWNLOAD_STATUS_FINISHED:
74    case WEBKIT_DOWNLOAD_STATUS_ERROR:
75        g_main_loop_quit(loop);
76        break;
77    case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
78        g_assert_not_reached();
79        break;
80    default:
81        break;
82    }
83}
84
85static gboolean
86set_filename(gchar* filename)
87{
88    gchar *uri = g_filename_to_uri(filename, NULL, NULL);
89
90    webkit_download_set_destination_uri(theDownload, uri);
91    g_free(uri);
92
93    webkit_download_start(theDownload);
94    return FALSE;
95}
96
97static void
98handle_download_requested_cb(WebKitDownload* download,
99                             gboolean* beenThere,
100                             gboolean asynch)
101{
102    theDownload = download;
103    *beenThere = TRUE;
104
105    if (temporaryFilename) {
106        if (asynch) {
107            g_idle_add((GSourceFunc)set_filename, temporaryFilename);
108        } else {
109            gchar *uri = g_filename_to_uri(temporaryFilename, NULL, NULL);
110            if (uri)
111                webkit_download_set_destination_uri(download, uri);
112            g_free(uri);
113        }
114    }
115
116    g_signal_connect(download, "notify::status",
117                     G_CALLBACK(notify_status_cb), NULL);
118}
119
120static gboolean
121download_requested_cb(WebKitWebView* web_view,
122                      WebKitDownload* download,
123                      gboolean* beenThere)
124{
125    handle_download_requested_cb(download, beenThere, FALSE);
126    return TRUE;
127}
128
129static gboolean
130download_requested_asynch_cb(WebKitWebView* web_view,
131                             WebKitDownload* download,
132                             gboolean* beenThere)
133{
134    handle_download_requested_cb(download, beenThere, TRUE);
135    return TRUE;
136}
137
138static void
139test_webkit_download_perform(gboolean asynch)
140{
141    WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
142    GCallback downloadRequestCallback = NULL;
143
144    g_object_ref_sink(G_OBJECT(webView));
145
146    g_signal_connect(webView, "navigation-policy-decision-requested",
147                     G_CALLBACK(navigation_policy_decision_requested_cb),
148                     NULL);
149
150    if (asynch)
151        downloadRequestCallback = G_CALLBACK(download_requested_asynch_cb);
152    else
153        downloadRequestCallback = G_CALLBACK(download_requested_cb);
154
155    gboolean beenThere = FALSE;
156    g_signal_connect(webView, "download-requested",
157                     downloadRequestCallback, &beenThere);
158
159    /* Preparation; FIXME: we should move this code to a test
160     * utilities file, because we have a very similar one in
161     * testwebframe.c */
162    GError *error = NULL;
163    gchar* filename;
164    int fd = g_file_open_tmp("webkit-testwebdownload-XXXXXX", &filename, &error);
165    close(fd);
166
167    if (error)
168        g_critical("Failed to open a temporary file for writing: %s.", error->message);
169
170    if (g_unlink(filename) == -1)
171        g_critical("Failed to delete the temporary file: %s.", g_strerror(errno));
172
173    theDownload = NULL;
174    temporaryFilename = filename;
175
176    loop = g_main_loop_new(NULL, TRUE);
177    webkit_web_view_load_uri(webView, "http://gnome.org/");
178    g_main_loop_run(loop);
179
180    g_assert_cmpint(beenThere, ==, TRUE);
181
182    g_assert_cmpint(g_file_test(temporaryFilename, G_FILE_TEST_IS_REGULAR), ==, TRUE);
183
184    g_unlink(temporaryFilename);
185    g_free(temporaryFilename);
186    temporaryFilename = NULL;
187
188    g_main_loop_unref(loop);
189    g_object_unref(webView);
190}
191
192static void
193test_webkit_download_synch(void)
194{
195    test_webkit_download_perform(FALSE);
196}
197
198static void
199test_webkit_download_asynch(void)
200{
201    test_webkit_download_perform(TRUE);
202}
203
204static gboolean mime_type_policy_decision_requested_cb(WebKitWebView* view, WebKitWebFrame* frame,
205                                                       WebKitNetworkRequest* request, const char* mime_type,
206                                                       WebKitWebPolicyDecision* decision, gpointer data)
207{
208    webkit_web_policy_decision_download(decision);
209    return TRUE;
210}
211
212static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
213{
214    if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
215        webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
216        g_main_loop_quit(loop);
217}
218
219static void
220test_webkit_download_data(void)
221{
222    gboolean beenThere = FALSE;
223    WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
224    g_object_ref_sink(webView);
225
226    g_signal_connect(webView, "download-requested",
227                     G_CALLBACK(download_requested_cb),
228                     &beenThere);
229
230    g_signal_connect(webView, "notify::load-status",
231                     G_CALLBACK(idle_quit_loop_cb),
232                     NULL);
233
234    g_signal_connect(webView, "mime-type-policy-decision-requested",
235                     G_CALLBACK(mime_type_policy_decision_requested_cb),
236                     NULL);
237
238    loop = g_main_loop_new(NULL, TRUE);
239
240    /* We're testing for a crash, so just not crashing is a pass */
241    webkit_web_view_load_uri(webView, "data:application/octect-stream,");
242    g_main_loop_run(loop);
243
244    g_assert_cmpint(beenThere, ==, TRUE);
245
246    g_main_loop_unref(loop);
247    g_object_unref(webView);
248}
249
250static void notifyDownloadStatusCallback(GObject *object, GParamSpec *pspec, gpointer data)
251{
252    WebKitDownload *download = WEBKIT_DOWNLOAD(object);
253    WebKitNetworkResponse *response = webkit_download_get_network_response(download);
254    SoupMessage *message = webkit_network_response_get_message(response);
255
256    switch (webkit_download_get_status(download)) {
257    case WEBKIT_DOWNLOAD_STATUS_ERROR:
258        g_assert_cmpint(message->status_code, ==, 404);
259        g_main_loop_quit(loop);
260        break;
261    case WEBKIT_DOWNLOAD_STATUS_FINISHED:
262    case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
263        g_assert_not_reached();
264        break;
265    default:
266        break;
267    }
268}
269
270static void serverCallback(SoupServer *server, SoupMessage *message, const char *path, GHashTable *query, SoupClientContext *context, gpointer userData)
271{
272    if (message->method != SOUP_METHOD_GET) {
273        soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
274        return;
275    }
276
277    soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
278    soup_message_body_complete(message->response_body);
279}
280
281static void test_webkit_download_not_found(void)
282{
283    SoupServer *server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
284    soup_server_run_async(server);
285    soup_server_add_handler(server, NULL, serverCallback, NULL, NULL);
286    SoupURI *baseURI = soup_uri_new("http://127.0.0.1/");
287    soup_uri_set_port(baseURI, soup_server_get_port(server));
288
289    SoupURI *uri = soup_uri_new_with_base(baseURI, "/foo");
290    char *uriString = soup_uri_to_string(uri, FALSE);
291    soup_uri_free(uri);
292
293    loop = g_main_loop_new(NULL, TRUE);
294    WebKitNetworkRequest *request = webkit_network_request_new(uriString);
295    g_free (uriString);
296    WebKitDownload *download = webkit_download_new(request);
297    g_object_unref(request);
298
299    webkit_download_set_destination_uri(download, "file:///tmp/foo");
300    g_signal_connect(download, "notify::status", G_CALLBACK(notifyDownloadStatusCallback), NULL);
301
302    webkit_download_start(download);
303    g_main_loop_run(loop);
304
305    g_object_unref(download);
306    g_main_loop_unref(loop);
307    soup_uri_free(baseURI);
308    g_object_unref(server);
309}
310
311int main(int argc, char** argv)
312{
313    gtk_test_init(&argc, &argv, NULL);
314
315    g_test_bug_base("https://bugs.webkit.org/");
316    g_test_add_func("/webkit/download/create", test_webkit_download_create);
317    g_test_add_func("/webkit/download/synch", test_webkit_download_synch);
318    g_test_add_func("/webkit/download/asynch", test_webkit_download_asynch);
319    g_test_add_func("/webkit/download/data", test_webkit_download_data);
320    g_test_add_func("/webkit/download/not-found", test_webkit_download_not_found);
321    return g_test_run ();
322}
323