|
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 |
|