427static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying = false)
428{
429 ResourceHandleInternal* d = handle->getInternal();
430
431 if (d->m_soupRequest) {
432 g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", 0);
433 d->m_soupRequest.clear();
434 }
435
436 if (d->m_inputStream) {
437 g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", 0);
438 d->m_inputStream.clear();
439 }
440
441 if (d->m_cancellable)
442 d->m_cancellable.clear();
443
444 if (d->m_soupMsg)
445 d->m_soupMsg.clear();
446
447 if (d->m_buffer) {
448 g_free(d->m_buffer);
449 d->m_buffer = 0;
450 }
451
452 if (!isDestroying)
453 handle->deref();
454}
455
456static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer userData)
457{
458 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
459 if (!handle)
460 return;
461
462 ResourceHandleInternal* d = handle->getInternal();
463 ResourceHandleClient* client = handle->client();
464
465 if (d->m_gotChunkHandler) {
466 // No need to call gotChunkHandler anymore. Received data will
467 // be reported by readCallback
468 if (g_signal_handler_is_connected(d->m_soupMsg.get(), d->m_gotChunkHandler))
469 g_signal_handler_disconnect(d->m_soupMsg.get(), d->m_gotChunkHandler);
470 }
471
472 if (d->m_cancelled || !client) {
473 cleanupSoupRequestOperation(handle.get());
474 return;
475 }
476
477 GOwnPtr<GError> error;
478 GInputStream* in = webkit_soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
479
480 if (error) {
481 SoupMessage* soupMsg = d->m_soupMsg.get();
482 gboolean isTransportError = d->m_soupMsg && SOUP_STATUS_IS_TRANSPORT_ERROR(soupMsg->status_code);
483
484 if (isTransportError || (error->domain == G_IO_ERROR)) {
485 SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
486 GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
487 gint errorCode = isTransportError ? soupMsg->status_code : error->code;
488 const gchar* errorMsg = isTransportError ? soupMsg->reason_phrase : error->message;
489 const gchar* quarkStr = isTransportError ? g_quark_to_string(SOUP_HTTP_ERROR) : g_quark_to_string(G_IO_ERROR);
490 ResourceError resourceError(quarkStr, errorCode, uriStr.get(), String::fromUTF8(errorMsg));
491
492 cleanupSoupRequestOperation(handle.get());
493 client->didFail(handle.get(), resourceError);
494 return;
495 }
496
497 if (d->m_soupMsg && soupMsg->status_code == SOUP_STATUS_UNAUTHORIZED) {
498 fillResponseFromMessage(soupMsg, &d->m_response);
499 client->didReceiveResponse(handle.get(), d->m_response);
500
501 // WebCore might have cancelled the job in the while
502 if (d->m_cancelled)
503 return;
504
505 if (soupMsg->response_body->data)
506 client->didReceiveData(handle.get(), soupMsg->response_body->data, soupMsg->response_body->length, true);
507 }
508
509 // didReceiveData above might have cancelled it
510 if (d->m_cancelled || !client) {
511 cleanupSoupRequestOperation(handle.get());
512 return;
513 }
514
515 client->didFinishLoading(handle.get(), 0);
516 return;
517 }
518
519 if (d->m_cancelled) {
520 cleanupSoupRequestOperation(handle.get());
521 return;
522 }
523
524 d->m_inputStream = adoptPlatformRef(in);
525 d->m_buffer = static_cast<char*>(g_malloc(READ_BUFFER_SIZE));
526 d->m_total = 0;
527
528 // readCallback needs it
529 g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle.get());
530
531 // We need to check if it's a file: URL and if it is a regular
532 // file as it could be a directory. In that case Soup properly
533 // returns a stream whose content is a HTML with a list of files
534 // in the directory
535 if (equalIgnoringCase(handle->firstRequest().url().protocol(), "file")
536 && G_IS_FILE_INPUT_STREAM(in)) {
537 ResourceResponse response;
538
539 response.setURL(handle->firstRequest().url());
540 response.setMimeType(webkit_soup_request_get_content_type(d->m_soupRequest.get()));
541 response.setExpectedContentLength(webkit_soup_request_get_content_length(d->m_soupRequest.get()));
542 client->didReceiveResponse(handle.get(), response);
543
544 if (d->m_cancelled) {
545 cleanupSoupRequestOperation(handle.get());
546 return;
547 }
548 }
549
550 g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
551 G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, 0);
552}
553