COMMIT_MESSAGE (2/2)

 1WebKitGtk+ to use the new API from the imported SoupURILoader code
 2

WebCore/platform/network/ResourceHandleInternal.h

4646#endif
4747
4848#if USE(SOUP)
 49#include "soup-requester.h"
 50#include <GRefPtr.h>
4951#include <libsoup/soup.h>
5052class Frame;
5153#endif

@@namespace WebCore {
108110 , m_formDataStream(loader)
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)
122120 , m_job(0)

@@namespace WebCore {
133131 m_user = url.user();
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
138139 ~ResourceHandleInternal();

@@namespace WebCore {
185186 Vector<char> m_postBytes;
186187#endif
187188#if USE(SOUP)
188  SoupMessage* m_msg;
 189 PlatformRefPtr<SoupMessage> m_soupMsg;
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)
200203 QNetworkReplyHandler* m_job;

WebCore/platform/network/soup/ResourceHandleSoup.cpp

4545#include "ResourceHandleInternal.h"
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>
5252#include <gio/gio.h>

5858
5959namespace WebCore {
6060
 61#define READ_BUFFER_SIZE 8192
 62
6163class WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
6264public:
6365 WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);

@@void WebCoreSynchronousLoader::run()
120122 g_main_loop_run(m_mainLoop);
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) {
135137 g_source_remove(m_idleHandler);

@@ResourceHandleInternal::~ResourceHandleInternal()
139141
140142ResourceHandle::~ResourceHandle()
141143{
142  if (d->m_msg)
143  g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
 144 if (d->m_soupMsg)
 145 g_signal_handlers_disconnect_matched(d->m_soupMsg.get(), G_SIGNAL_MATCH_DATA,
144146 0, 0, 0, 0, this);
145147
146  cleanupGioOperation(this, true);
 148 cleanupSoupRequestOperation(this, true);
147149}
148150
149151void ResourceHandle::prepareForURL(const KURL &url)

@@static void restartedCallback(SoupMessage* msg, gpointer data)
185187 if (d->m_cancelled)
186188 return;
187189
188  char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
189  String location = String(uri);
190  g_free(uri);
 190 GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(msg), false));
 191 String location = String::fromUTF8(uri.get());
191192 KURL newURL = KURL(handle->firstRequest().url(), location);
192193
193194 ResourceRequest request = handle->firstRequest();

@@static void restartedCallback(SoupMessage* msg, gpointer data)
213214 String firstPartyString = request.firstPartyForCookies().string();
214215 if (!firstPartyString.isEmpty()) {
215216 GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
216  soup_message_set_first_party(d->m_msg, firstParty.get());
 217 soup_message_set_first_party(d->m_soupMsg.get(), firstParty.get());
217218 }
218219#endif
219220}

@@static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
293294 return;
294295
295296 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  }
338297
339  client->didFinishLoading(handle.get(), 0);
340298}
341299
342 // parseDataUrl() is taken from the CURL http backend.
343300static gboolean parseDataUrl(gpointer callbackData)
344301{
345302 ResourceHandle* handle = static_cast<ResourceHandle*>(callbackData);

@@static gboolean parseDataUrl(gpointer callbackData)
364321 }
365322
366323 String mediaType = url.substring(5, index - 5);
367  String data = url.substring(index + 1);
368324
369325 bool isBase64 = mediaType.endsWith(";base64", false);
370326 if (isBase64)

@@static gboolean parseDataUrl(gpointer callbackData)
380336 response.setURL(handle->firstRequest().url());
381337 response.setMimeType(mimeType);
382338
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  }
 339 // For non base64 encoded data we have to convert to UTF-16 early
 340 // due to limitations in KURL
 341 response.setTextEncodingName(isBase64 ? charset : "UTF-16");
 342 client->didReceiveResponse(handle, response);
414343
 344 // The load may be cancelled, and the client may be destroyed
 345 // by any of the client reporting calls, so we check, and bail
 346 // out in either of those cases.
415347 if (d->m_cancelled || !handle->client())
416348 return false;
417349
418  client->didFinishLoading(handle, 0);
 350 SoupSession* session = handle->defaultSession();
 351 GOwnPtr<GError> error;
 352 d->m_soupRequest = adoptPlatformRef(webkit_soup_requester_request(d->m_requester.get(), handle->firstRequest().url().string().utf8().data(), session, &error.outPtr()));
 353 if (error) {
 354 d->m_soupRequest = 0;
 355 return false;
 356 }
 357
 358 d->m_inputStream = adoptPlatformRef(webkit_soup_request_send(d->m_soupRequest.get(), 0, &error.outPtr()));
 359 if (error) {
 360 d->m_inputStream = 0;
 361 return false;
 362 }
 363
 364 d->m_buffer = static_cast<char*>(g_malloc(READ_BUFFER_SIZE));
 365 d->m_total = 0;
 366
 367 g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle);
 368 // balanced by a deref() in cleanupSoupRequestOperation, which should always run
 369 handle->ref();
 370
 371 d->m_cancellable = adoptPlatformRef(g_cancellable_new());
 372 g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
 373 d->m_cancellable.get(), readCallback, GINT_TO_POINTER(!isBase64));
419374
420375 return false;
421376}

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

@@static bool startHttp(ResourceHandle* handle)
483565 url.removeFragmentIdentifier();
484566 request.setURL(url);
485567
486  d->m_msg = request.toSoupMessage();
487  if (!d->m_msg)
 568 GOwnPtr<GError> error;
 569 d->m_soupRequest = adoptPlatformRef(webkit_soup_requester_request(d->m_requester.get(), url.string().utf8().data(), session, &error.outPtr()));
 570 if (error) {
 571 d->m_soupRequest = 0;
 572 return false;
 573 }
 574
 575 g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
 576
 577 d->m_soupMsg = adoptPlatformRef(webkit_soup_request_http_get_message(WEBKIT_SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
 578 SoupMessage* soupMsg = d->m_soupMsg.get();
 579 request.updateSoupMessage(soupMsg);
 580
 581 if (!d->m_soupMsg)
488582 return false;
489583
490584 if (!handle->shouldContentSniff())
491  soup_message_disable_feature(d->m_msg, SOUP_TYPE_CONTENT_SNIFFER);
 585 soup_message_disable_feature(soupMsg, SOUP_TYPE_CONTENT_SNIFFER);
492586
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);
 587 g_signal_connect(soupMsg, "restarted", G_CALLBACK(restartedCallback), handle);
 588 g_signal_connect(soupMsg, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
 589 g_signal_connect(soupMsg, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle);
 590 d->m_gotChunkHandler = g_signal_connect(soupMsg, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
497591
498592#ifdef HAVE_LIBSOUP_2_29_90
499593 String firstPartyString = request.firstPartyForCookies().string();
500594 if (!firstPartyString.isEmpty()) {
501595 GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
502  soup_message_set_first_party(d->m_msg, firstParty.get());
 596 soup_message_set_first_party(soupMsg, firstParty.get());
503597 }
504598#endif
505  g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle));
506599
507600 FormData* httpBody = d->m_firstRequest.httpBody();
508601 if (httpBody && !httpBody->isEmpty()) {

@@static bool startHttp(ResourceHandle* handle)
512605 if (numElements < 2) {
513606 Vector<char> body;
514607 httpBody->flatten(body);
515  soup_message_set_request(d->m_msg, d->m_firstRequest.httpContentType().utf8().data(),
 608 soup_message_set_request(soupMsg, d->m_firstRequest.httpContentType().utf8().data(),
516609 SOUP_MEMORY_COPY, body.data(), body.size());
517610 } else {
518611 /*

@@static bool startHttp(ResourceHandle* handle)
521614 * copying into memory; TODO: support upload of non-local
522615 * (think sftp://) files by using GIO?
523616 */
524  soup_message_body_set_accumulate(d->m_msg->request_body, FALSE);
 617 soup_message_body_set_accumulate(soupMsg->request_body, FALSE);
525618 for (size_t i = 0; i < numElements; i++) {
526619 const FormDataElement& element = httpBody->elements()[i];
527620
528621 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());
 622 soup_message_body_append(soupMsg->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
530623 else {
531624 /*
532625 * mapping for uploaded files code inspired by technique used in
533626 * libsoup's simple-httpd test
534627 */
535  GError* error = 0;
 628 GOwnPtr<GError> error;
536629 CString fileName = fileSystemRepresentation(element.m_filename);
537  GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error);
 630 GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
538631
539632 if (error) {
540  g_error_free(error);
541  g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
 633 g_signal_handlers_disconnect_matched(soupMsg, G_SIGNAL_MATCH_DATA,
542634 0, 0, 0, 0, handle);
543  g_object_unref(d->m_msg);
544  d->m_msg = 0;
 635 d->m_soupMsg.clear();
545636
546637 return false;
547638 }

@@static bool startHttp(ResourceHandle* handle)
549640 SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping),
550641 g_mapped_file_get_length(fileMapping),
551642 fileMapping,
552 #if GLIB_CHECK_VERSION(2, 21, 3)
553643 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);
 644 soup_message_body_append_buffer(soupMsg->request_body, soupBuffer);
558645 soup_buffer_free(soupBuffer);
559646 }
560647 }
561648 }
562649 }
563650
564  // balanced by a deref() in finishedCallback, which should always run
 651 // balanced by a deref() in cleanupSoupRequestOperation, which should always run
565652 handle->ref();
566653
567654 // Make sure we have an Accept header for subresources; some sites
568655 // 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", "*/*");
 656 if (!soup_message_headers_get_one(soupMsg->request_headers, "Accept"))
 657 soup_message_headers_append(soupMsg->request_headers, "Accept", "*/*");
571658
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);
 659 d->m_cancellable = adoptPlatformRef(g_cancellable_new());
 660 webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
577661
578662 return true;
579663}
580664
581665bool ResourceHandle::start(NetworkingContext* context)
582666{
583  ASSERT(!d->m_msg);
 667 ASSERT(!d->m_soupMsg);
584668
585669 // The frame could be null if the ResourceHandle is not associated to any
586670 // Frame, e.g. if we are downloading a file.

@@bool ResourceHandle::start(NetworkingContext* context)
620704void ResourceHandle::cancel()
621705{
622706 d->m_cancelled = true;
623  if (d->m_msg)
624  soup_session_cancel_message(defaultSession(), d->m_msg, SOUP_STATUS_CANCELLED);
 707 if (d->m_soupMsg)
 708 soup_session_cancel_message(defaultSession(), d->m_soupMsg.get(), SOUP_STATUS_CANCELLED);
625709 else if (d->m_cancellable)
626  g_cancellable_cancel(d->m_cancellable);
 710 g_cancellable_cancel(d->m_cancellable.get());
627711}
628712
629713PassRefPtr<SharedBuffer> ResourceHandle::bufferedData()

@@void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const
667751 syncLoader.run();
668752}
669753
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 
702754static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
703755{
704756 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));

@@static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
708760 ResourceHandleInternal* d = handle->getInternal();
709761 ResourceHandleClient* client = handle->client();
710762
711  g_input_stream_close_finish(d->m_inputStream, res, 0);
712  cleanupGioOperation(handle.get());
 763 g_input_stream_close_finish(d->m_inputStream.get(), res, 0);
 764 cleanupSoupRequestOperation(handle.get());
713765
714766 // The load may have been cancelled, the client may have been
715767 // destroyed already. In such cases calling didFinishLoading is a

@@static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
720772 client->didFinishLoading(handle.get(), 0);
721773}
722774
723 static void readCallback(GObject* source, GAsyncResult* res, gpointer)
 775static void readCallback(GObject* source, GAsyncResult* res, gpointer data)
724776{
725777 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
726778 if (!handle)
727779 return;
728780
 781 bool convertToUTF16 = static_cast<bool>(data);
729782 ResourceHandleInternal* d = handle->getInternal();
730783 ResourceHandleClient* client = handle->client();
731784
732785 if (d->m_cancelled || !client) {
733  cleanupGioOperation(handle.get());
 786 cleanupSoupRequestOperation(handle.get());
734787 return;
735788 }
736789
737  GError* error = 0;
 790 GOwnPtr<GError> error;
738791
739  gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error);
 792 gssize bytesRead = g_input_stream_read_finish(d->m_inputStream.get(), res, &error.outPtr());
740793 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,
 794 SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
 795 GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
 796 ResourceError resourceError(g_quark_to_string(G_IO_ERROR), error->code, uriStr.get(),
745797 error ? String::fromUTF8(error->message) : String());
746  g_free(uri);
747  g_error_free(error);
748  cleanupGioOperation(handle.get());
 798 cleanupSoupRequestOperation(handle.get());
749799 client->didFail(handle.get(), resourceError);
750800 return;
751801 }
752802
753803 if (!bytesRead) {
754  g_input_stream_close_async(d->m_inputStream, G_PRIORITY_DEFAULT,
 804 g_input_stream_close_async(d->m_inputStream.get(), G_PRIORITY_DEFAULT,
755805 0, closeCallback, 0);
756806 return;
757807 }
758808
759809 d->m_total += bytesRead;
760  client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
761 
762  // didReceiveData may cancel the load, which may release the last reference.
763  if (d->m_cancelled) {
764  cleanupGioOperation(handle.get());
765  return;
 810 if (G_LIKELY(!convertToUTF16))
 811 client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
 812 else {
 813 // We have to convert it to UTF-16 due to limitations in KURL
 814 String data = String::fromUTF8(d->m_buffer, bytesRead);
 815 client->didReceiveData(handle.get(), reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
766816 }
767817
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 
 818 // didReceiveData may cancel the load, which may release the last reference.
782819 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);
 820 cleanupSoupRequestOperation(handle.get());
799821 return;
800822 }
801823
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);
 824 g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
 825 G_PRIORITY_DEFAULT, d->m_cancellable.get(),
 826 readCallback, data);
811827}
812828
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 }
889829static bool startGio(ResourceHandle* handle, KURL url)
890830{
891831 ASSERT(handle);
892832
893  ResourceHandleInternal* d = handle->getInternal();
894 
895833 if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST")
896834 return false;
897835
 836 SoupSession* session = handle->defaultSession();
 837 ResourceHandleInternal* d = handle->getInternal();
 838
898839 // GIO doesn't know how to handle refs and queries, so remove them
899840 // TODO: use KURL.fileSystemPath after KURLGtk and FileSystemGtk are
900841 // using GIO internally, and providing URIs instead of file paths
901842 url.removeFragmentIdentifier();
902843 url.setQuery(String());
903844 url.removePort();
 845 CString urlStr = url.string().utf8().data();
904846
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);
 847 GOwnPtr<GError> error;
 848 d->m_soupRequest = adoptPlatformRef(webkit_soup_requester_request(d->m_requester.get(), urlStr.data(), session, &error.outPtr()));
 849 if (error) {
 850 d->m_soupRequest = 0;
 851 return false;
 852 }
 853
 854 g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
915855
916  // balanced by a deref() in cleanupGioOperation, which should always run
 856 // balanced by a deref() in cleanupSoupRequestOperation, which should always run
917857 handle->ref();
918858
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);
 859 d->m_cancellable = adoptPlatformRef(g_cancellable_new());
 860 webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
 861
927862 return true;
928863}
929864

WebCore/platform/network/soup/ResourceRequest.h

@@namespace WebCore {
6767 updateFromSoupMessage(soupMessage);
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; }
7475 void setSoupMessageFlags(SoupMessageFlags soupFlags) { m_soupFlags = soupFlags; }

WebCore/platform/network/soup/ResourceRequestSoup.cpp

@@using namespace std;
3333
3434namespace WebCore {
3535
 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}
 58
3659SoupMessage* ResourceRequest::toSoupMessage() const
3760{
3861 SoupMessage* soupMessage = soup_message_new(httpMethod().utf8().data(), url().string().utf8().data());

WebKit/gtk/ChangeLog

 12010-10-01 Sergio Villar Senin <svillar@igalia.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 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-09-26 Jenn Braithwaite <jennb@chromium.org>
215
316 Reviewed by Adam Barth.

WebKit/gtk/webkit/webkitdownload.cpp

@@WebKitDownload* webkit_download_new_with_handle(WebKitNetworkRequest* request, W
419419 g_return_val_if_fail(request, NULL);
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_soupMsg)
 423 soup_session_pause_message(webkit_get_default_session(), d->m_soupMsg.get());
424424
425425 WebKitDownload* download = WEBKIT_DOWNLOAD(g_object_new(WEBKIT_TYPE_DOWNLOAD, "network-request", request, NULL));
426426 WebKitDownloadPrivate* priv = download->priv;

@@void webkit_download_start(WebKitDownload* download)
492492 priv->resourceHandle->setClient(priv->downloadClient);
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_soupMsg)
 496 soup_session_unpause_message(webkit_get_default_session(), d->m_soupMsg.get());
497497 }
498498
499499 priv->timer = g_timer_new();