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 |