Changeset 32761 in webkit
- Timestamp:
- May 1, 2008 9:50:00 AM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r32759 r32761 1 2008-05-01 Dan Winship <danw@gnome.org> 2 3 Reviewed by Alp Toker. 4 5 http://bugs.webkit.org/show_bug.cgi?id=18490 6 Add mostly-working file: support and mostly-broken ftp: support to 7 the soup backend. 8 9 * platform/network/soup/ResourceHandleSoup.cpp (start): after 10 doing basic checks, delegate to one of three submethods 11 (startData): handles data: URLs 12 (startHttp): handles http: and https: URLs, via libsoup 13 (startGio, etc): handles file: and ftp: URLs, via gio. Lots of 14 FIXMEs detailing the parts that don't fully work yet. 15 16 * platform/network/ResourceHandle.h: 17 * platform/network/ResourceHandleInternal.h: add new member 18 variables for gio-based loading 19 1 20 2008-05-01 Alp Toker <alp@nuanti.com> 2 21 -
trunk/WebCore/platform/network/ResourceHandle.h
r32442 r32761 173 173 174 174 private: 175 void scheduleFailure(FailureType); 175 #if USE(SOUP) 176 bool startData(String urlString); 177 bool startHttp(String urlString); 178 bool startGio(String urlString); 179 #endif 180 181 void scheduleFailure(FailureType); 176 182 177 183 bool start(Frame*); -
trunk/WebCore/platform/network/ResourceHandleInternal.h
r31682 r32761 111 111 , m_msg(0) 112 112 , m_cancelled(false) 113 , m_gfile(0) 114 , m_input_stream(0) 115 , m_cancellable(0) 116 , m_buffer(0) 117 , m_bufsize(0) 118 , m_total(0) 113 119 #endif 114 120 #if PLATFORM(QT) … … 177 183 ResourceResponse m_response; 178 184 bool m_cancelled; 185 GFile* m_gfile; 186 GInputStream* m_input_stream; 187 GCancellable* m_cancellable; 188 char* m_buffer; 189 gsize m_bufsize, m_total; 179 190 #endif 180 191 #if PLATFORM(QT) -
trunk/WebCore/platform/network/soup/ResourceHandleSoup.cpp
r31878 r32761 23 23 #include "ResourceHandle.h" 24 24 25 #include " Base64.h"25 #include "CookieJar.h" 26 26 #include "DocLoader.h" 27 27 #include "Frame.h" … … 33 33 #include "ResourceHandleInternal.h" 34 34 #include "ResourceResponse.h" 35 #include "CookieJar.h" 36 35 36 #include <gio/gio.h> 37 37 #include <libsoup/soup.h> 38 38 #include <libsoup/soup-message.h> … … 45 45 { 46 46 ERROR_TRANSPORT, 47 ERROR_UNKNOWN_PROTOCOL 47 ERROR_UNKNOWN_PROTOCOL, 48 ERROR_BAD_NON_HTTP_METHOD 48 49 }; 49 50 … … 246 247 } 247 248 248 bool ResourceHandle::start(Frame* frame) 249 { 250 ASSERT(!d->m_msg); 251 252 // If we are no longer attached to a Page, this must be an attempted load from an 253 // onUnload handler, so let's just block it. 254 if (!frame->page()) 255 return false; 256 257 KURL url = request().url(); 258 String protocol = url.protocol(); 259 260 if (equalIgnoringCase(protocol, "data")) { 261 // If parseDataUrl is called syncronously the job is not yet effectively started 249 bool ResourceHandle::startData(String urlString) 250 { 251 // If parseDataUrl is called synchronously the job is not yet effectively started 262 252 // and webkit won't never know that the data has been parsed even didFinishLoading is called. 263 253 g_idle_add(parseDataUrl, this); 264 254 return true; 265 } 266 267 String urlString = url.string(); 268 269 if (!equalIgnoringCase(protocol, "http") && !equalIgnoringCase(protocol, "https")) { 270 // If we don't call didFail the job is not complete for webkit even false is returned. 271 if (d->client()) { 272 ResourceError error("webkit-network-error", ERROR_UNKNOWN_PROTOCOL, urlString, protocol); 273 d->client()->didFail(this, error); 274 } 275 return false; 276 } 277 278 if (url.isLocalFile()) { 279 String query = url.query(); 280 // Remove any query part sent to a local file. 281 if (!query.isEmpty()) 282 urlString = urlString.left(urlString.find(query)); 283 // Determine the MIME type based on the path. 284 d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(String(urlString))); 285 } 286 255 } 256 257 bool ResourceHandle::startHttp(String urlString) 258 { 287 259 if (!session) { 288 260 session = soup_session_async_new(); … … 335 307 } 336 308 309 bool ResourceHandle::start(Frame* frame) 310 { 311 ASSERT(!d->m_msg); 312 313 // If we are no longer attached to a Page, this must be an attempted load from an 314 // onUnload handler, so let's just block it. 315 if (!frame->page()) 316 return false; 317 318 KURL url = request().url(); 319 String urlString = url.string(); 320 String protocol = url.protocol(); 321 322 if (equalIgnoringCase(protocol, "data")) 323 return startData(urlString); 324 else if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) 325 return startHttp(urlString); 326 else if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps")) 327 // FIXME: should we be doing any other protocols here? 328 return startGio(urlString); 329 else { 330 // If we don't call didFail the job is not complete for webkit even false is returned. 331 if (d->client()) { 332 ResourceError error("webkit-network-error", ERROR_UNKNOWN_PROTOCOL, urlString, protocol); 333 d->client()->didFail(this, error); 334 } 335 return false; 336 } 337 } 338 337 339 void ResourceHandle::cancel() 338 340 { … … 342 344 // For re-entrancy troubles we call didFinishLoading when the message hasn't been handled yet. 343 345 d->client()->didFinishLoading(this); 346 } else if (d->m_cancellable) { 347 g_cancellable_cancel(d->m_cancellable); 348 d->client()->didFinishLoading(this); 344 349 } 345 350 } … … 380 385 } 381 386 382 } 387 // GIO-based loader 388 389 static void cleanupGioOperation(ResourceHandle* handle) 390 { 391 ResourceHandleInternal* d = handle->getInternal(); 392 393 if (d->m_gfile) { 394 g_object_unref(d->m_gfile); 395 d->m_gfile = NULL; 396 } 397 if (d->m_cancellable) { 398 g_object_unref(d->m_cancellable); 399 d->m_cancellable = NULL; 400 } 401 if (d->m_input_stream) { 402 g_object_unref(d->m_input_stream); 403 d->m_cancellable = NULL; 404 } 405 if (d->m_buffer) { 406 g_free(d->m_buffer); 407 d->m_buffer = NULL; 408 } 409 } 410 411 static void closeCallback(GObject* source, GAsyncResult* res, gpointer data) 412 { 413 ResourceHandle* handle = static_cast<ResourceHandle*>(data); 414 ResourceHandleInternal* d = handle->getInternal(); 415 416 g_input_stream_close_finish(d->m_input_stream, res, NULL); 417 cleanupGioOperation(handle); 418 } 419 420 static void readCallback(GObject* source, GAsyncResult* res, gpointer data) 421 { 422 ResourceHandle* handle = static_cast<ResourceHandle*>(data); 423 ResourceHandleInternal* d = handle->getInternal(); 424 ResourceHandleClient* client = handle->client(); 425 426 if (d->m_cancelled || !client) { 427 cleanupGioOperation(handle); 428 return; 429 } 430 431 gssize nread; 432 GError *error = 0; 433 434 nread = g_input_stream_read_finish(d->m_input_stream, res, &error); 435 if (error) { 436 cleanupGioOperation(handle); 437 // FIXME: error 438 client->didFinishLoading(handle); 439 return; 440 } else if (!nread) { 441 client->didFinishLoading(handle); 442 g_input_stream_close_async(d->m_input_stream, G_PRIORITY_DEFAULT, 443 NULL, closeCallback, handle); 444 return; 445 } 446 447 d->m_total += nread; 448 client->didReceiveData(handle, d->m_buffer, nread, d->m_total); 449 450 g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, 451 G_PRIORITY_DEFAULT, d->m_cancellable, 452 readCallback, handle); 453 } 454 455 static void openCallback(GObject* source, GAsyncResult* res, gpointer data) 456 { 457 ResourceHandle* handle = static_cast<ResourceHandle*>(data); 458 ResourceHandleInternal* d = handle->getInternal(); 459 ResourceHandleClient* client = handle->client(); 460 461 if (d->m_cancelled || !client) { 462 cleanupGioOperation(handle); 463 return; 464 } 465 466 GFileInputStream* in; 467 GError *error = NULL; 468 in = g_file_read_finish(G_FILE(source), res, &error); 469 if (error) { 470 cleanupGioOperation(handle); 471 // FIXME: error 472 client->didFinishLoading(handle); 473 return; 474 } 475 476 d->m_input_stream = G_INPUT_STREAM(in); 477 d->m_bufsize = 8192; 478 d->m_buffer = static_cast<char*>(g_malloc(d->m_bufsize)); 479 d->m_total = 0; 480 g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, 481 G_PRIORITY_DEFAULT, d->m_cancellable, 482 readCallback, handle); 483 } 484 485 static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data) 486 { 487 ResourceHandle* handle = static_cast<ResourceHandle*>(data); 488 ResourceHandleInternal* d = handle->getInternal(); 489 ResourceHandleClient* client = handle->client(); 490 491 if (d->m_cancelled) { 492 cleanupGioOperation(handle); 493 return; 494 } 495 496 ResourceResponse response; 497 498 char* uri = g_file_get_uri(d->m_gfile); 499 response.setUrl(KURL(uri)); 500 g_free(uri); 501 502 GError *error = NULL; 503 GFileInfo* info = g_file_query_info_finish(d->m_gfile, res, &error); 504 505 if (error) { 506 // FIXME: to be able to handle ftp URIs properly, we must 507 // check if the error is G_IO_ERROR_NOT_MOUNTED, and if so, 508 // call g_file_mount_enclosing_volume() to mount the ftp 509 // server (and then keep track of the fact that we mounted it, 510 // and set a timeout to unmount it later after it's been idle 511 // for a while). 512 513 cleanupGioOperation(handle); 514 515 if (error->domain == G_IO_ERROR && 516 error->code == G_IO_ERROR_NOT_FOUND) 517 response.setHTTPStatusCode(SOUP_STATUS_NOT_FOUND); 518 else if (error->domain == G_IO_ERROR && 519 error->code == G_IO_ERROR_PERMISSION_DENIED) 520 response.setHTTPStatusCode(SOUP_STATUS_FORBIDDEN); 521 else 522 response.setHTTPStatusCode(SOUP_STATUS_BAD_REQUEST); // ? 523 g_error_free(error); 524 525 // FIXME: do we need to fake up a response body containing the 526 // error message? 527 528 client->didReceiveResponse(handle, response); 529 client->didFinishLoading(handle); 530 return; 531 } 532 533 if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) { 534 // FIXME: what if the URI points to a directory? Should we 535 // generate a listing? How? What do other backends do here? 536 537 cleanupGioOperation(handle); 538 response.setHTTPStatusCode(SOUP_STATUS_FORBIDDEN); // ? 539 client->didReceiveResponse(handle, response); 540 client->didFinishLoading(handle); 541 return; 542 } 543 544 response.setMimeType(g_file_info_get_content_type(info)); 545 response.setExpectedContentLength(g_file_info_get_size(info)); 546 response.setHTTPStatusCode(SOUP_STATUS_OK); 547 548 GTimeVal tv; 549 g_file_info_get_modification_time(info, &tv); 550 response.setLastModifiedDate(tv.tv_sec); 551 552 client->didReceiveResponse(handle, response); 553 554 g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable, 555 openCallback, handle); 556 } 557 558 bool ResourceHandle::startGio(String urlString) 559 { 560 if (request().httpMethod() != "GET") { 561 ResourceError error("webkit-network-error", ERROR_BAD_NON_HTTP_METHOD, urlString, request().httpMethod()); 562 d->client()->didFail(this, error); 563 return false; 564 } 565 566 d->m_gfile = g_file_new_for_uri(urlString.utf8().data()); 567 d->m_cancellable = g_cancellable_new(); 568 g_file_query_info_async(d->m_gfile, 569 G_FILE_ATTRIBUTE_STANDARD_TYPE "," 570 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," 571 G_FILE_ATTRIBUTE_STANDARD_SIZE, 572 G_FILE_QUERY_INFO_NONE, 573 G_PRIORITY_DEFAULT, d->m_cancellable, 574 queryInfoCallback, this); 575 return true; 576 } 577 578 } 579
Note: See TracChangeset
for help on using the changeset viewer.