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