| 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/browser/blob/blob_url_request_job.h" | 5 #include "storage/browser/blob/blob_url_request_job.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/files/file_util_proxy.h" | 12 #include "base/files/file_util_proxy.h" |
| 13 #include "base/format_macros.h" | 13 #include "base/format_macros.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
| 16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
| 19 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" |
| 20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 21 #include "net/http/http_request_headers.h" | 21 #include "net/http/http_request_headers.h" |
| 22 #include "net/http/http_response_headers.h" | 22 #include "net/http/http_response_headers.h" |
| 23 #include "net/http/http_response_info.h" | 23 #include "net/http/http_response_info.h" |
| 24 #include "net/http/http_util.h" | 24 #include "net/http/http_util.h" |
| 25 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
| 26 #include "net/url_request/url_request_context.h" | 26 #include "net/url_request/url_request_context.h" |
| 27 #include "net/url_request/url_request_error_job.h" | 27 #include "net/url_request/url_request_error_job.h" |
| 28 #include "net/url_request/url_request_status.h" | 28 #include "net/url_request/url_request_status.h" |
| 29 #include "webkit/browser/blob/file_stream_reader.h" | 29 #include "storage/browser/blob/file_stream_reader.h" |
| 30 #include "webkit/browser/fileapi/file_system_context.h" | 30 #include "storage/browser/fileapi/file_system_context.h" |
| 31 #include "webkit/browser/fileapi/file_system_url.h" | 31 #include "storage/browser/fileapi/file_system_url.h" |
| 32 | 32 |
| 33 namespace webkit_blob { | 33 namespace storage { |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 bool IsFileType(BlobData::Item::Type type) { | 37 bool IsFileType(BlobData::Item::Type type) { |
| 38 switch (type) { | 38 switch (type) { |
| 39 case BlobData::Item::TYPE_FILE: | 39 case BlobData::Item::TYPE_FILE: |
| 40 case BlobData::Item::TYPE_FILE_FILESYSTEM: | 40 case BlobData::Item::TYPE_FILE_FILESYSTEM: |
| 41 return true; | 41 return true; |
| 42 default: | 42 default: |
| 43 return false; | 43 return false; |
| 44 } | 44 } |
| 45 } | 45 } |
| 46 | 46 |
| 47 } // namespace | 47 } // namespace |
| 48 | 48 |
| 49 BlobURLRequestJob::BlobURLRequestJob( | 49 BlobURLRequestJob::BlobURLRequestJob( |
| 50 net::URLRequest* request, | 50 net::URLRequest* request, |
| 51 net::NetworkDelegate* network_delegate, | 51 net::NetworkDelegate* network_delegate, |
| 52 BlobData* blob_data, | 52 BlobData* blob_data, |
| 53 fileapi::FileSystemContext* file_system_context, | 53 storage::FileSystemContext* file_system_context, |
| 54 base::MessageLoopProxy* file_thread_proxy) | 54 base::MessageLoopProxy* file_thread_proxy) |
| 55 : net::URLRequestJob(request, network_delegate), | 55 : net::URLRequestJob(request, network_delegate), |
| 56 blob_data_(blob_data), | 56 blob_data_(blob_data), |
| 57 file_system_context_(file_system_context), | 57 file_system_context_(file_system_context), |
| 58 file_thread_proxy_(file_thread_proxy), | 58 file_thread_proxy_(file_thread_proxy), |
| 59 total_size_(0), | 59 total_size_(0), |
| 60 remaining_bytes_(0), | 60 remaining_bytes_(0), |
| 61 pending_get_file_info_count_(0), | 61 pending_get_file_info_count_(0), |
| 62 current_item_index_(0), | 62 current_item_index_(0), |
| 63 current_item_offset_(0), | 63 current_item_offset_(0), |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 187 |
| 188 void BlobURLRequestJob::CountSize() { | 188 void BlobURLRequestJob::CountSize() { |
| 189 pending_get_file_info_count_ = 0; | 189 pending_get_file_info_count_ = 0; |
| 190 total_size_ = 0; | 190 total_size_ = 0; |
| 191 item_length_list_.resize(blob_data_->items().size()); | 191 item_length_list_.resize(blob_data_->items().size()); |
| 192 | 192 |
| 193 for (size_t i = 0; i < blob_data_->items().size(); ++i) { | 193 for (size_t i = 0; i < blob_data_->items().size(); ++i) { |
| 194 const BlobData::Item& item = blob_data_->items().at(i); | 194 const BlobData::Item& item = blob_data_->items().at(i); |
| 195 if (IsFileType(item.type())) { | 195 if (IsFileType(item.type())) { |
| 196 ++pending_get_file_info_count_; | 196 ++pending_get_file_info_count_; |
| 197 GetFileStreamReader(i)->GetLength( | 197 GetFileStreamReader(i) |
| 198 base::Bind(&BlobURLRequestJob::DidGetFileItemLength, | 198 ->GetLength(base::Bind(&BlobURLRequestJob::DidGetFileItemLength, |
| 199 weak_factory_.GetWeakPtr(), i)); | 199 weak_factory_.GetWeakPtr(), |
| 200 i)); |
| 200 continue; | 201 continue; |
| 201 } | 202 } |
| 202 | 203 |
| 203 if (!AddItemLength(i, item.length())) | 204 if (!AddItemLength(i, item.length())) |
| 204 return; | 205 return; |
| 205 } | 206 } |
| 206 | 207 |
| 207 if (pending_get_file_info_count_ == 0) | 208 if (pending_get_file_info_count_ == 0) |
| 208 DidCountSize(net::OK); | 209 DidCountSize(net::OK); |
| 209 } | 210 } |
| 210 | 211 |
| 211 void BlobURLRequestJob::DidCountSize(int error) { | 212 void BlobURLRequestJob::DidCountSize(int error) { |
| 212 DCHECK(!error_); | 213 DCHECK(!error_); |
| 213 | 214 |
| 214 // If an error occured, bail out. | 215 // If an error occured, bail out. |
| 215 if (error != net::OK) { | 216 if (error != net::OK) { |
| 216 NotifyFailure(error); | 217 NotifyFailure(error); |
| 217 return; | 218 return; |
| 218 } | 219 } |
| 219 | 220 |
| 220 // Apply the range requirement. | 221 // Apply the range requirement. |
| 221 if (!byte_range_.ComputeBounds(total_size_)) { | 222 if (!byte_range_.ComputeBounds(total_size_)) { |
| 222 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); | 223 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); |
| 223 return; | 224 return; |
| 224 } | 225 } |
| 225 | 226 |
| 226 remaining_bytes_ = byte_range_.last_byte_position() - | 227 remaining_bytes_ = |
| 227 byte_range_.first_byte_position() + 1; | 228 byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1; |
| 228 DCHECK_GE(remaining_bytes_, 0); | 229 DCHECK_GE(remaining_bytes_, 0); |
| 229 | 230 |
| 230 // Do the seek at the beginning of the request. | 231 // Do the seek at the beginning of the request. |
| 231 if (byte_range_.first_byte_position()) | 232 if (byte_range_.first_byte_position()) |
| 232 Seek(byte_range_.first_byte_position()); | 233 Seek(byte_range_.first_byte_position()); |
| 233 | 234 |
| 234 NotifySuccess(); | 235 NotifySuccess(); |
| 235 } | 236 } |
| 236 | 237 |
| 237 void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) { | 238 void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) { |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 return bytes_read; | 432 return bytes_read; |
| 432 } | 433 } |
| 433 | 434 |
| 434 int BlobURLRequestJob::ComputeBytesToRead() const { | 435 int BlobURLRequestJob::ComputeBytesToRead() const { |
| 435 int64 current_item_length = item_length_list_[current_item_index_]; | 436 int64 current_item_length = item_length_list_[current_item_index_]; |
| 436 | 437 |
| 437 int64 item_remaining = current_item_length - current_item_offset_; | 438 int64 item_remaining = current_item_length - current_item_offset_; |
| 438 int64 buf_remaining = read_buf_->BytesRemaining(); | 439 int64 buf_remaining = read_buf_->BytesRemaining(); |
| 439 int64 max_remaining = std::numeric_limits<int>::max(); | 440 int64 max_remaining = std::numeric_limits<int>::max(); |
| 440 | 441 |
| 441 int64 min = std::min(std::min(std::min(item_remaining, | 442 int64 min = std::min( |
| 442 buf_remaining), | 443 std::min(std::min(item_remaining, buf_remaining), remaining_bytes_), |
| 443 remaining_bytes_), | 444 max_remaining); |
| 444 max_remaining); | |
| 445 | 445 |
| 446 return static_cast<int>(min); | 446 return static_cast<int>(min); |
| 447 } | 447 } |
| 448 | 448 |
| 449 bool BlobURLRequestJob::ReadLoop(int* bytes_read) { | 449 bool BlobURLRequestJob::ReadLoop(int* bytes_read) { |
| 450 // Read until we encounter an error or could not get the data immediately. | 450 // Read until we encounter an error or could not get the data immediately. |
| 451 while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) { | 451 while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) { |
| 452 if (!ReadItem()) | 452 if (!ReadItem()) |
| 453 return false; | 453 return false; |
| 454 } | 454 } |
| 455 | 455 |
| 456 *bytes_read = BytesReadCompleted(); | 456 *bytes_read = BytesReadCompleted(); |
| 457 return true; | 457 return true; |
| 458 } | 458 } |
| 459 | 459 |
| 460 void BlobURLRequestJob::NotifySuccess() { | 460 void BlobURLRequestJob::NotifySuccess() { |
| 461 net::HttpStatusCode status_code = net::HTTP_OK; | 461 net::HttpStatusCode status_code = net::HTTP_OK; |
| 462 if (byte_range_set_ && byte_range_.IsValid()) | 462 if (byte_range_set_ && byte_range_.IsValid()) |
| 463 status_code = net::HTTP_PARTIAL_CONTENT; | 463 status_code = net::HTTP_PARTIAL_CONTENT; |
| 464 HeadersCompleted(status_code); | 464 HeadersCompleted(status_code); |
| 465 } | 465 } |
| 466 | 466 |
| 467 void BlobURLRequestJob::NotifyFailure(int error_code) { | 467 void BlobURLRequestJob::NotifyFailure(int error_code) { |
| 468 error_ = true; | 468 error_ = true; |
| 469 | 469 |
| 470 // If we already return the headers on success, we can't change the headers | 470 // If we already return the headers on success, we can't change the headers |
| 471 // now. Instead, we just error out. | 471 // now. Instead, we just error out. |
| 472 if (response_info_) { | 472 if (response_info_) { |
| 473 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, | 473 NotifyDone( |
| 474 error_code)); | 474 net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); |
| 475 return; | 475 return; |
| 476 } | 476 } |
| 477 | 477 |
| 478 net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; | 478 net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; |
| 479 switch (error_code) { | 479 switch (error_code) { |
| 480 case net::ERR_ACCESS_DENIED: | 480 case net::ERR_ACCESS_DENIED: |
| 481 status_code = net::HTTP_FORBIDDEN; | 481 status_code = net::HTTP_FORBIDDEN; |
| 482 break; | 482 break; |
| 483 case net::ERR_FILE_NOT_FOUND: | 483 case net::ERR_FILE_NOT_FOUND: |
| 484 status_code = net::HTTP_NOT_FOUND; | 484 status_code = net::HTTP_NOT_FOUND; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 509 if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) { | 509 if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) { |
| 510 std::string content_length_header(net::HttpRequestHeaders::kContentLength); | 510 std::string content_length_header(net::HttpRequestHeaders::kContentLength); |
| 511 content_length_header.append(": "); | 511 content_length_header.append(": "); |
| 512 content_length_header.append(base::Int64ToString(remaining_bytes_)); | 512 content_length_header.append(base::Int64ToString(remaining_bytes_)); |
| 513 headers->AddHeader(content_length_header); | 513 headers->AddHeader(content_length_header); |
| 514 if (status_code == net::HTTP_PARTIAL_CONTENT) { | 514 if (status_code == net::HTTP_PARTIAL_CONTENT) { |
| 515 DCHECK(byte_range_set_); | 515 DCHECK(byte_range_set_); |
| 516 DCHECK(byte_range_.IsValid()); | 516 DCHECK(byte_range_.IsValid()); |
| 517 std::string content_range_header(net::HttpResponseHeaders::kContentRange); | 517 std::string content_range_header(net::HttpResponseHeaders::kContentRange); |
| 518 content_range_header.append(": bytes "); | 518 content_range_header.append(": bytes "); |
| 519 content_range_header.append(base::StringPrintf( | 519 content_range_header.append( |
| 520 "%" PRId64 "-%" PRId64, | 520 base::StringPrintf("%" PRId64 "-%" PRId64, |
| 521 byte_range_.first_byte_position(), byte_range_.last_byte_position())); | 521 byte_range_.first_byte_position(), |
| 522 byte_range_.last_byte_position())); |
| 522 content_range_header.append("/"); | 523 content_range_header.append("/"); |
| 523 content_range_header.append(base::StringPrintf("%" PRId64, total_size_)); | 524 content_range_header.append(base::StringPrintf("%" PRId64, total_size_)); |
| 524 headers->AddHeader(content_range_header); | 525 headers->AddHeader(content_range_header); |
| 525 } | 526 } |
| 526 if (!blob_data_->content_type().empty()) { | 527 if (!blob_data_->content_type().empty()) { |
| 527 std::string content_type_header(net::HttpRequestHeaders::kContentType); | 528 std::string content_type_header(net::HttpRequestHeaders::kContentType); |
| 528 content_type_header.append(": "); | 529 content_type_header.append(": "); |
| 529 content_type_header.append(blob_data_->content_type()); | 530 content_type_header.append(blob_data_->content_type()); |
| 530 headers->AddHeader(content_type_header); | 531 headers->AddHeader(content_type_header); |
| 531 } | 532 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 switch (item.type()) { | 567 switch (item.type()) { |
| 567 case BlobData::Item::TYPE_FILE: | 568 case BlobData::Item::TYPE_FILE: |
| 568 reader = FileStreamReader::CreateForLocalFile( | 569 reader = FileStreamReader::CreateForLocalFile( |
| 569 file_thread_proxy_.get(), | 570 file_thread_proxy_.get(), |
| 570 item.path(), | 571 item.path(), |
| 571 item.offset() + additional_offset, | 572 item.offset() + additional_offset, |
| 572 item.expected_modification_time()); | 573 item.expected_modification_time()); |
| 573 break; | 574 break; |
| 574 case BlobData::Item::TYPE_FILE_FILESYSTEM: | 575 case BlobData::Item::TYPE_FILE_FILESYSTEM: |
| 575 reader = file_system_context_->CreateFileStreamReader( | 576 reader = file_system_context_->CreateFileStreamReader( |
| 576 fileapi::FileSystemURL( | 577 storage::FileSystemURL( |
| 577 file_system_context_->CrackURL(item.filesystem_url())), | 578 file_system_context_->CrackURL( |
| 578 item.offset() + additional_offset, | 579 item.filesystem_url())), |
| 579 item.expected_modification_time()).release(); | 580 item.offset() + additional_offset, |
| 581 item.expected_modification_time()) |
| 582 .release(); |
| 580 break; | 583 break; |
| 581 default: | 584 default: |
| 582 NOTREACHED(); | 585 NOTREACHED(); |
| 583 } | 586 } |
| 584 DCHECK(reader); | 587 DCHECK(reader); |
| 585 index_to_reader_[index] = reader; | 588 index_to_reader_[index] = reader; |
| 586 } | 589 } |
| 587 | 590 |
| 588 } // namespace webkit_blob | 591 } // namespace storage |
| OLD | NEW |