OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/blob/blob_url_request_job.h" | 5 #include "webkit/blob/blob_url_request_job.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 bytes_to_read_(0), | 66 bytes_to_read_(0), |
67 error_(false), | 67 error_(false), |
68 headers_set_(false), | 68 headers_set_(false), |
69 byte_range_set_(false) { | 69 byte_range_set_(false) { |
70 DCHECK(file_thread_proxy_); | 70 DCHECK(file_thread_proxy_); |
71 } | 71 } |
72 | 72 |
73 BlobURLRequestJob::~BlobURLRequestJob() { | 73 BlobURLRequestJob::~BlobURLRequestJob() { |
74 // FileStream's destructor won't close it for us because we passed in our own | 74 // FileStream's destructor won't close it for us because we passed in our own |
75 // file handle. | 75 // file handle. |
76 CloseStream(); | 76 CloseFileStream(); |
77 } | 77 } |
78 | 78 |
79 void BlobURLRequestJob::Start() { | 79 void BlobURLRequestJob::Start() { |
80 // Continue asynchronously. | 80 // Continue asynchronously. |
81 MessageLoop::current()->PostTask( | 81 MessageLoop::current()->PostTask( |
82 FROM_HERE, | 82 FROM_HERE, |
83 base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); | 83 base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); |
84 } | 84 } |
85 | 85 |
86 void BlobURLRequestJob::Kill() { | 86 void BlobURLRequestJob::Kill() { |
87 CloseStream(); | 87 CloseFileStream(); |
88 | 88 |
89 net::URLRequestJob::Kill(); | 89 net::URLRequestJob::Kill(); |
90 weak_factory_.InvalidateWeakPtrs(); | 90 weak_factory_.InvalidateWeakPtrs(); |
91 } | 91 } |
92 | 92 |
93 bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, | 93 bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, |
94 int dest_size, | 94 int dest_size, |
95 int* bytes_read) { | 95 int* bytes_read) { |
96 DCHECK_NE(dest_size, 0); | 96 DCHECK_NE(dest_size, 0); |
97 DCHECK(bytes_read); | 97 DCHECK(bytes_read); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 // If nothing to read for current item, advance to next item. | 289 // If nothing to read for current item, advance to next item. |
290 if (bytes_to_read_ == 0) { | 290 if (bytes_to_read_ == 0) { |
291 AdvanceItem(); | 291 AdvanceItem(); |
292 return ReadItem(); | 292 return ReadItem(); |
293 } | 293 } |
294 | 294 |
295 // Do the reading. | 295 // Do the reading. |
296 const BlobData::Item& item = blob_data_->items().at(item_index_); | 296 const BlobData::Item& item = blob_data_->items().at(item_index_); |
297 switch (item.type) { | 297 switch (item.type) { |
298 case BlobData::TYPE_DATA: | 298 case BlobData::TYPE_DATA: |
299 return ReadBytes(item); | 299 return ReadBytesItem(item); |
300 case BlobData::TYPE_FILE: | 300 case BlobData::TYPE_FILE: |
301 return DispatchReadFile(item); | 301 return ReadFileItem(item); |
302 default: | 302 default: |
303 DCHECK(false); | 303 DCHECK(false); |
304 return false; | 304 return false; |
305 } | 305 } |
306 } | 306 } |
307 | 307 |
308 void BlobURLRequestJob::AdvanceItem() { | 308 void BlobURLRequestJob::AdvanceItem() { |
309 // Close the stream if the current item is a file. | 309 // Close the stream if the current item is a file. |
310 CloseStream(); | 310 CloseFileStream(); |
311 | 311 |
312 // Advance to the next item. | 312 // Advance to the next item. |
313 item_index_++; | 313 item_index_++; |
314 current_item_offset_ = 0; | 314 current_item_offset_ = 0; |
315 } | 315 } |
316 | 316 |
317 void BlobURLRequestJob::AdvanceBytesRead(int result) { | 317 void BlobURLRequestJob::AdvanceBytesRead(int result) { |
318 DCHECK_GT(result, 0); | 318 DCHECK_GT(result, 0); |
319 | 319 |
320 // Do we finish reading the current item? | 320 // Do we finish reading the current item? |
321 current_item_offset_ += result; | 321 current_item_offset_ += result; |
322 if (current_item_offset_ == item_length_list_[item_index_]) | 322 if (current_item_offset_ == item_length_list_[item_index_]) |
323 AdvanceItem(); | 323 AdvanceItem(); |
324 | 324 |
325 // Subtract the remaining bytes. | 325 // Subtract the remaining bytes. |
326 remaining_bytes_ -= result; | 326 remaining_bytes_ -= result; |
327 DCHECK_GE(remaining_bytes_, 0); | 327 DCHECK_GE(remaining_bytes_, 0); |
328 | 328 |
329 // Adjust the read buffer. | 329 // Adjust the read buffer. |
330 read_buf_->DidConsume(result); | 330 read_buf_->DidConsume(result); |
331 DCHECK_GE(read_buf_->BytesRemaining(), 0); | 331 DCHECK_GE(read_buf_->BytesRemaining(), 0); |
332 } | 332 } |
333 | 333 |
334 bool BlobURLRequestJob::ReadBytes(const BlobData::Item& item) { | 334 bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item) { |
335 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read_); | 335 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read_); |
336 | 336 |
337 memcpy(read_buf_->data(), | 337 memcpy(read_buf_->data(), |
338 &item.data.at(0) + item.offset + current_item_offset_, | 338 &item.data.at(0) + item.offset + current_item_offset_, |
339 bytes_to_read_); | 339 bytes_to_read_); |
340 | 340 |
341 AdvanceBytesRead(bytes_to_read_); | 341 AdvanceBytesRead(bytes_to_read_); |
342 return true; | 342 return true; |
343 } | 343 } |
344 | 344 |
345 bool BlobURLRequestJob::DispatchReadFile(const BlobData::Item& item) { | 345 bool BlobURLRequestJob::ReadFileItem(const BlobData::Item& item) { |
346 // If the stream already exists, keep reading from it. | 346 // If the stream already exists, keep reading from it. |
347 if (stream_ != NULL) | 347 if (stream_ != NULL) |
348 return ReadFile(); | 348 return ReadFileStream(); |
349 | 349 |
350 base::FileUtilProxy::CreateOrOpen( | 350 base::FileUtilProxy::CreateOrOpen( |
351 file_thread_proxy_, item.file_path, kFileOpenFlags, | 351 file_thread_proxy_, item.file_path, kFileOpenFlags, |
352 base::Bind(&BlobURLRequestJob::DidOpen, | 352 base::Bind(&BlobURLRequestJob::DidOpenForReadFile, |
353 weak_factory_.GetWeakPtr())); | 353 weak_factory_.GetWeakPtr())); |
354 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | 354 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
355 return false; | 355 return false; |
356 } | 356 } |
357 | 357 |
358 void BlobURLRequestJob::DidOpen(base::PlatformFileError rv, | 358 void BlobURLRequestJob::DidOpenForReadFile(base::PlatformFileError rv, |
359 base::PassPlatformFile file, | 359 base::PassPlatformFile file, |
360 bool created) { | 360 bool created) { |
361 if (rv != base::PLATFORM_FILE_OK) { | 361 if (rv != base::PLATFORM_FILE_OK) { |
362 NotifyFailure(net::ERR_FAILED); | 362 NotifyFailure(net::ERR_FAILED); |
363 return; | 363 return; |
364 } | 364 } |
365 | 365 |
366 DCHECK(!stream_.get()); | 366 DCHECK(!stream_.get()); |
367 stream_.reset(new net::FileStream(file.ReleaseValue(), kFileOpenFlags, NULL)); | 367 stream_.reset(new net::FileStream(file.ReleaseValue(), kFileOpenFlags, NULL)); |
368 | 368 |
369 const BlobData::Item& item = blob_data_->items().at(item_index_); | 369 const BlobData::Item& item = blob_data_->items().at(item_index_); |
370 { | 370 { |
371 // stream_.Seek() blocks the IO thread, see http://crbug.com/75548. | 371 // stream_.Seek() blocks the IO thread, see http://crbug.com/75548. |
372 base::ThreadRestrictions::ScopedAllowIO allow_io; | 372 base::ThreadRestrictions::ScopedAllowIO allow_io; |
373 int64 offset = current_item_offset_ + static_cast<int64>(item.offset); | 373 int64 offset = current_item_offset_ + static_cast<int64>(item.offset); |
374 if (offset > 0 && offset != stream_->Seek(net::FROM_BEGIN, offset)) { | 374 if (offset > 0 && offset != stream_->Seek(net::FROM_BEGIN, offset)) { |
375 NotifyFailure(net::ERR_FAILED); | 375 NotifyFailure(net::ERR_FAILED); |
376 return; | 376 return; |
377 } | 377 } |
378 } | 378 } |
379 | 379 |
380 ReadFile(); | 380 ReadFileStream(); |
381 } | 381 } |
382 | 382 |
383 bool BlobURLRequestJob::ReadFile() { | 383 bool BlobURLRequestJob::ReadFileStream() { |
384 DCHECK(stream_.get()); | 384 DCHECK(stream_.get()); |
385 DCHECK(stream_->IsOpen()); | 385 DCHECK(stream_->IsOpen()); |
386 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read_); | 386 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read_); |
387 | 387 |
388 // Start the asynchronous reading. | 388 // Start the asynchronous reading. |
389 int rv = stream_->Read(read_buf_, | 389 int rv = stream_->Read(read_buf_, |
390 bytes_to_read_, | 390 bytes_to_read_, |
391 base::Bind(&BlobURLRequestJob::DidRead, | 391 base::Bind(&BlobURLRequestJob::DidReadFileStream, |
392 base::Unretained(this))); | 392 base::Unretained(this))); |
393 | 393 |
394 // If I/O pending error is returned, we just need to wait. | 394 // If I/O pending error is returned, we just need to wait. |
395 if (rv == net::ERR_IO_PENDING) { | 395 if (rv == net::ERR_IO_PENDING) { |
396 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); | 396 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
397 return false; | 397 return false; |
398 } | 398 } |
399 | 399 |
400 // For all other errors, bail out. | 400 // For all other errors, bail out. |
401 if (rv < 0) { | 401 if (rv < 0) { |
402 NotifyFailure(net::ERR_FAILED); | 402 NotifyFailure(net::ERR_FAILED); |
403 return false; | 403 return false; |
404 } | 404 } |
405 | 405 |
406 // Otherwise, data is immediately available. | 406 // Otherwise, data is immediately available. |
407 if (GetStatus().is_io_pending()) | 407 if (GetStatus().is_io_pending()) |
408 DidRead(rv); | 408 DidReadFileStream(rv); |
409 else | 409 else |
410 AdvanceBytesRead(rv); | 410 AdvanceBytesRead(rv); |
411 | 411 |
412 return true; | 412 return true; |
413 } | 413 } |
414 | 414 |
415 void BlobURLRequestJob::DidRead(int result) { | 415 void BlobURLRequestJob::DidReadFileStream(int result) { |
416 if (result < 0) { | 416 if (result < 0) { |
417 NotifyFailure(net::ERR_FAILED); | 417 NotifyFailure(net::ERR_FAILED); |
418 return; | 418 return; |
419 } | 419 } |
420 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status | 420 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status |
421 | 421 |
422 AdvanceBytesRead(result); | 422 AdvanceBytesRead(result); |
423 | 423 |
424 // If the read buffer is completely filled, we're done. | 424 // If the read buffer is completely filled, we're done. |
425 if (!read_buf_->BytesRemaining()) { | 425 if (!read_buf_->BytesRemaining()) { |
426 int bytes_read = ReadCompleted(); | 426 int bytes_read = BytesReadCompleted(); |
427 NotifyReadComplete(bytes_read); | 427 NotifyReadComplete(bytes_read); |
428 return; | 428 return; |
429 } | 429 } |
430 | 430 |
431 // Otherwise, continue the reading. | 431 // Otherwise, continue the reading. |
432 int bytes_read = 0; | 432 int bytes_read = 0; |
433 if (ReadLoop(&bytes_read)) | 433 if (ReadLoop(&bytes_read)) |
434 NotifyReadComplete(bytes_read); | 434 NotifyReadComplete(bytes_read); |
435 } | 435 } |
436 | 436 |
437 void BlobURLRequestJob::CloseStream() { | 437 void BlobURLRequestJob::CloseFileStream() { |
438 if (stream_ != NULL) { | 438 if (stream_ != NULL) { |
439 // stream_.Close() blocks the IO thread, see http://crbug.com/75548. | 439 // stream_.Close() blocks the IO thread, see http://crbug.com/75548. |
440 base::ThreadRestrictions::ScopedAllowIO allow_io; | 440 base::ThreadRestrictions::ScopedAllowIO allow_io; |
441 stream_->CloseSync(); | 441 stream_->CloseSync(); |
442 stream_.reset(NULL); | 442 stream_.reset(NULL); |
443 } | 443 } |
444 } | 444 } |
445 | 445 |
446 int BlobURLRequestJob::ReadCompleted() { | 446 int BlobURLRequestJob::BytesReadCompleted() { |
447 int bytes_read = read_buf_->BytesConsumed(); | 447 int bytes_read = read_buf_->BytesConsumed(); |
448 read_buf_ = NULL; | 448 read_buf_ = NULL; |
449 return bytes_read; | 449 return bytes_read; |
450 } | 450 } |
451 | 451 |
452 int BlobURLRequestJob::ComputeBytesToRead() const { | 452 int BlobURLRequestJob::ComputeBytesToRead() const { |
453 int64 current_item_remaining_bytes = | 453 int64 current_item_remaining_bytes = |
454 item_length_list_[item_index_] - current_item_offset_; | 454 item_length_list_[item_index_] - current_item_offset_; |
455 int bytes_to_read = (read_buf_->BytesRemaining() > | 455 int bytes_to_read = (read_buf_->BytesRemaining() > |
456 current_item_remaining_bytes) | 456 current_item_remaining_bytes) |
457 ? static_cast<int>(current_item_remaining_bytes) | 457 ? static_cast<int>(current_item_remaining_bytes) |
458 : read_buf_->BytesRemaining(); | 458 : read_buf_->BytesRemaining(); |
459 if (bytes_to_read > remaining_bytes_) | 459 if (bytes_to_read > remaining_bytes_) |
460 bytes_to_read = static_cast<int>(remaining_bytes_); | 460 bytes_to_read = static_cast<int>(remaining_bytes_); |
461 return bytes_to_read; | 461 return bytes_to_read; |
462 } | 462 } |
463 | 463 |
464 bool BlobURLRequestJob::ReadLoop(int* bytes_read) { | 464 bool BlobURLRequestJob::ReadLoop(int* bytes_read) { |
465 // Read until we encounter an error or could not get the data immediately. | 465 // Read until we encounter an error or could not get the data immediately. |
466 while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) { | 466 while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) { |
467 if (!ReadItem()) | 467 if (!ReadItem()) |
468 return false; | 468 return false; |
469 } | 469 } |
470 | 470 |
471 *bytes_read = ReadCompleted(); | 471 *bytes_read = BytesReadCompleted(); |
472 return true; | 472 return true; |
473 } | 473 } |
474 | 474 |
475 void BlobURLRequestJob::NotifySuccess() { | 475 void BlobURLRequestJob::NotifySuccess() { |
476 int status_code = 0; | 476 int status_code = 0; |
477 std::string status_text; | 477 std::string status_text; |
478 if (byte_range_set_ && byte_range_.IsValid()) { | 478 if (byte_range_set_ && byte_range_.IsValid()) { |
479 status_code = kHTTPPartialContent; | 479 status_code = kHTTPPartialContent; |
480 status_text += kHTTPPartialContentText; | 480 status_text += kHTTPPartialContentText; |
481 } else { | 481 } else { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 response_info_.reset(new net::HttpResponseInfo()); | 558 response_info_.reset(new net::HttpResponseInfo()); |
559 response_info_->headers = headers; | 559 response_info_->headers = headers; |
560 | 560 |
561 set_expected_content_size(remaining_bytes_); | 561 set_expected_content_size(remaining_bytes_); |
562 headers_set_ = true; | 562 headers_set_ = true; |
563 | 563 |
564 NotifyHeadersComplete(); | 564 NotifyHeadersComplete(); |
565 } | 565 } |
566 | 566 |
567 } // namespace webkit_blob | 567 } // namespace webkit_blob |
OLD | NEW |