Changeset 69589 in webkit


Ignore:
Timestamp:
Oct 12, 2010 10:59:30 AM (14 years ago)
Author:
commit-queue@webkit.org
Message:

2010-10-12 Sergio Villar Senin <svillar@igalia.com>

Reviewed by Martin Robinson.

[GTK] Add HTTP caching support
https://bugs.webkit.org/show_bug.cgi?id=44261

ResourceHandle's m_msg renamed to m_soupMsg and it's also now a PlatformRefPtr

  • webkit/webkitdownload.cpp: (webkit_download_new_with_handle): (webkit_download_start):
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/platform/network/ResourceHandleInternal.h

    r68371 r69589  
    4747
    4848#if USE(SOUP)
     49#include "soup-requester.h"
     50#include <GRefPtr.h>
    4951#include <libsoup/soup.h>
    5052class Frame;
     
    109111#endif
    110112#if USE(SOUP)
    111             , m_msg(0)
    112113            , m_cancelled(false)
    113             , m_gfile(0)
    114             , m_inputStream(0)
    115             , m_cancellable(0)
    116114            , m_buffer(0)
    117             , m_bufferSize(0)
    118115            , m_total(0)
    119116            , m_idleHandler(0)
     117            , m_gotChunkHandler(0)
    120118#endif
    121119#if PLATFORM(QT)
     
    134132            m_pass = url.pass();
    135133            m_firstRequest.removeCredentials();
     134#if USE(SOUP)
     135            m_requester = adoptPlatformRef(webkit_soup_requester_new());
     136#endif
    136137        }
    137138       
     
    186187#endif
    187188#if USE(SOUP)
    188         SoupMessage* m_msg;
     189        PlatformRefPtr<SoupMessage> m_soupMessage;
    189190        ResourceResponse m_response;
    190191        bool m_cancelled;
    191         GFile* m_gfile;
    192         GInputStream* m_inputStream;
    193         GCancellable* m_cancellable;
     192        PlatformRefPtr<WebKitSoupRequest> m_soupRequest;
     193        PlatformRefPtr<WebKitSoupRequester> m_requester;
     194        PlatformRefPtr<GInputStream> m_inputStream;
     195        PlatformRefPtr<GCancellable> m_cancellable;
    194196        char* m_buffer;
    195         gsize m_bufferSize, m_total;
     197        gsize m_total;
    196198        guint m_idleHandler;
    197199        RefPtr<NetworkingContext> m_context;
     200        gulong m_gotChunkHandler;
    198201#endif
    199202#if PLATFORM(QT)
  • trunk/WebCore/platform/network/soup/ResourceHandleSoup.cpp

    r68313 r69589  
    4646#include "ResourceResponse.h"
    4747#include "SharedBuffer.h"
     48#include "soup-request-http.h"
    4849#include "TextEncoding.h"
    49 
    5050#include <errno.h>
    5151#include <fcntl.h>
     
    5959namespace WebCore {
    6060
     61#define READ_BUFFER_SIZE 8192
     62
    6163class WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
    6264public:
     
    121123}
    122124
    123 static void cleanupGioOperation(ResourceHandle* handle, bool isDestroying);
    124 static bool startData(ResourceHandle* handle, String urlString);
    125 static bool startGio(ResourceHandle* handle, KURL url);
     125static void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying);
     126static void sendRequestCallback(GObject*, GAsyncResult*, gpointer);
     127static void readCallback(GObject*, GAsyncResult*, gpointer);
     128static void closeCallback(GObject*, GAsyncResult*, gpointer);
     129static bool startGio(ResourceHandle*, KURL);
    126130
    127131ResourceHandleInternal::~ResourceHandleInternal()
    128132{
    129     if (m_msg) {
    130         g_object_unref(m_msg);
    131         m_msg = 0;
    132     }
     133    if (m_soupRequest)
     134        g_object_set_data(G_OBJECT(m_soupRequest.get()), "webkit-resource", 0);
    133135
    134136    if (m_idleHandler) {
     
    140142ResourceHandle::~ResourceHandle()
    141143{
    142     if (d->m_msg)
    143         g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
    144                                              0, 0, 0, 0, this);
    145 
    146     cleanupGioOperation(this, true);
     144    cleanupSoupRequestOperation(this, true);
    147145}
    148146
     
    186184        return;
    187185
    188     char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
    189     String location = String(uri);
    190     g_free(uri);
     186    GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(msg), false));
     187    String location = String::fromUTF8(uri.get());
    191188    KURL newURL = KURL(handle->firstRequest().url(), location);
    192189
     
    214211    if (!firstPartyString.isEmpty()) {
    215212        GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
    216         soup_message_set_first_party(d->m_msg, firstParty.get());
     213        soup_message_set_first_party(d->m_soupMessage.get(), firstParty.get());
    217214    }
    218215#endif
     
    294291
    295292    client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
    296 }
    297 
    298 // Called at the end of the message, with all the necessary about the last informations.
    299 // Doesn't get called for redirects.
    300 static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data)
    301 {
    302     RefPtr<ResourceHandle> handle = adoptRef(static_cast<ResourceHandle*>(data));
    303     // TODO: maybe we should run this code even if there's no client?
    304     if (!handle)
    305         return;
    306 
    307     ResourceHandleInternal* d = handle->getInternal();
    308 
    309     ResourceHandleClient* client = handle->client();
    310     if (!client)
    311         return;
    312 
    313     if (d->m_cancelled)
    314         return;
    315 
    316     if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) {
    317         char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
    318         ResourceError error(g_quark_to_string(SOUP_HTTP_ERROR),
    319                             msg->status_code,
    320                             uri,
    321                             String::fromUTF8(msg->reason_phrase));
    322         g_free(uri);
    323         client->didFail(handle.get(), error);
    324         return;
    325     }
    326 
    327     if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
    328         fillResponseFromMessage(msg, &d->m_response);
    329         client->didReceiveResponse(handle.get(), d->m_response);
    330 
    331         // WebCore might have cancelled the job in the while
    332         if (d->m_cancelled)
    333             return;
    334 
    335         if (msg->response_body->data)
    336             client->didReceiveData(handle.get(), msg->response_body->data, msg->response_body->length, true);
    337     }
    338 
    339     client->didFinishLoading(handle.get(), 0);
    340 }
    341 
    342 // parseDataUrl() is taken from the CURL http backend.
     293
     294}
     295
    343296static gboolean parseDataUrl(gpointer callbackData)
    344297{
     
    365318
    366319    String mediaType = url.substring(5, index - 5);
    367     String data = url.substring(index + 1);
    368320
    369321    bool isBase64 = mediaType.endsWith(";base64", false);
     
    381333    response.setMimeType(mimeType);
    382334
    383     if (isBase64) {
    384         data = decodeURLEscapeSequences(data);
    385         response.setTextEncodingName(charset);
    386         client->didReceiveResponse(handle, response);
    387 
    388         // The load may be cancelled, and the client may be destroyed
    389         // by any of the client reporting calls, so we check, and bail
    390         // out in either of those cases.
    391         if (d->m_cancelled || !handle->client())
    392             return false;
    393 
    394         // Use the GLib Base64, since WebCore's decoder isn't
    395         // general-purpose and fails on Acid3 test 97 (whitespace).
    396         size_t outLength = 0;
    397         char* outData = 0;
    398         outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength));
    399         if (outData && outLength > 0)
    400             client->didReceiveData(handle, outData, outLength, 0);
    401         g_free(outData);
    402     } else {
    403         // We have to convert to UTF-16 early due to limitations in KURL
    404         data = decodeURLEscapeSequences(data, TextEncoding(charset));
    405         response.setTextEncodingName("UTF-16");
    406         client->didReceiveResponse(handle, response);
    407 
    408         if (d->m_cancelled || !handle->client())
    409             return false;
    410 
    411         if (data.length() > 0)
    412             client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
    413     }
    414 
     335    // For non base64 encoded data we have to convert to UTF-16 early
     336    // due to limitations in KURL
     337    response.setTextEncodingName(isBase64 ? charset : "UTF-16");
     338    client->didReceiveResponse(handle, response);
     339
     340    // The load may be cancelled, and the client may be destroyed
     341    // by any of the client reporting calls, so we check, and bail
     342    // out in either of those cases.
    415343    if (d->m_cancelled || !handle->client())
    416344        return false;
    417345
    418     client->didFinishLoading(handle, 0);
     346    SoupSession* session = handle->defaultSession();
     347    GOwnPtr<GError> error;
     348    d->m_soupRequest = adoptPlatformRef(webkit_soup_requester_request(d->m_requester.get(), handle->firstRequest().url().string().utf8().data(), session, &error.outPtr()));
     349    if (error) {
     350        d->m_soupRequest = 0;
     351        return false;
     352    }
     353
     354    d->m_inputStream = adoptPlatformRef(webkit_soup_request_send(d->m_soupRequest.get(), 0, &error.outPtr()));
     355    if (error) {
     356        d->m_inputStream = 0;
     357        return false;
     358    }
     359
     360    d->m_buffer = static_cast<char*>(g_slice_alloc0(READ_BUFFER_SIZE));
     361    d->m_total = 0;
     362
     363    g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle);
     364    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
     365    handle->ref();
     366
     367    d->m_cancellable = adoptPlatformRef(g_cancellable_new());
     368    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
     369                              d->m_cancellable.get(), readCallback, GINT_TO_POINTER(!isBase64));
    419370
    420371    return false;
     
    470421}
    471422
     423static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying = false)
     424{
     425    ResourceHandleInternal* d = handle->getInternal();
     426
     427    if (d->m_soupRequest) {
     428        g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", 0);
     429        d->m_soupRequest.clear();
     430    }
     431
     432    if (d->m_inputStream) {
     433        g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", 0);
     434        d->m_inputStream.clear();
     435    }
     436
     437    d->m_cancellable.clear();
     438
     439    if (d->m_soupMessage) {
     440        g_signal_handlers_disconnect_matched(d->m_soupMessage.get(), G_SIGNAL_MATCH_DATA,
     441                                             0, 0, 0, 0, handle);
     442        d->m_soupMessage.clear();
     443    }
     444
     445    if (d->m_buffer) {
     446        g_slice_free1(READ_BUFFER_SIZE, d->m_buffer);
     447        d->m_buffer = 0;
     448    }
     449
     450    if (!isDestroying)
     451        handle->deref();
     452}
     453
     454static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer userData)
     455{
     456    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
     457    if (!handle)
     458        return;
     459
     460    ResourceHandleInternal* d = handle->getInternal();
     461    ResourceHandleClient* client = handle->client();
     462
     463    if (d->m_gotChunkHandler) {
     464        // No need to call gotChunkHandler anymore. Received data will
     465        // be reported by readCallback
     466        if (g_signal_handler_is_connected(d->m_soupMessage.get(), d->m_gotChunkHandler))
     467            g_signal_handler_disconnect(d->m_soupMessage.get(), d->m_gotChunkHandler);
     468    }
     469
     470    if (d->m_cancelled || !client) {
     471        cleanupSoupRequestOperation(handle.get());
     472        return;
     473    }
     474
     475    GOwnPtr<GError> error;
     476    GInputStream* in = webkit_soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
     477
     478    if (error) {
     479        SoupMessage* soupMsg = d->m_soupMessage.get();
     480        gboolean isTransportError = d->m_soupMessage && SOUP_STATUS_IS_TRANSPORT_ERROR(soupMsg->status_code);
     481
     482        if (isTransportError || (error->domain == G_IO_ERROR)) {
     483            SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
     484            GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
     485            gint errorCode = isTransportError ? soupMsg->status_code : error->code;
     486            const gchar* errorMsg = isTransportError ? soupMsg->reason_phrase : error->message;
     487            const gchar* quarkStr = isTransportError ? g_quark_to_string(SOUP_HTTP_ERROR) : g_quark_to_string(G_IO_ERROR);
     488            ResourceError resourceError(quarkStr, errorCode, uriStr.get(), String::fromUTF8(errorMsg));
     489
     490            cleanupSoupRequestOperation(handle.get());
     491            client->didFail(handle.get(), resourceError);
     492            return;
     493        }
     494
     495        if (d->m_soupMessage && soupMessage->status_code == SOUP_STATUS_UNAUTHORIZED) {
     496            fillResponseFromMessage(soupMsg, &d->m_response);
     497            client->didReceiveResponse(handle.get(), d->m_response);
     498
     499            // WebCore might have cancelled the job in the while
     500            if (!d->m_cancelled && soupMsg->response_body->data)
     501                client->didReceiveData(handle.get(), soupMsg->response_body->data, soupMsg->response_body->length, true);
     502        }
     503
     504        // didReceiveData above might have cancelled it
     505        if (d->m_cancelled || !client) {
     506            cleanupSoupRequestOperation(handle.get());
     507            return;
     508        }
     509
     510        client->didFinishLoading(handle.get(), 0);
     511        return;
     512    }
     513
     514    if (d->m_cancelled) {
     515        cleanupSoupRequestOperation(handle.get());
     516        return;
     517    }
     518
     519    d->m_inputStream = adoptPlatformRef(in);
     520    d->m_buffer = static_cast<char*>(g_slice_alloc0(READ_BUFFER_SIZE));
     521    d->m_total = 0;
     522
     523    // readCallback needs it
     524    g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle.get());
     525
     526    // We need to check if it's a file: URL and if it is a regular
     527    // file as it could be a directory. In that case Soup properly
     528    // returns a stream whose content is a HTML with a list of files
     529    // in the directory
     530    if (equalIgnoringCase(handle->firstRequest().url().protocol(), "file")
     531        && G_IS_FILE_INPUT_STREAM(in)) {
     532        ResourceResponse response;
     533
     534        response.setURL(handle->firstRequest().url());
     535        response.setMimeType(webkit_soup_request_get_content_type(d->m_soupRequest.get()));
     536        response.setExpectedContentLength(webkit_soup_request_get_content_length(d->m_soupRequest.get()));
     537        client->didReceiveResponse(handle.get(), response);
     538
     539        if (d->m_cancelled) {
     540            cleanupSoupRequestOperation(handle.get());
     541            return;
     542        }
     543    }
     544
     545    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
     546                              G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, 0);
     547}
     548
    472549static bool startHttp(ResourceHandle* handle)
    473550{
     
    484561    request.setURL(url);
    485562
    486     d->m_msg = request.toSoupMessage();
    487     if (!d->m_msg)
    488         return false;
     563    GOwnPtr<GError> error;
     564    d->m_soupRequest = adoptPlatformRef(webkit_soup_requester_request(d->m_requester.get(), url.string().utf8().data(), session, &error.outPtr()));
     565    if (error) {
     566        d->m_soupRequest = 0;
     567        return false;
     568    }
     569
     570    g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
     571
     572    d->m_soupMessage = adoptPlatformRef(webkit_soup_request_http_get_message(WEBKIT_SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
     573    if (!d->m_soupMessage)
     574        return false;
     575
     576    SoupMessage* soupMessage = d->m_soupMessage.get();
     577    request.updateSoupMessage(soupMessage);
    489578
    490579    if (!handle->shouldContentSniff())
    491         soup_message_disable_feature(d->m_msg, SOUP_TYPE_CONTENT_SNIFFER);
    492 
    493     g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), handle);
    494     g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
    495     g_signal_connect(d->m_msg, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle);
    496     g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
     580        soup_message_disable_feature(soupMessage, SOUP_TYPE_CONTENT_SNIFFER);
     581
     582    g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle);
     583    g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
     584    g_signal_connect(soupMessage, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle);
     585    d->m_gotChunkHandler = g_signal_connect(soupMessage, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
    497586
    498587#ifdef HAVE_LIBSOUP_2_29_90
     
    500589    if (!firstPartyString.isEmpty()) {
    501590        GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
    502         soup_message_set_first_party(d->m_msg, firstParty.get());
     591        soup_message_set_first_party(soupMessage, firstParty.get());
    503592    }
    504593#endif
    505     g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle));
    506594
    507595    FormData* httpBody = d->m_firstRequest.httpBody();
     
    513601            Vector<char> body;
    514602            httpBody->flatten(body);
    515             soup_message_set_request(d->m_msg, d->m_firstRequest.httpContentType().utf8().data(),
     603            soup_message_set_request(soupMessage, d->m_firstRequest.httpContentType().utf8().data(),
    516604                                     SOUP_MEMORY_COPY, body.data(), body.size());
    517605        } else {
     
    522610             * (think sftp://) files by using GIO?
    523611             */
    524             soup_message_body_set_accumulate(d->m_msg->request_body, FALSE);
     612            soup_message_body_set_accumulate(soupMessage->request_body, FALSE);
    525613            for (size_t i = 0; i < numElements; i++) {
    526614                const FormDataElement& element = httpBody->elements()[i];
    527615
    528616                if (element.m_type == FormDataElement::data)
    529                     soup_message_body_append(d->m_msg->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
     617                    soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
    530618                else {
    531619                    /*
     
    533621                     * libsoup's simple-httpd test
    534622                     */
    535                     GError* error = 0;
     623                    GOwnPtr<GError> error;
    536624                    CString fileName = fileSystemRepresentation(element.m_filename);
    537                     GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error);
     625                    GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
    538626
    539627                    if (error) {
    540                         g_error_free(error);
    541                         g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
     628                        g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA,
    542629                                                             0, 0, 0, 0, handle);
    543                         g_object_unref(d->m_msg);
    544                         d->m_msg = 0;
     630                        d->m_soupMessage.clear();
    545631
    546632                        return false;
     
    550636                                                                        g_mapped_file_get_length(fileMapping),
    551637                                                                        fileMapping,
    552 #if GLIB_CHECK_VERSION(2, 21, 3)
    553638                                                                        reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
    554 #else
    555                                                                         reinterpret_cast<GDestroyNotify>(g_mapped_file_free));
    556 #endif
    557                     soup_message_body_append_buffer(d->m_msg->request_body, soupBuffer);
     639                    soup_message_body_append_buffer(soupMessage->request_body, soupBuffer);
    558640                    soup_buffer_free(soupBuffer);
    559641                }
     
    562644    }
    563645
    564     // balanced by a deref() in finishedCallback, which should always run
     646    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
    565647    handle->ref();
    566648
    567649    // Make sure we have an Accept header for subresources; some sites
    568650    // want this to serve some of their subresources
    569     if (!soup_message_headers_get_one(d->m_msg->request_headers, "Accept"))
    570         soup_message_headers_append(d->m_msg->request_headers, "Accept", "*/*");
    571 
    572     // Balanced in ResourceHandleInternal's destructor; we need to
    573     // keep our own ref, because after queueing the message, the
    574     // session owns the initial reference.
    575     g_object_ref(d->m_msg);
    576     soup_session_queue_message(session, d->m_msg, finishedCallback, handle);
     651    if (!soup_message_headers_get_one(soupMessage->request_headers, "Accept"))
     652        soup_message_headers_append(soupMessage->request_headers, "Accept", "*/*");
     653
     654    d->m_cancellable = adoptPlatformRef(g_cancellable_new());
     655    webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
    577656
    578657    return true;
     
    581660bool ResourceHandle::start(NetworkingContext* context)
    582661{
    583     ASSERT(!d->m_msg);
     662    ASSERT(!d->m_soupMessage);
    584663
    585664    // The frame could be null if the ResourceHandle is not associated to any
     
    621700{
    622701    d->m_cancelled = true;
    623     if (d->m_msg)
    624         soup_session_cancel_message(defaultSession(), d->m_msg, SOUP_STATUS_CANCELLED);
     702    if (d->m_soupMessage)
     703        soup_session_cancel_message(defaultSession(), d->m_soupMessage.get(), SOUP_STATUS_CANCELLED);
    625704    else if (d->m_cancellable)
    626         g_cancellable_cancel(d->m_cancellable);
     705        g_cancellable_cancel(d->m_cancellable.get());
    627706}
    628707
     
    668747}
    669748
    670 // GIO-based loader
    671 
    672 static void cleanupGioOperation(ResourceHandle* handle, bool isDestroying = false)
    673 {
    674     ResourceHandleInternal* d = handle->getInternal();
    675 
    676     if (d->m_gfile) {
    677         g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", 0);
    678         g_object_unref(d->m_gfile);
    679         d->m_gfile = 0;
    680     }
    681 
    682     if (d->m_cancellable) {
    683         g_object_unref(d->m_cancellable);
    684         d->m_cancellable = 0;
    685     }
    686 
    687     if (d->m_inputStream) {
    688         g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", 0);
    689         g_object_unref(d->m_inputStream);
    690         d->m_inputStream = 0;
    691     }
    692 
    693     if (d->m_buffer) {
    694         g_free(d->m_buffer);
    695         d->m_buffer = 0;
    696     }
    697 
    698     if (!isDestroying)
    699         handle->deref();
    700 }
    701 
    702749static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
    703750{
     
    709756    ResourceHandleClient* client = handle->client();
    710757
    711     g_input_stream_close_finish(d->m_inputStream, res, 0);
    712     cleanupGioOperation(handle.get());
     758    g_input_stream_close_finish(d->m_inputStream.get(), res, 0);
     759    cleanupSoupRequestOperation(handle.get());
    713760
    714761    // The load may have been cancelled, the client may have been
     
    721768}
    722769
    723 static void readCallback(GObject* source, GAsyncResult* res, gpointer)
     770static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer data)
    724771{
    725772    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
     
    727774        return;
    728775
     776    bool convertToUTF16 = static_cast<bool>(data);
    729777    ResourceHandleInternal* d = handle->getInternal();
    730778    ResourceHandleClient* client = handle->client();
    731779
    732780    if (d->m_cancelled || !client) {
    733         cleanupGioOperation(handle.get());
    734         return;
    735     }
    736 
    737     GError* error = 0;
    738 
    739     gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error);
     781        cleanupSoupRequestOperation(handle.get());
     782        return;
     783    }
     784
     785    GOwnPtr<GError> error;
     786
     787    gssize bytesRead = g_input_stream_read_finish(d->m_inputStream.get(), asyncResult, &error.outPtr());
    740788    if (error) {
    741         char* uri = g_file_get_uri(d->m_gfile);
    742         ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
    743                                     error->code,
    744                                     uri,
     789        SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
     790        GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
     791        ResourceError resourceError(g_quark_to_string(G_IO_ERROR), error->code, uriStr.get(),
    745792                                    error ? String::fromUTF8(error->message) : String());
    746         g_free(uri);
    747         g_error_free(error);
    748         cleanupGioOperation(handle.get());
     793        cleanupSoupRequestOperation(handle.get());
    749794        client->didFail(handle.get(), resourceError);
    750795        return;
     
    752797
    753798    if (!bytesRead) {
    754         g_input_stream_close_async(d->m_inputStream, G_PRIORITY_DEFAULT,
     799        g_input_stream_close_async(d->m_inputStream.get(), G_PRIORITY_DEFAULT,
    755800                                   0, closeCallback, 0);
    756801        return;
     
    758803
    759804    d->m_total += bytesRead;
    760     client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
     805    if (G_LIKELY(!convertToUTF16))
     806        client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
     807    else {
     808        // We have to convert it to UTF-16 due to limitations in KURL
     809        String data = String::fromUTF8(d->m_buffer, bytesRead);
     810        client->didReceiveData(handle.get(), reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
     811    }
    761812
    762813    // didReceiveData may cancel the load, which may release the last reference.
    763     if (d->m_cancelled) {
    764         cleanupGioOperation(handle.get());
    765         return;
    766     }
    767 
    768     g_input_stream_read_async(d->m_inputStream, d->m_buffer, d->m_bufferSize,
    769                               G_PRIORITY_DEFAULT, d->m_cancellable,
    770                               readCallback, 0);
    771 }
    772 
    773 static void openCallback(GObject* source, GAsyncResult* res, gpointer)
    774 {
    775     RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
    776     if (!handle)
    777         return;
    778 
    779     ResourceHandleInternal* d = handle->getInternal();
    780     ResourceHandleClient* client = handle->client();
    781 
    782814    if (d->m_cancelled || !client) {
    783         cleanupGioOperation(handle.get());
    784         return;
    785     }
    786 
    787     GError* error = 0;
    788     GFileInputStream* in = g_file_read_finish(G_FILE(source), res, &error);
    789     if (error) {
    790         char* uri = g_file_get_uri(d->m_gfile);
    791         ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
    792                                     error->code,
    793                                     uri,
    794                                     error ? String::fromUTF8(error->message) : String());
    795         g_free(uri);
    796         g_error_free(error);
    797         cleanupGioOperation(handle.get());
    798         client->didFail(handle.get(), resourceError);
    799         return;
    800     }
    801 
    802     d->m_inputStream = G_INPUT_STREAM(in);
    803     d->m_bufferSize = 8192;
    804     d->m_buffer = static_cast<char*>(g_malloc(d->m_bufferSize));
    805     d->m_total = 0;
    806 
    807     g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", handle.get());
    808     g_input_stream_read_async(d->m_inputStream, d->m_buffer, d->m_bufferSize,
    809                               G_PRIORITY_DEFAULT, d->m_cancellable,
    810                               readCallback, 0);
    811 }
    812 
    813 static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
    814 {
    815     RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
    816     if (!handle)
    817         return;
    818 
    819     ResourceHandleInternal* d = handle->getInternal();
    820     ResourceHandleClient* client = handle->client();
    821 
    822     if (d->m_cancelled) {
    823         cleanupGioOperation(handle.get());
    824         return;
    825     }
    826 
    827     ResourceResponse response;
    828 
    829     char* uri = g_file_get_uri(d->m_gfile);
    830     response.setURL(KURL(KURL(), uri));
    831     g_free(uri);
    832 
    833     GError* error = 0;
    834     GFileInfo* info = g_file_query_info_finish(d->m_gfile, res, &error);
    835 
    836     if (error) {
    837         // FIXME: to be able to handle ftp URIs properly, we must
    838         // check if the error is G_IO_ERROR_NOT_MOUNTED, and if so,
    839         // call g_file_mount_enclosing_volume() to mount the ftp
    840         // server (and then keep track of the fact that we mounted it,
    841         // and set a timeout to unmount it later after it's been idle
    842         // for a while).
    843         char* uri = g_file_get_uri(d->m_gfile);
    844         ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
    845                                     error->code,
    846                                     uri,
    847                                     error ? String::fromUTF8(error->message) : String());
    848         g_free(uri);
    849         g_error_free(error);
    850         cleanupGioOperation(handle.get());
    851         client->didFail(handle.get(), resourceError);
    852         return;
    853     }
    854 
    855     if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) {
    856         // FIXME: what if the URI points to a directory? Should we
    857         // generate a listing? How? What do other backends do here?
    858         char* uri = g_file_get_uri(d->m_gfile);
    859         ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
    860                                     G_IO_ERROR_FAILED,
    861                                     uri,
    862                                     String());
    863         g_free(uri);
    864         cleanupGioOperation(handle.get());
    865         client->didFail(handle.get(), resourceError);
    866         return;
    867     }
    868 
    869     // According to http://library.gnome.org/devel/gio/stable/gio-GContentType.html
    870     // GContentType on Unix is the mime type, but not on Win32.
    871     GOwnPtr<gchar> mimeType(g_content_type_get_mime_type(g_file_info_get_content_type(info)));
    872     response.setMimeType(mimeType.get());
    873     response.setExpectedContentLength(g_file_info_get_size(info));
    874 
    875     GTimeVal tv;
    876     g_file_info_get_modification_time(info, &tv);
    877     response.setLastModifiedDate(tv.tv_sec);
    878 
    879     client->didReceiveResponse(handle.get(), response);
    880 
    881     if (d->m_cancelled) {
    882         cleanupGioOperation(handle.get());
    883         return;
    884     }
    885 
    886     g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable,
    887                       openCallback, 0);
    888 }
     815        cleanupSoupRequestOperation(handle.get());
     816        return;
     817    }
     818
     819    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
     820                              d->m_cancellable.get(), readCallback, data);
     821}
     822
    889823static bool startGio(ResourceHandle* handle, KURL url)
    890824{
    891825    ASSERT(handle);
    892826
    893     ResourceHandleInternal* d = handle->getInternal();
    894 
    895827    if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST")
    896828        return false;
     829
     830    SoupSession* session = handle->defaultSession();
     831    ResourceHandleInternal* d = handle->getInternal();
    897832
    898833    // GIO doesn't know how to handle refs and queries, so remove them
     
    902837    url.setQuery(String());
    903838    url.removePort();
    904 
    905 #if !OS(WINDOWS)
    906     // we avoid the escaping for local files, because
    907     // g_filename_from_uri (used internally by GFile) has problems
    908     // decoding strings with arbitrary percent signs
    909     if (url.isLocalFile())
    910         d->m_gfile = g_file_new_for_path(url.prettyURL().utf8().data() + sizeof("file://") - 1);
    911     else
    912 #endif
    913         d->m_gfile = g_file_new_for_uri(url.string().utf8().data());
    914     g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", handle);
    915 
    916     // balanced by a deref() in cleanupGioOperation, which should always run
     839    CString urlStr = url.string().utf8();
     840
     841    GOwnPtr<GError> error;
     842    d->m_soupRequest = adoptPlatformRef(webkit_soup_requester_request(d->m_requester.get(), urlStr.data(), session, &error.outPtr()));
     843    if (error) {
     844        d->m_soupRequest = 0;
     845        return false;
     846    }
     847
     848    g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
     849
     850    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
    917851    handle->ref();
    918852
    919     d->m_cancellable = g_cancellable_new();
    920     g_file_query_info_async(d->m_gfile,
    921                             G_FILE_ATTRIBUTE_STANDARD_TYPE ","
    922                             G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
    923                             G_FILE_ATTRIBUTE_STANDARD_SIZE,
    924                             G_FILE_QUERY_INFO_NONE,
    925                             G_PRIORITY_DEFAULT, d->m_cancellable,
    926                             queryInfoCallback, 0);
     853    d->m_cancellable = adoptPlatformRef(g_cancellable_new());
     854    webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
     855
    927856    return true;
    928857}
  • trunk/WebCore/platform/network/soup/ResourceRequest.h

    r68762 r69589  
    6868        }
    6969
     70        void updateSoupMessage(SoupMessage*) const;
    7071        SoupMessage* toSoupMessage() const;
    71         void updateFromSoupMessage(SoupMessage* soupMessage);
     72        void updateFromSoupMessage(SoupMessage*);
    7273
    7374        SoupMessageFlags soupMessageFlags() const { return m_soupFlags; }
  • trunk/WebCore/platform/network/soup/ResourceRequestSoup.cpp

    r56825 r69589  
    3333
    3434namespace WebCore {
     35
     36void ResourceRequest::updateSoupMessage(SoupMessage* soupMessage) const
     37{
     38    g_object_set(soupMessage, SOUP_MESSAGE_METHOD, httpMethod().utf8().data(), NULL);
     39
     40    const HTTPHeaderMap& headers = httpHeaderFields();
     41    SoupMessageHeaders* soupHeaders = soupMessage->request_headers;
     42    if (!headers.isEmpty()) {
     43        HTTPHeaderMap::const_iterator end = headers.end();
     44        for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it)
     45            soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
     46    }
     47
     48#ifdef HAVE_LIBSOUP_2_29_90
     49    String firstPartyString = firstPartyForCookies().string();
     50    if (!firstPartyString.isEmpty()) {
     51        GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
     52        soup_message_set_first_party(soupMessage, firstParty.get());
     53    }
     54#endif
     55
     56    soup_message_set_flags(soupMessage, m_soupFlags);
     57}
    3558
    3659SoupMessage* ResourceRequest::toSoupMessage() const
  • trunk/WebKit/gtk/ChangeLog

    r69444 r69589  
     12010-10-12  Sergio Villar Senin  <svillar@igalia.com>
     2
     3        Reviewed by Martin Robinson.
     4
     5        [GTK] Add HTTP caching support
     6        https://bugs.webkit.org/show_bug.cgi?id=44261
     7
     8        ResourceHandle's m_msg renamed to m_soupMsg and it's also now a PlatformRefPtr
     9
     10        * webkit/webkitdownload.cpp:
     11        (webkit_download_new_with_handle):
     12        (webkit_download_start):
     13
    1142010-10-09  Carlos Garcia Campos  <cgarcia@igalia.com>
    215
  • trunk/WebKit/gtk/webkit/webkitdownload.cpp

    r68040 r69589  
    420420
    421421    ResourceHandleInternal* d = handle->getInternal();
    422     if (d->m_msg)
    423         soup_session_pause_message(webkit_get_default_session(), d->m_msg);
     422    if (d->m_soupMessage)
     423        soup_session_pause_message(webkit_get_default_session(), d->m_soupMessage.get());
    424424
    425425    WebKitDownload* download = WEBKIT_DOWNLOAD(g_object_new(WEBKIT_TYPE_DOWNLOAD, "network-request", request, NULL));
     
    493493
    494494        ResourceHandleInternal* d = priv->resourceHandle->getInternal();
    495         if (d->m_msg)
    496             soup_session_unpause_message(webkit_get_default_session(), d->m_msg);
     495        if (d->m_soupMessage)
     496            soup_session_unpause_message(webkit_get_default_session(), d->m_soupMessage.get());
    497497    }
    498498
Note: See TracChangeset for help on using the changeset viewer.