Changeset 101917 in webkit for trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
- Timestamp:
- Dec 3, 2011 1:22:54 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
r100640 r101917 181 181 } 182 182 183 // All other kinds of redirections, except for the *304* status code184 // (SOUP_STATUS_NOT_MODIFIED) which needs to be fed into WebCore, will be185 // handled by soup directly.186 static gboolean statusWillBeHandledBySoup(guint statusCode)187 {188 if (SOUP_STATUS_IS_TRANSPORT_ERROR(statusCode)189 || (SOUP_STATUS_IS_REDIRECTION(statusCode) && (statusCode != SOUP_STATUS_NOT_MODIFIED))190 || (statusCode == SOUP_STATUS_UNAUTHORIZED))191 return true;192 193 return false;194 }195 196 183 // Called each time the message is going to be sent again except the first time. 197 184 // It's used mostly to let webkit know about redirects. … … 235 222 } 236 223 237 static void contentSniffedCallback(SoupMessage*, const char*, GHashTable*, gpointer);238 239 static void gotHeadersCallback(SoupMessage* msg, gpointer data)240 {241 // For 401, we will accumulate the resource body, and only use it242 // in case authentication with the soup feature doesn't happen.243 // For 302 we accumulate the body too because it could be used by244 // some servers to redirect with a clunky http-equiv=REFRESH245 if (statusWillBeHandledBySoup(msg->status_code)) {246 soup_message_body_set_accumulate(msg->response_body, TRUE);247 return;248 }249 250 // For all the other responses, we handle each chunk ourselves,251 // and we don't need msg->response_body to contain all of the data252 // we got, when we finish downloading.253 soup_message_body_set_accumulate(msg->response_body, FALSE);254 255 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);256 257 // The content-sniffed callback will handle the response if WebCore258 // require us to sniff.259 if (!handle || statusWillBeHandledBySoup(msg->status_code))260 return;261 262 if (handle->shouldContentSniff()) {263 // Avoid MIME type sniffing if the response comes back as 304 Not Modified.264 if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {265 soup_message_disable_feature(msg, SOUP_TYPE_CONTENT_SNIFFER);266 g_signal_handlers_disconnect_by_func(msg, reinterpret_cast<gpointer>(contentSniffedCallback), handle.get());267 } else268 return;269 }270 271 ResourceHandleInternal* d = handle->getInternal();272 if (d->m_cancelled)273 return;274 ResourceHandleClient* client = handle->client();275 if (!client)276 return;277 278 ASSERT(d->m_response.isNull());279 280 d->m_response.updateFromSoupMessage(msg);281 client->didReceiveResponse(handle.get(), d->m_response);282 }283 284 224 static void wroteBodyDataCallback(SoupMessage*, SoupBuffer* buffer, gpointer data) 285 225 { … … 299 239 300 240 client->didSendData(handle.get(), internal->m_bodyDataSent, internal->m_bodySize); 301 }302 303 // This callback will not be called if the content sniffer is disabled in startHTTPRequest.304 static void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data)305 {306 307 if (statusWillBeHandledBySoup(msg->status_code))308 return;309 310 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);311 if (!handle)312 return;313 ResourceHandleInternal* d = handle->getInternal();314 if (d->m_cancelled)315 return;316 ResourceHandleClient* client = handle->client();317 if (!client)318 return;319 320 ASSERT(d->m_response.isNull());321 322 if (sniffedType) {323 const char* officialType = soup_message_headers_get_one(msg->response_headers, "Content-Type");324 if (!officialType || strcmp(officialType, sniffedType)) {325 GString* str = g_string_new(sniffedType);326 if (params) {327 GHashTableIter iter;328 gpointer key, value;329 g_hash_table_iter_init(&iter, params);330 while (g_hash_table_iter_next(&iter, &key, &value)) {331 g_string_append(str, "; ");332 soup_header_g_string_append_param(str, static_cast<const char*>(key), static_cast<const char*>(value));333 }334 }335 d->m_response.setSniffedContentType(str->str);336 g_string_free(str, TRUE);337 }338 }339 340 d->m_response.updateFromSoupMessage(msg);341 client->didReceiveResponse(handle.get(), d->m_response);342 }343 344 static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)345 {346 if (statusWillBeHandledBySoup(msg->status_code))347 return;348 349 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);350 if (!handle)351 return;352 ResourceHandleInternal* d = handle->getInternal();353 if (d->m_cancelled)354 return;355 ResourceHandleClient* client = handle->client();356 if (!client)357 return;358 359 ASSERT(!d->m_response.isNull());360 361 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793362 // -1 means we do not provide any data about transfer size to inspector so it would use363 // Content-Length headers or content size to show transfer size.364 client->didReceiveData(handle.get(), chunk->data, chunk->length, -1);365 }366 367 static void finishedCallback(SoupMessage* msg, gpointer data)368 {369 RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);370 if (!handle)371 return;372 handle->getInternal()->m_finished = true;373 241 } 374 242 … … 398 266 if (!isDestroying) 399 267 handle->deref(); 400 }401 402 static bool soupErrorShouldCauseLoadFailure(GError* error, SoupMessage* message)403 {404 // Libsoup treats some non-error conditions as errors, including redirects and 304 Not Modified responses.405 return message && SOUP_STATUS_IS_TRANSPORT_ERROR(message->status_code) || error->domain == G_IO_ERROR;406 268 } 407 269 … … 432 294 ResourceHandleInternal* d = handle->getInternal(); 433 295 ResourceHandleClient* client = handle->client(); 434 435 if (d->m_gotChunkHandler) { 436 // No need to call gotChunkHandler anymore. Received data will 437 // be reported by readCallback 438 if (g_signal_handler_is_connected(d->m_soupMessage.get(), d->m_gotChunkHandler)) 439 g_signal_handler_disconnect(d->m_soupMessage.get(), d->m_gotChunkHandler); 440 } 296 SoupMessage* soupMessage = d->m_soupMessage.get(); 441 297 442 298 if (d->m_cancelled || !client) { … … 448 304 GInputStream* in = soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr()); 449 305 if (error) { 450 SoupMessage* soupMessage = d->m_soupMessage.get(); 451 452 if (soupErrorShouldCauseLoadFailure(error.get(), soupMessage)) { 453 client->didFail(handle.get(), convertSoupErrorToResourceError(error.get(), d->m_soupRequest.get(), soupMessage)); 454 cleanupSoupRequestOperation(handle.get()); 455 return; 456 } 457 458 if (soupMessage && statusWillBeHandledBySoup(soupMessage->status_code)) { 459 ASSERT(d->m_response.isNull()); 460 461 d->m_response.updateFromSoupMessage(soupMessage); 462 client->didReceiveResponse(handle.get(), d->m_response); 463 464 // WebCore might have cancelled the job in the while. We 465 // must check for response_body->length and not 466 // response_body->data as libsoup always creates the 467 // SoupBuffer for the body even if the length is 0 468 if (!d->m_cancelled && soupMessage->response_body->length) 469 client->didReceiveData(handle.get(), soupMessage->response_body->data, 470 soupMessage->response_body->length, soupMessage->response_body->length); 471 } 472 473 // didReceiveData above might have canceled this operation. If not, inform the client we've finished loading. 474 if (!d->m_cancelled && client) 475 client->didFinishLoading(handle.get(), 0); 476 477 cleanupSoupRequestOperation(handle.get()); 478 return; 479 } 480 481 if (d->m_cancelled) { 306 client->didFail(handle.get(), convertSoupErrorToResourceError(error.get(), d->m_soupRequest.get(), soupMessage)); 482 307 cleanupSoupRequestOperation(handle.get()); 483 308 return; … … 487 312 d->m_buffer = static_cast<char*>(g_slice_alloc(READ_BUFFER_SIZE)); 488 313 489 // If not using SoupMessage we need to call didReceiveResponse now. 490 // (This will change later when SoupRequest supports content sniffing.) 491 if (!d->m_soupMessage) { 314 if (soupMessage) { 315 if (handle->shouldContentSniff() && soupMessage->status_code != SOUP_STATUS_NOT_MODIFIED) { 316 const char* sniffedType = soup_request_get_content_type(d->m_soupRequest.get()); 317 d->m_response.setSniffedContentType(sniffedType); 318 } 319 d->m_response.updateFromSoupMessage(soupMessage); 320 321 if (d->m_defersLoading) 322 soup_session_pause_message(handle->defaultSession(), soupMessage); 323 } else { 492 324 d->m_response.setURL(handle->firstRequest().url()); 493 325 const gchar* contentType = soup_request_get_content_type(d->m_soupRequest.get()); … … 495 327 d->m_response.setTextEncodingName(extractCharsetFromMediaType(contentType)); 496 328 d->m_response.setExpectedContentLength(soup_request_get_content_length(d->m_soupRequest.get())); 497 client->didReceiveResponse(handle.get(), d->m_response); 498 499 if (d->m_cancelled) { 500 cleanupSoupRequestOperation(handle.get()); 501 return; 502 } 329 } 330 331 client->didReceiveResponse(handle.get(), d->m_response); 332 333 if (d->m_cancelled) { 334 cleanupSoupRequestOperation(handle.get()); 335 return; 503 336 } 504 337 … … 621 454 request.setURL(url); 622 455 623 d->m_finished = false;624 625 456 GOwnPtr<GError> error; 626 457 d->m_soupRequest = adoptGRef(soup_requester_request(requester, url.string().utf8().data(), &error.outPtr())); … … 639 470 if (!handle->shouldContentSniff()) 640 471 soup_message_disable_feature(soupMessage, SOUP_TYPE_CONTENT_SNIFFER); 641 else642 g_signal_connect(soupMessage, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle);643 472 644 473 g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle); 645 g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle);646 474 g_signal_connect(soupMessage, "wrote-body-data", G_CALLBACK(wroteBodyDataCallback), handle); 647 d->m_gotChunkHandler = g_signal_connect(soupMessage, "got-chunk", G_CALLBACK(gotChunkCallback), handle);648 d->m_finishedHandler = g_signal_connect(soupMessage, "finished", G_CALLBACK(finishedCallback), handle);649 475 650 476 String firstPartyString = request.firstPartyForCookies().string();
Note: See TracChangeset
for help on using the changeset viewer.