| Differences between
and this patch
- a/WebCore/platform/network/ResourceHandleInternal.h -4 / +13 lines
Lines 46-51 a/WebCore/platform/network/ResourceHandleInternal.h_sec1
46
#endif
46
#endif
47
47
48
#if USE(SOUP)
48
#if USE(SOUP)
49
#include "soup-request.h"
50
#include "soup-requester.h"
51
#include <GRefPtr.h>
49
#include <libsoup/soup.h>
52
#include <libsoup/soup.h>
50
class Frame;
53
class Frame;
51
#endif
54
#endif
Lines 114-127 namespace WebCore { a/WebCore/platform/network/ResourceHandleInternal.h_sec2
114
#if USE(SOUP)
117
#if USE(SOUP)
115
            , m_msg(0)
118
            , m_msg(0)
116
            , m_cancelled(false)
119
            , m_cancelled(false)
117
            , m_gfile(0)
120
            , m_soupRequest(0)
121
            , m_requester(0)
118
            , m_inputStream(0)
122
            , m_inputStream(0)
119
            , m_cancellable(0)
123
            , m_cancellable(0)
120
            , m_buffer(0)
124
            , m_buffer(0)
121
            , m_bufferSize(0)
122
            , m_total(0)
125
            , m_total(0)
123
            , m_idleHandler(0)
126
            , m_idleHandler(0)
124
            , m_frame(0)
127
            , m_frame(0)
128
            , m_gotChunkHandler(0)
125
#endif
129
#endif
126
#if PLATFORM(QT)
130
#if PLATFORM(QT)
127
            , m_job(0)
131
            , m_job(0)
Lines 139-144 namespace WebCore { a/WebCore/platform/network/ResourceHandleInternal.h_sec3
139
            m_user = url.user();
143
            m_user = url.user();
140
            m_pass = url.pass();
144
            m_pass = url.pass();
141
            m_firstRequest.removeCredentials();
145
            m_firstRequest.removeCredentials();
146
#if USE(SOUP)
147
            m_requester = soup_requester_new();
148
#endif
142
        }
149
        }
143
        
150
        
144
        ~ResourceHandleInternal();
151
        ~ResourceHandleInternal();
Lines 196-208 namespace WebCore { a/WebCore/platform/network/ResourceHandleInternal.h_sec4
196
        SoupMessage* m_msg;
203
        SoupMessage* m_msg;
197
        ResourceResponse m_response;
204
        ResourceResponse m_response;
198
        bool m_cancelled;
205
        bool m_cancelled;
199
        GFile* m_gfile;
206
        PlatformRefPtr<SoupRequest> m_soupRequest;
207
        PlatformRefPtr<SoupRequester> m_requester;
200
        GInputStream* m_inputStream;
208
        GInputStream* m_inputStream;
201
        GCancellable* m_cancellable;
209
        GCancellable* m_cancellable;
202
        char* m_buffer;
210
        char* m_buffer;
203
        gsize m_bufferSize, m_total;
211
        gsize m_total;
204
        guint m_idleHandler;
212
        guint m_idleHandler;
205
        Frame* m_frame;
213
        Frame* m_frame;
214
        gulong m_gotChunkHandler;
206
#endif
215
#endif
207
#if PLATFORM(QT)
216
#if PLATFORM(QT)
208
        QNetworkReplyHandler* m_job;
217
        QNetworkReplyHandler* m_job;
- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp -249 / +221 lines
Lines 45-52 a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec1
45
#include "ResourceHandleInternal.h"
45
#include "ResourceHandleInternal.h"
46
#include "ResourceResponse.h"
46
#include "ResourceResponse.h"
47
#include "SharedBuffer.h"
47
#include "SharedBuffer.h"
48
#include "soup-request-http.h"
48
#include "TextEncoding.h"
49
#include "TextEncoding.h"
49
50
#include <errno.h>
50
#include <errno.h>
51
#include <fcntl.h>
51
#include <fcntl.h>
52
#include <gio/gio.h>
52
#include <gio/gio.h>
Lines 58-63 a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec2
58
58
59
namespace WebCore {
59
namespace WebCore {
60
60
61
#define READ_BUFFER_SIZE 8192
62
61
class WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
63
class WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
62
public:
64
public:
63
    WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);
65
    WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);
Lines 120-127 void WebCoreSynchronousLoader::run() a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec3
120
        g_main_loop_run(m_mainLoop);
122
        g_main_loop_run(m_mainLoop);
121
}
123
}
122
124
123
static void cleanupGioOperation(ResourceHandle* handle, bool isDestroying);
125
static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying);
124
static bool startData(ResourceHandle* handle, String urlString);
126
static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer);
127
static void readCallback(GObject* source, GAsyncResult* res, gpointer);
128
static void closeCallback(GObject* source, GAsyncResult* res, gpointer);
125
static bool startGio(ResourceHandle* handle, KURL url);
129
static bool startGio(ResourceHandle* handle, KURL url);
126
130
127
ResourceHandleInternal::~ResourceHandleInternal()
131
ResourceHandleInternal::~ResourceHandleInternal()
Lines 131-136 ResourceHandleInternal::~ResourceHandleInternal() a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec4
131
        m_msg = 0;
135
        m_msg = 0;
132
    }
136
    }
133
137
138
    if (m_soupRequest)
139
        g_object_set_data(G_OBJECT(m_soupRequest.get()), "webkit-resource", 0);
140
134
    if (m_idleHandler) {
141
    if (m_idleHandler) {
135
        g_source_remove(m_idleHandler);
142
        g_source_remove(m_idleHandler);
136
        m_idleHandler = 0;
143
        m_idleHandler = 0;
Lines 143-149 ResourceHandle::~ResourceHandle() a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec5
143
        g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
150
        g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
144
                                             0, 0, 0, 0, this);
151
                                             0, 0, 0, 0, this);
145
152
146
    cleanupGioOperation(this, true);
153
    cleanupSoupRequestOperation(this, true);
147
}
154
}
148
155
149
void ResourceHandle::prepareForURL(const KURL &url)
156
void ResourceHandle::prepareForURL(const KURL &url)
Lines 185-193 static void restartedCallback(SoupMessage* msg, gpointer data) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec6
185
    if (d->m_cancelled)
192
    if (d->m_cancelled)
186
        return;
193
        return;
187
194
188
    char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
195
    GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(msg), false));
189
    String location = String(uri);
196
    String location = String::fromUTF8(uri.get());
190
    g_free(uri);
191
    KURL newURL = KURL(handle->firstRequest().url(), location);
197
    KURL newURL = KURL(handle->firstRequest().url(), location);
192
198
193
    ResourceRequest request = handle->firstRequest();
199
    ResourceRequest request = handle->firstRequest();
Lines 293-342 static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec7
293
        return;
299
        return;
294
300
295
    client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
301
    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
302
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());
340
}
303
}
341
304
342
// parseDataUrl() is taken from the CURL http backend.
305
// parseDataUrl() is taken from the CURL http backend.
Lines 364-370 static gboolean parseDataUrl(gpointer callbackData) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec8
364
    }
327
    }
365
328
366
    String mediaType = url.substring(5, index - 5);
329
    String mediaType = url.substring(5, index - 5);
367
    String data = url.substring(index + 1);
368
330
369
    bool isBase64 = mediaType.endsWith(";base64", false);
331
    bool isBase64 = mediaType.endsWith(";base64", false);
370
    if (isBase64)
332
    if (isBase64)
Lines 381-387 static gboolean parseDataUrl(gpointer callbackData) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec9
381
    response.setMimeType(mimeType);
343
    response.setMimeType(mimeType);
382
344
383
    if (isBase64) {
345
    if (isBase64) {
384
        data = decodeURLEscapeSequences(data);
385
        response.setTextEncodingName(charset);
346
        response.setTextEncodingName(charset);
386
        client->didReceiveResponse(handle, response);
347
        client->didReceiveResponse(handle, response);
387
348
Lines 390-421 static gboolean parseDataUrl(gpointer callbackData) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec10
390
        // out in either of those cases.
351
        // out in either of those cases.
391
        if (d->m_cancelled || !handle->client())
352
        if (d->m_cancelled || !handle->client())
392
            return false;
353
            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 {
354
    } else {
403
        // We have to convert to UTF-16 early due to limitations in KURL
355
        // We have to convert to UTF-16 early due to limitations in KURL
404
        data = decodeURLEscapeSequences(data, TextEncoding(charset));
405
        response.setTextEncodingName("UTF-16");
356
        response.setTextEncodingName("UTF-16");
406
        client->didReceiveResponse(handle, response);
357
        client->didReceiveResponse(handle, response);
407
358
408
        if (d->m_cancelled || !handle->client())
359
        if (d->m_cancelled || !handle->client())
409
            return false;
360
            return false;
410
411
        if (data.length() > 0)
412
            client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
413
    }
361
    }
414
362
415
    if (d->m_cancelled || !handle->client())
363
    if (d->m_cancelled || !handle->client())
416
        return false;
364
        return false;
417
365
418
    client->didFinishLoading(handle);
366
    SoupSession* session = handle->defaultSession();
367
    GOwnPtr<GError> error;
368
    d->m_soupRequest = soup_requester_request(d->m_requester.get(), handle->firstRequest().url().string().utf8().data(), session, &error.outPtr());
369
    if (error)
370
        return false;
371
372
    GInputStream* in = soup_request_send(d->m_soupRequest.get(), 0, &error.outPtr());
373
    if (error)
374
        return false;
375
376
    d->m_inputStream = in;
377
    d->m_buffer = static_cast<char*>(g_malloc(READ_BUFFER_SIZE));
378
    d->m_total = 0;
379
380
    g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", handle);
381
    handle->ref();
382
383
    d->m_cancellable = g_cancellable_new();
384
    g_input_stream_read_async(d->m_inputStream, d->m_buffer, READ_BUFFER_SIZE,
385
                              G_PRIORITY_DEFAULT, d->m_cancellable,
386
                              readCallback, (isBase64) ? 0 : GINT_TO_POINTER(1));
419
387
420
    return false;
388
    return false;
421
}
389
}
Lines 469-474 static void ensureSessionIsInitialized(SoupSession* session) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec11
469
    g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
437
    g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
470
}
438
}
471
439
440
static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying = false)
441
{
442
    ResourceHandleInternal* d = handle->getInternal();
443
444
    if (d->m_soupRequest) {
445
        g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", 0);
446
        d->m_soupRequest.clear();
447
    }
448
449
    if (d->m_cancellable) {
450
        g_object_unref(d->m_cancellable);
451
        d->m_cancellable = 0;
452
    }
453
454
    if (d->m_inputStream) {
455
        g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", 0);
456
        g_object_unref(d->m_inputStream);
457
        d->m_inputStream = 0;
458
    }
459
460
    if (d->m_buffer) {
461
        g_free(d->m_buffer);
462
        d->m_buffer = 0;
463
    }
464
465
    if (!isDestroying)
466
        handle->deref();
467
}
468
469
static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer userData)
470
{
471
    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
472
    if (!handle)
473
        return;
474
475
    ResourceHandleInternal* d = handle->getInternal();
476
    ResourceHandleClient* client = handle->client();
477
478
    if (d->m_gotChunkHandler) {
479
        // No need to call gotChunkHandler anymore. Received data will
480
        // be reported by readCallback
481
        if (g_signal_handler_is_connected(d->m_msg, d->m_gotChunkHandler))
482
            g_signal_handler_disconnect(d->m_msg, d->m_gotChunkHandler);
483
    }
484
485
    if (d->m_cancelled || !client) {
486
        cleanupSoupRequestOperation(handle.get());
487
        return;
488
    }
489
490
    GOwnPtr<GError> error;
491
    GInputStream* in = soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
492
493
    if (error) {
494
        if (d->m_msg && SOUP_STATUS_IS_TRANSPORT_ERROR(d->m_msg->status_code)) {
495
            SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
496
            GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
497
            ResourceError resourceError(g_quark_to_string(SOUP_HTTP_ERROR),
498
                                        d->m_msg->status_code,
499
                                        uriStr.get(),
500
                                        String::fromUTF8(d->m_msg->reason_phrase));
501
            cleanupSoupRequestOperation(handle.get());
502
            client->didFail(handle.get(), resourceError);
503
            return;
504
        }
505
506
        if (error->domain == G_IO_ERROR) {
507
            SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
508
            GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
509
            ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
510
                                        error->code,
511
                                        uriStr.get(),
512
                                        error ? String::fromUTF8(error->message) : String());
513
            cleanupSoupRequestOperation(handle.get());
514
            client->didFail(handle.get(), resourceError);
515
            return;
516
        }
517
518
        if (d->m_msg && d->m_msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
519
            fillResponseFromMessage(d->m_msg, &d->m_response);
520
            client->didReceiveResponse(handle.get(), d->m_response);
521
522
            // WebCore might have cancelled the job in the while
523
            if (d->m_cancelled)
524
                return;
525
526
            if (d->m_msg->response_body->data)
527
                client->didReceiveData(handle.get(), d->m_msg->response_body->data, d->m_msg->response_body->length, true);
528
        }
529
530
        // didReceiveData above might have cancelled it
531
        if (d->m_cancelled || !client) {
532
          cleanupSoupRequestOperation(handle.get());
533
          return;
534
        }
535
536
        client->didFinishLoading(handle.get());
537
        return;
538
    }
539
540
    if (d->m_cancelled) {
541
        cleanupSoupRequestOperation(handle.get());
542
        return;
543
    }
544
545
    d->m_inputStream = in;
546
    d->m_buffer = static_cast<char*>(g_malloc(READ_BUFFER_SIZE));
547
    d->m_total = 0;
548
549
    // readCallback needs it
550
    g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", handle.get());
551
552
    // We need to check if it's a file: URL and if it is a regular
553
    // file as it could be a directory. In that case Soup properly
554
    // returns a stream whose content is a HTML with a list of files
555
    // in the directory
556
    if (equalIgnoringCase(handle->firstRequest().url().protocol(), "file")
557
        && G_IS_FILE_INPUT_STREAM(in)) {
558
        ResourceResponse response;
559
560
        response.setURL(handle->firstRequest().url());
561
        response.setMimeType(soup_request_get_content_type(d->m_soupRequest.get()));
562
        response.setExpectedContentLength(soup_request_get_content_length(d->m_soupRequest.get()));
563
        client->didReceiveResponse(handle.get(), response);
564
565
        if (d->m_cancelled) {
566
            cleanupSoupRequestOperation(handle.get());
567
            return;
568
        }
569
    }
570
571
    g_input_stream_read_async(d->m_inputStream, d->m_buffer, READ_BUFFER_SIZE,
572
                              G_PRIORITY_DEFAULT, d->m_cancellable,
573
                              readCallback, 0);
574
}
575
472
static bool startHttp(ResourceHandle* handle)
576
static bool startHttp(ResourceHandle* handle)
473
{
577
{
474
    ASSERT(handle);
578
    ASSERT(handle);
Lines 483-489 static bool startHttp(ResourceHandle* handle) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec12
483
    url.removeFragmentIdentifier();
587
    url.removeFragmentIdentifier();
484
    request.setURL(url);
588
    request.setURL(url);
485
589
486
    d->m_msg = request.toSoupMessage();
590
    GOwnPtr<GError> error;
591
    d->m_soupRequest = soup_requester_request(d->m_requester.get(), url.string().utf8().data(), session, &error.outPtr());
592
    if (error)
593
        return false;
594
595
    g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
596
597
    d->m_msg = soup_request_http_get_message(SOUP_REQUEST_HTTP(d->m_soupRequest.get()));
598
    request.updateSoupMessage(d->m_msg);
599
487
    if (!d->m_msg)
600
    if (!d->m_msg)
488
        return false;
601
        return false;
489
602
Lines 493-499 static bool startHttp(ResourceHandle* handle) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec13
493
    g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), handle);
606
    g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), handle);
494
    g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
607
    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);
608
    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);
609
    d->m_gotChunkHandler = g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
497
610
498
#ifdef HAVE_LIBSOUP_2_29_90
611
#ifdef HAVE_LIBSOUP_2_29_90
499
    String firstPartyString = request.firstPartyForCookies().string();
612
    String firstPartyString = request.firstPartyForCookies().string();
Lines 502-508 static bool startHttp(ResourceHandle* handle) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec14
502
        soup_message_set_first_party(d->m_msg, firstParty.get());
615
        soup_message_set_first_party(d->m_msg, firstParty.get());
503
    }
616
    }
504
#endif
617
#endif
505
    g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle));
506
618
507
    FormData* httpBody = d->m_firstRequest.httpBody();
619
    FormData* httpBody = d->m_firstRequest.httpBody();
508
    if (httpBody && !httpBody->isEmpty()) {
620
    if (httpBody && !httpBody->isEmpty()) {
Lines 532-543 static bool startHttp(ResourceHandle* handle) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec15
532
                     * mapping for uploaded files code inspired by technique used in
644
                     * mapping for uploaded files code inspired by technique used in
533
                     * libsoup's simple-httpd test
645
                     * libsoup's simple-httpd test
534
                     */
646
                     */
535
                    GError* error = 0;
647
                    GOwnPtr<GError> error;
536
                    CString fileName = fileSystemRepresentation(element.m_filename);
648
                    CString fileName = fileSystemRepresentation(element.m_filename);
537
                    GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error);
649
                    GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
538
650
539
                    if (error) {
651
                    if (error) {
540
                        g_error_free(error);
541
                        g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
652
                        g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
542
                                                             0, 0, 0, 0, handle);
653
                                                             0, 0, 0, 0, handle);
543
                        g_object_unref(d->m_msg);
654
                        g_object_unref(d->m_msg);
Lines 569-579 static bool startHttp(ResourceHandle* handle) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec16
569
    if (!soup_message_headers_get_one(d->m_msg->request_headers, "Accept"))
680
    if (!soup_message_headers_get_one(d->m_msg->request_headers, "Accept"))
570
        soup_message_headers_append(d->m_msg->request_headers, "Accept", "*/*");
681
        soup_message_headers_append(d->m_msg->request_headers, "Accept", "*/*");
571
682
572
    // Balanced in ResourceHandleInternal's destructor; we need to
683
    d->m_cancellable = g_cancellable_new();
573
    // keep our own ref, because after queueing the message, the
684
    soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable, sendRequestCallback, 0);
574
    // session owns the initial reference.
575
    g_object_ref(d->m_msg);
576
    soup_session_queue_message(session, d->m_msg, finishedCallback, handle);
577
685
578
    return true;
686
    return true;
579
}
687
}
Lines 667-704 void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec17
667
    syncLoader.run();
775
    syncLoader.run();
668
}
776
}
669
777
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
702
static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
778
static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
703
{
779
{
704
    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
780
    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
Lines 709-715 static void closeCallback(GObject* source, GAsyncResult* res, gpointer) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec18
709
    ResourceHandleClient* client = handle->client();
785
    ResourceHandleClient* client = handle->client();
710
786
711
    g_input_stream_close_finish(d->m_inputStream, res, 0);
787
    g_input_stream_close_finish(d->m_inputStream, res, 0);
712
    cleanupGioOperation(handle.get());
788
    cleanupSoupRequestOperation(handle.get());
713
789
714
    // The load may have been cancelled, the client may have been
790
    // The load may have been cancelled, the client may have been
715
    // destroyed already. In such cases calling didFinishLoading is a
791
    // destroyed already. In such cases calling didFinishLoading is a
Lines 720-751 static void closeCallback(GObject* source, GAsyncResult* res, gpointer) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec19
720
    client->didFinishLoading(handle.get());
796
    client->didFinishLoading(handle.get());
721
}
797
}
722
798
723
static void readCallback(GObject* source, GAsyncResult* res, gpointer)
799
static void readCallback(GObject* source, GAsyncResult* res, gpointer data)
724
{
800
{
725
    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
801
    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
726
    if (!handle)
802
    if (!handle)
727
        return;
803
        return;
728
804
805
    bool convertToUTF16 = static_cast<bool>(data);
729
    ResourceHandleInternal* d = handle->getInternal();
806
    ResourceHandleInternal* d = handle->getInternal();
730
    ResourceHandleClient* client = handle->client();
807
    ResourceHandleClient* client = handle->client();
731
808
732
    if (d->m_cancelled || !client) {
809
    if (d->m_cancelled || !client) {
733
        cleanupGioOperation(handle.get());
810
        cleanupSoupRequestOperation(handle.get());
734
        return;
811
        return;
735
    }
812
    }
736
813
737
    GError* error = 0;
814
    GOwnPtr<GError> error;
738
815
739
    gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error);
816
    gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error.outPtr());
740
    if (error) {
817
    if (error) {
741
        char* uri = g_file_get_uri(d->m_gfile);
818
        SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
819
        GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
742
        ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
820
        ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
743
                                    error->code,
821
                                    error->code,
744
                                    uri,
822
                                    uriStr.get(),
745
                                    error ? String::fromUTF8(error->message) : String());
823
                                    error ? String::fromUTF8(error->message) : String());
746
        g_free(uri);
824
        cleanupSoupRequestOperation(handle.get());
747
        g_error_free(error);
748
        cleanupGioOperation(handle.get());
749
        client->didFail(handle.get(), resourceError);
825
        client->didFail(handle.get(), resourceError);
750
        return;
826
        return;
751
    }
827
    }
Lines 757-897 static void readCallback(GObject* source, GAsyncResult* res, gpointer) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec20
757
    }
833
    }
758
834
759
    d->m_total += bytesRead;
835
    d->m_total += bytesRead;
760
    client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
836
    if (G_LIKELY(!convertToUTF16))
761
837
        client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
762
    // didReceiveData may cancel the load, which may release the last reference.
838
    else {
763
    if (d->m_cancelled) {
839
        // We have to convert it to UTF-16 due to limitations in KURL
764
        cleanupGioOperation(handle.get());
840
        String data = String::fromUTF8(d->m_buffer, bytesRead);
765
        return;
841
        client->didReceiveData(handle.get(), reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
766
    }
842
    }
767
843
768
    g_input_stream_read_async(d->m_inputStream, d->m_buffer, d->m_bufferSize,
844
    // didReceiveData may cancel the load, which may release the last reference.
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
782
    if (d->m_cancelled || !client) {
845
    if (d->m_cancelled || !client) {
783
        cleanupGioOperation(handle.get());
846
        cleanupSoupRequestOperation(handle.get());
784
        return;
847
        return;
785
    }
848
    }
786
849
787
    GError* error = 0;
850
    g_input_stream_read_async(d->m_inputStream, d->m_buffer, READ_BUFFER_SIZE,
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,
851
                              G_PRIORITY_DEFAULT, d->m_cancellable,
810
                              readCallback, 0);
852
                              readCallback, data);
811
}
853
}
812
854
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
    response.setMimeType(g_file_info_get_content_type(info));
870
    response.setExpectedContentLength(g_file_info_get_size(info));
871
872
    GTimeVal tv;
873
    g_file_info_get_modification_time(info, &tv);
874
    response.setLastModifiedDate(tv.tv_sec);
875
876
    client->didReceiveResponse(handle.get(), response);
877
878
    if (d->m_cancelled) {
879
        cleanupGioOperation(handle.get());
880
        return;
881
    }
882
883
    g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable,
884
                      openCallback, 0);
885
}
886
static bool startGio(ResourceHandle* handle, KURL url)
855
static bool startGio(ResourceHandle* handle, KURL url)
887
{
856
{
888
    ASSERT(handle);
857
    ASSERT(handle);
889
858
890
    ResourceHandleInternal* d = handle->getInternal();
891
892
    if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST")
859
    if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST")
893
        return false;
860
        return false;
894
861
862
    CString urlStr;
863
    SoupSession* session = handle->defaultSession();
864
    ResourceHandleInternal* d = handle->getInternal();
865
895
    // GIO doesn't know how to handle refs and queries, so remove them
866
    // GIO doesn't know how to handle refs and queries, so remove them
896
    // TODO: use KURL.fileSystemPath after KURLGtk and FileSystemGtk are
867
    // TODO: use KURL.fileSystemPath after KURLGtk and FileSystemGtk are
897
    // using GIO internally, and providing URIs instead of file paths
868
    // using GIO internally, and providing URIs instead of file paths
Lines 904-926 static bool startGio(ResourceHandle* handle, KURL url) a/WebCore/platform/network/soup/ResourceHandleSoup.cpp_sec21
904
    // g_filename_from_uri (used internally by GFile) has problems
875
    // g_filename_from_uri (used internally by GFile) has problems
905
    // decoding strings with arbitrary percent signs
876
    // decoding strings with arbitrary percent signs
906
    if (url.isLocalFile())
877
    if (url.isLocalFile())
907
        d->m_gfile = g_file_new_for_path(url.prettyURL().utf8().data() + sizeof("file://") - 1);
878
        urlStr = url.prettyURL().utf8().data();
908
    else
879
    else
909
#endif
880
#endif
910
        d->m_gfile = g_file_new_for_uri(url.string().utf8().data());
881
        urlStr = url.string().utf8().data();
911
    g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", handle);
882
883
    GOwnPtr<GError> error;
884
    d->m_soupRequest = soup_requester_request(d->m_requester.get(), urlStr.data(), session, &error.outPtr());
885
    if (error)
886
        return false;
887
888
    g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
912
889
913
    // balanced by a deref() in cleanupGioOperation, which should always run
890
    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
914
    handle->ref();
891
    handle->ref();
915
892
916
    d->m_cancellable = g_cancellable_new();
893
    d->m_cancellable = g_cancellable_new();
917
    g_file_query_info_async(d->m_gfile,
894
    soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable, sendRequestCallback, 0);
918
                            G_FILE_ATTRIBUTE_STANDARD_TYPE ","
895
919
                            G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
920
                            G_FILE_ATTRIBUTE_STANDARD_SIZE,
921
                            G_FILE_QUERY_INFO_NONE,
922
                            G_PRIORITY_DEFAULT, d->m_cancellable,
923
                            queryInfoCallback, 0);
924
    return true;
896
    return true;
925
}
897
}
926
898
- a/WebCore/platform/network/soup/ResourceRequest.h +1 lines
Lines 67-72 namespace WebCore { a/WebCore/platform/network/soup/ResourceRequest.h_sec1
67
            updateFromSoupMessage(soupMessage);
67
            updateFromSoupMessage(soupMessage);
68
        }
68
        }
69
69
70
        void updateSoupMessage(SoupMessage* soupMessage) const;
70
        SoupMessage* toSoupMessage() const;
71
        SoupMessage* toSoupMessage() const;
71
        void updateFromSoupMessage(SoupMessage* soupMessage);
72
        void updateFromSoupMessage(SoupMessage* soupMessage);
72
73
- a/WebCore/platform/network/soup/ResourceRequestSoup.cpp -1 / +23 lines
Lines 33-38 using namespace std; a/WebCore/platform/network/soup/ResourceRequestSoup.cpp_sec1
33
33
34
namespace WebCore {
34
namespace WebCore {
35
35
36
void 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
}
58
36
SoupMessage* ResourceRequest::toSoupMessage() const
59
SoupMessage* ResourceRequest::toSoupMessage() const
37
{
60
{
38
    SoupMessage* soupMessage = soup_message_new(httpMethod().utf8().data(), url().string().utf8().data());
61
    SoupMessage* soupMessage = soup_message_new(httpMethod().utf8().data(), url().string().utf8().data());
39
- 

Return to Bug 44261