Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: storage/browser/blob/blob_url_request_job.cc

Issue 1376123002: Revert of [Blob] BlobReader class & tests, and removal of all redundant reading. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "storage/browser/blob/blob_url_request_job.h" 5 #include "storage/browser/blob/blob_url_request_job.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 13 matching lines...) Expand all
24 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
25 #include "net/disk_cache/disk_cache.h" 25 #include "net/disk_cache/disk_cache.h"
26 #include "net/http/http_request_headers.h" 26 #include "net/http/http_request_headers.h"
27 #include "net/http/http_response_headers.h" 27 #include "net/http/http_response_headers.h"
28 #include "net/http/http_response_info.h" 28 #include "net/http/http_response_info.h"
29 #include "net/http/http_util.h" 29 #include "net/http/http_util.h"
30 #include "net/url_request/url_request.h" 30 #include "net/url_request/url_request.h"
31 #include "net/url_request/url_request_context.h" 31 #include "net/url_request/url_request_context.h"
32 #include "net/url_request/url_request_error_job.h" 32 #include "net/url_request/url_request_error_job.h"
33 #include "net/url_request/url_request_status.h" 33 #include "net/url_request/url_request_status.h"
34 #include "storage/browser/blob/blob_data_handle.h"
35 #include "storage/browser/blob/blob_reader.h"
36 #include "storage/browser/fileapi/file_stream_reader.h" 34 #include "storage/browser/fileapi/file_stream_reader.h"
37 #include "storage/browser/fileapi/file_system_context.h" 35 #include "storage/browser/fileapi/file_system_context.h"
38 #include "storage/browser/fileapi/file_system_url.h" 36 #include "storage/browser/fileapi/file_system_url.h"
39 #include "storage/common/data_element.h" 37 #include "storage/common/data_element.h"
40 38
41 namespace storage { 39 namespace storage {
42 40
41 namespace {
42
43 bool IsFileType(DataElement::Type type) {
44 switch (type) {
45 case DataElement::TYPE_FILE:
46 case DataElement::TYPE_FILE_FILESYSTEM:
47 return true;
48 default:
49 return false;
50 }
51 }
52
53 } // namespace
54
43 BlobURLRequestJob::BlobURLRequestJob( 55 BlobURLRequestJob::BlobURLRequestJob(
44 net::URLRequest* request, 56 net::URLRequest* request,
45 net::NetworkDelegate* network_delegate, 57 net::NetworkDelegate* network_delegate,
46 BlobDataHandle* blob_handle, 58 scoped_ptr<BlobDataSnapshot> blob_data,
47 FileSystemContext* file_system_context, 59 storage::FileSystemContext* file_system_context,
48 base::SingleThreadTaskRunner* file_task_runner) 60 base::SingleThreadTaskRunner* file_task_runner)
49 : net::URLRequestJob(request, network_delegate), 61 : net::URLRequestJob(request, network_delegate),
62 blob_data_(blob_data.Pass()),
63 file_system_context_(file_system_context),
64 file_task_runner_(file_task_runner),
65 total_size_(0),
66 remaining_bytes_(0),
67 pending_get_file_info_count_(0),
68 current_item_index_(0),
69 current_item_offset_(0),
50 error_(false), 70 error_(false),
51 byte_range_set_(false), 71 byte_range_set_(false),
52 weak_factory_(this) { 72 weak_factory_(this) {
53 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest", this, "uuid", 73 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest", this, "uuid",
54 blob_handle ? blob_handle->uuid() : "NotFound"); 74 blob_data_ ? blob_data_->uuid() : "NotFound");
55 DCHECK(file_task_runner); 75 DCHECK(file_task_runner_.get());
56 if (blob_handle) {
57 blob_handle_.reset(new BlobDataHandle(*blob_handle));
58 blob_reader_ =
59 blob_handle_->CreateReader(file_system_context, file_task_runner);
60 }
61 } 76 }
62 77
63 void BlobURLRequestJob::Start() { 78 void BlobURLRequestJob::Start() {
64 // Continue asynchronously. 79 // Continue asynchronously.
65 base::MessageLoop::current()->PostTask( 80 base::MessageLoop::current()->PostTask(
66 FROM_HERE, 81 FROM_HERE,
67 base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); 82 base::Bind(&BlobURLRequestJob::DidStart, weak_factory_.GetWeakPtr()));
68 } 83 }
69 84
70 void BlobURLRequestJob::Kill() { 85 void BlobURLRequestJob::Kill() {
71 if (blob_reader_) { 86 DeleteCurrentFileReader();
72 blob_reader_->Kill(); 87
73 }
74 net::URLRequestJob::Kill(); 88 net::URLRequestJob::Kill();
75 weak_factory_.InvalidateWeakPtrs(); 89 weak_factory_.InvalidateWeakPtrs();
76 } 90 }
77 91
78 bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest, 92 bool BlobURLRequestJob::ReadRawData(net::IOBuffer* dest,
79 int dest_size, 93 int dest_size,
80 int* bytes_read) { 94 int* bytes_read) {
81 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadRawData", this, "uuid",
82 blob_handle_ ? blob_handle_->uuid() : "NotFound");
83 DCHECK_NE(dest_size, 0); 95 DCHECK_NE(dest_size, 0);
84 DCHECK(bytes_read); 96 DCHECK(bytes_read);
97 DCHECK_GE(remaining_bytes_, 0);
85 98
86 // Bail out immediately if we encounter an error. 99 // Bail out immediately if we encounter an error.
87 if (error_) { 100 if (error_) {
88 *bytes_read = 0; 101 *bytes_read = 0;
89 return true; 102 return true;
90 } 103 }
91 104
92 BlobReader::Status read_status = 105 if (remaining_bytes_ < dest_size)
93 blob_reader_->Read(dest, dest_size, bytes_read, 106 dest_size = static_cast<int>(remaining_bytes_);
94 base::Bind(&BlobURLRequestJob::DidReadRawData,
95 weak_factory_.GetWeakPtr()));
96 107
97 switch (read_status) { 108 // If we should copy zero bytes because |remaining_bytes_| is zero, short
98 case BlobReader::Status::NET_ERROR: 109 // circuit here.
99 NotifyFailure(blob_reader_->net_error()); 110 if (!dest_size) {
100 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid", 111 *bytes_read = 0;
101 blob_handle_ ? blob_handle_->uuid() : "NotFound"); 112 return true;
102 return false;
103 case BlobReader::Status::IO_PENDING:
104 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
105 return false;
106 case BlobReader::Status::DONE:
107 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
108 blob_handle_ ? blob_handle_->uuid() : "NotFound");
109 return true;
110 } 113 }
111 NOTREACHED(); 114
112 return true; 115 // Keep track of the buffer.
116 DCHECK(!read_buf_.get());
117 read_buf_ = new net::DrainableIOBuffer(dest, dest_size);
118
119 return ReadLoop(bytes_read);
113 } 120 }
114 121
115 bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const { 122 bool BlobURLRequestJob::GetMimeType(std::string* mime_type) const {
116 if (!response_info_) 123 if (!response_info_)
117 return false; 124 return false;
118 125
119 return response_info_->headers->GetMimeType(mime_type); 126 return response_info_->headers->GetMimeType(mime_type);
120 } 127 }
121 128
122 void BlobURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { 129 void BlobURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
(...skipping 22 matching lines...) Expand all
145 // We don't support multiple range requests in one single URL request, 152 // We don't support multiple range requests in one single URL request,
146 // because we need to do multipart encoding here. 153 // because we need to do multipart encoding here.
147 // TODO(jianli): Support multipart byte range requests. 154 // TODO(jianli): Support multipart byte range requests.
148 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); 155 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
149 } 156 }
150 } 157 }
151 } 158 }
152 } 159 }
153 160
154 BlobURLRequestJob::~BlobURLRequestJob() { 161 BlobURLRequestJob::~BlobURLRequestJob() {
162 STLDeleteValues(&index_to_reader_);
155 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest", this, "uuid", 163 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest", this, "uuid",
156 blob_handle_ ? blob_handle_->uuid() : "NotFound"); 164 blob_data_ ? blob_data_->uuid() : "NotFound");
157 } 165 }
158 166
159 void BlobURLRequestJob::DidStart() { 167 void BlobURLRequestJob::DidStart() {
168 current_file_chunk_number_ = 0;
160 error_ = false; 169 error_ = false;
161 170
162 // We only support GET request per the spec. 171 // We only support GET request per the spec.
163 if (request()->method() != "GET") { 172 if (request()->method() != "GET") {
164 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); 173 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
165 return; 174 return;
166 } 175 }
167 176
168 // If the blob data is not present, bail out. 177 // If the blob data is not present, bail out.
169 if (!blob_handle_) { 178 if (!blob_data_) {
170 NotifyFailure(net::ERR_FILE_NOT_FOUND); 179 NotifyFailure(net::ERR_FILE_NOT_FOUND);
171 return; 180 return;
172 } 181 }
173 182
183 CountSize();
184 }
185
186 bool BlobURLRequestJob::AddItemLength(size_t index, int64 item_length) {
187 if (item_length > kint64max - total_size_) {
188 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid",
189 blob_data_->uuid());
190 NotifyFailure(net::ERR_FAILED);
191 return false;
192 }
193
194 // Cache the size and add it to the total size.
195 DCHECK_LT(index, item_length_list_.size());
196 item_length_list_[index] = item_length;
197 total_size_ += item_length;
198 return true;
199 }
200
201 bool BlobURLRequestJob::CountSize() {
174 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::CountSize", this, "uuid", 202 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::CountSize", this, "uuid",
175 blob_handle_->uuid()); 203 blob_data_->uuid());
176 BlobReader::Status size_status = blob_reader_->CalculateSize(base::Bind( 204 pending_get_file_info_count_ = 0;
177 &BlobURLRequestJob::DidCalculateSize, weak_factory_.GetWeakPtr())); 205 total_size_ = 0;
178 switch (size_status) { 206 const auto& items = blob_data_->items();
179 case BlobReader::Status::NET_ERROR: 207 item_length_list_.resize(items.size());
180 NotifyFailure(blob_reader_->net_error()); 208
181 return; 209 for (size_t i = 0; i < items.size(); ++i) {
182 case BlobReader::Status::IO_PENDING: 210 const BlobDataItem& item = *items.at(i);
183 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); 211 if (IsFileType(item.type())) {
184 return; 212 ++pending_get_file_info_count_;
185 case BlobReader::Status::DONE: 213 storage::FileStreamReader* const reader = GetFileStreamReader(i);
186 DidCalculateSize(net::OK); 214 if (!reader) {
187 return; 215 NotifyFailure(net::ERR_FAILED);
188 } 216 return false;
189 } 217 }
190 218 if (!reader->GetLength(
191 void BlobURLRequestJob::DidCalculateSize(int result) { 219 base::Bind(&BlobURLRequestJob::DidGetFileItemLength,
220 weak_factory_.GetWeakPtr(), i))) {
221 NotifyFailure(net::ERR_FILE_NOT_FOUND);
222 return false;
223 }
224 continue;
225 }
226
227 if (!AddItemLength(i, item.length()))
228 return false;
229 }
230
231 if (pending_get_file_info_count_ == 0)
232 DidCountSize(net::OK);
233
234 return true;
235 }
236
237 void BlobURLRequestJob::DidCountSize(int error) {
238 DCHECK(!error_);
192 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid", 239 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::CountSize", this, "uuid",
193 blob_handle_->uuid()); 240 blob_data_->uuid());
194 // Clear the IO_PENDING status 241
242 // If an error occured, bail out.
243 if (error != net::OK) {
244 NotifyFailure(error);
245 return;
246 }
247
248 // Apply the range requirement.
249 if (!byte_range_.ComputeBounds(total_size_)) {
250 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
251 return;
252 }
253
254 remaining_bytes_ = base::checked_cast<int64>(
255 byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1);
256 DCHECK_GE(remaining_bytes_, 0);
257
258 // Do the seek at the beginning of the request.
259 if (byte_range_.first_byte_position())
260 Seek(byte_range_.first_byte_position());
261
262 NotifySuccess();
263 }
264
265 void BlobURLRequestJob::DidGetFileItemLength(size_t index, int64 result) {
266 // Do nothing if we have encountered an error.
267 if (error_)
268 return;
269
270 if (result == net::ERR_UPLOAD_FILE_CHANGED) {
271 NotifyFailure(net::ERR_FILE_NOT_FOUND);
272 return;
273 } else if (result < 0) {
274 NotifyFailure(result);
275 return;
276 }
277
278 const auto& items = blob_data_->items();
279 DCHECK_LT(index, items.size());
280 const BlobDataItem& item = *items.at(index);
281 DCHECK(IsFileType(item.type()));
282
283 uint64 file_length = result;
284 uint64 item_offset = item.offset();
285 uint64 item_length = item.length();
286
287 if (item_offset > file_length) {
288 NotifyFailure(net::ERR_FILE_NOT_FOUND);
289 return;
290 }
291
292 uint64 max_length = file_length - item_offset;
293
294 // If item length is undefined, then we need to use the file size being
295 // resolved in the real time.
296 if (item_length == std::numeric_limits<uint64>::max()) {
297 item_length = max_length;
298 } else if (item_length > max_length) {
299 NotifyFailure(net::ERR_FILE_NOT_FOUND);
300 return;
301 }
302
303 if (!AddItemLength(index, item_length))
304 return;
305
306 if (--pending_get_file_info_count_ == 0)
307 DidCountSize(net::OK);
308 }
309
310 void BlobURLRequestJob::Seek(int64 offset) {
311 // Skip the initial items that are not in the range.
312 const auto& items = blob_data_->items();
313 for (current_item_index_ = 0;
314 current_item_index_ < items.size() &&
315 offset >= item_length_list_[current_item_index_];
316 ++current_item_index_) {
317 offset -= item_length_list_[current_item_index_];
318 }
319
320 // Set the offset that need to jump to for the first item in the range.
321 current_item_offset_ = offset;
322
323 if (offset == 0)
324 return;
325
326 // Adjust the offset of the first stream if it is of file type.
327 const BlobDataItem& item = *items.at(current_item_index_);
328 if (IsFileType(item.type())) {
329 DeleteCurrentFileReader();
330 CreateFileStreamReader(current_item_index_, offset);
331 }
332 }
333
334 bool BlobURLRequestJob::ReadItem() {
335 // Are we done with reading all the blob data?
336 if (remaining_bytes_ == 0)
337 return true;
338
339 const auto& items = blob_data_->items();
340 // If we get to the last item but still expect something to read, bail out
341 // since something is wrong.
342 if (current_item_index_ >= items.size()) {
343 NotifyFailure(net::ERR_FAILED);
344 return false;
345 }
346
347 // Compute the bytes to read for current item.
348 int bytes_to_read = ComputeBytesToRead();
349
350 // If nothing to read for current item, advance to next item.
351 if (bytes_to_read == 0) {
352 AdvanceItem();
353 return true;
354 }
355
356 // Do the reading.
357 const BlobDataItem& item = *items.at(current_item_index_);
358 if (item.type() == DataElement::TYPE_BYTES)
359 return ReadBytesItem(item, bytes_to_read);
360 if (item.type() == DataElement::TYPE_DISK_CACHE_ENTRY)
361 return ReadDiskCacheEntryItem(item, bytes_to_read);
362 if (!IsFileType(item.type())) {
363 NOTREACHED();
364 return false;
365 }
366 storage::FileStreamReader* const reader =
367 GetFileStreamReader(current_item_index_);
368 if (!reader) {
369 NotifyFailure(net::ERR_FAILED);
370 return false;
371 }
372
373 return ReadFileItem(reader, bytes_to_read);
374 }
375
376 void BlobURLRequestJob::AdvanceItem() {
377 // Close the file if the current item is a file.
378 DeleteCurrentFileReader();
379
380 // Advance to the next item.
381 current_item_index_++;
382 current_item_offset_ = 0;
383 }
384
385 void BlobURLRequestJob::AdvanceBytesRead(int result) {
386 DCHECK_GT(result, 0);
387
388 // Do we finish reading the current item?
389 current_item_offset_ += result;
390 if (current_item_offset_ == item_length_list_[current_item_index_])
391 AdvanceItem();
392
393 // Subtract the remaining bytes.
394 remaining_bytes_ -= result;
395 DCHECK_GE(remaining_bytes_, 0);
396
397 // Adjust the read buffer.
398 read_buf_->DidConsume(result);
399 DCHECK_GE(read_buf_->BytesRemaining(), 0);
400 }
401
402 bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item,
403 int bytes_to_read) {
404 TRACE_EVENT1("Blob", "BlobRequest::ReadBytesItem", "uuid",
405 blob_data_->uuid());
406 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
407
408 memcpy(read_buf_->data(),
409 item.bytes() + item.offset() + current_item_offset_,
410 bytes_to_read);
411
412 AdvanceBytesRead(bytes_to_read);
413 return true;
414 }
415
416 bool BlobURLRequestJob::ReadFileItem(FileStreamReader* reader,
417 int bytes_to_read) {
418 DCHECK(!GetStatus().is_io_pending())
419 << "Can't begin IO while another IO operation is pending.";
420 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
421 DCHECK(reader);
422 int chunk_number = current_file_chunk_number_++;
423 TRACE_EVENT_ASYNC_BEGIN1("Blob", "BlobRequest::ReadFileItem", this, "uuid",
424 blob_data_->uuid());
425 const int result =
426 reader->Read(read_buf_.get(), bytes_to_read,
427 base::Bind(&BlobURLRequestJob::DidReadFile,
428 weak_factory_.GetWeakPtr(), chunk_number));
429 if (result >= 0) {
430 AdvanceBytesRead(result);
431 return true;
432 }
433 if (result == net::ERR_IO_PENDING)
434 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
435 else
436 NotifyFailure(result);
437 return false;
438 }
439
440 void BlobURLRequestJob::DidReadFile(int chunk_number, int result) {
441 DCHECK(GetStatus().is_io_pending())
442 << "Asynchronous IO completed while IO wasn't pending?";
443 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadFileItem", this, "uuid",
444 blob_data_->uuid());
445 if (result <= 0) {
446 NotifyFailure(result);
447 return;
448 }
449 SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
450
451 AdvanceBytesRead(result);
452
453 // Otherwise, continue the reading.
454 int bytes_read = 0;
455 if (ReadLoop(&bytes_read))
456 NotifyReadComplete(bytes_read);
457 }
458
459 void BlobURLRequestJob::DeleteCurrentFileReader() {
460 IndexToReaderMap::iterator found = index_to_reader_.find(current_item_index_);
461 if (found != index_to_reader_.end() && found->second) {
462 delete found->second;
463 index_to_reader_.erase(found);
464 }
465 }
466
467 bool BlobURLRequestJob::ReadDiskCacheEntryItem(const BlobDataItem& item,
468 int bytes_to_read) {
469 DCHECK(!GetStatus().is_io_pending())
470 << "Can't begin IO while another IO operation is pending.";
471 DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read);
472
473 const int result = item.disk_cache_entry()->ReadData(
474 item.disk_cache_stream_index(), current_item_offset_, read_buf_.get(),
475 bytes_to_read, base::Bind(&BlobURLRequestJob::DidReadDiskCacheEntry,
476 weak_factory_.GetWeakPtr()));
477 if (result >= 0) {
478 AdvanceBytesRead(result);
479 return true;
480 }
481 if (result == net::ERR_IO_PENDING)
482 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
483 else
484 NotifyFailure(result);
485 return false;
486 }
487
488 void BlobURLRequestJob::DidReadDiskCacheEntry(int result) {
489 DCHECK(GetStatus().is_io_pending())
490 << "Asynchronous IO completed while IO wasn't pending?";
491 if (result <= 0) {
492 NotifyFailure(result);
493 return;
494 }
195 SetStatus(net::URLRequestStatus()); 495 SetStatus(net::URLRequestStatus());
196 496
197 if (result != net::OK) { 497 AdvanceBytesRead(result);
198 NotifyFailure(result); 498
199 return; 499 int bytes_read = 0;
200 } 500 if (ReadLoop(&bytes_read))
201 501 NotifyReadComplete(bytes_read);
202 // Apply the range requirement. 502 }
203 if (!byte_range_.ComputeBounds(blob_reader_->total_size())) { 503
204 NotifyFailure(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); 504 int BlobURLRequestJob::BytesReadCompleted() {
205 return; 505 int bytes_read = read_buf_->BytesConsumed();
206 } 506 read_buf_ = NULL;
207 507 return bytes_read;
208 DCHECK_LE(byte_range_.first_byte_position(), 508 }
209 byte_range_.last_byte_position() + 1); 509
210 uint64_t length = base::checked_cast<uint64_t>( 510 int BlobURLRequestJob::ComputeBytesToRead() const {
211 byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1); 511 int64 current_item_length = item_length_list_[current_item_index_];
212 512
213 if (byte_range_set_) 513 int64 item_remaining = current_item_length - current_item_offset_;
214 blob_reader_->SetReadRange(byte_range_.first_byte_position(), length); 514 int64 buf_remaining = read_buf_->BytesRemaining();
215 515 int64 max_remaining = std::numeric_limits<int>::max();
516
517 int64 min = std::min(std::min(std::min(item_remaining,
518 buf_remaining),
519 remaining_bytes_),
520 max_remaining);
521
522 return static_cast<int>(min);
523 }
524
525 bool BlobURLRequestJob::ReadLoop(int* bytes_read) {
526 // Read until we encounter an error or could not get the data immediately.
527 while (remaining_bytes_ > 0 && read_buf_->BytesRemaining() > 0) {
528 if (!ReadItem())
529 return false;
530 }
531
532 *bytes_read = BytesReadCompleted();
533 return true;
534 }
535
536 void BlobURLRequestJob::NotifySuccess() {
216 net::HttpStatusCode status_code = net::HTTP_OK; 537 net::HttpStatusCode status_code = net::HTTP_OK;
217 if (byte_range_set_ && byte_range_.IsValid()) 538 if (byte_range_set_ && byte_range_.IsValid())
218 status_code = net::HTTP_PARTIAL_CONTENT; 539 status_code = net::HTTP_PARTIAL_CONTENT;
219 HeadersCompleted(status_code); 540 HeadersCompleted(status_code);
220 } 541 }
221 542
222 void BlobURLRequestJob::DidReadRawData(int result) {
223 TRACE_EVENT_ASYNC_END1("Blob", "BlobRequest::ReadRawData", this, "uuid",
224 blob_handle_ ? blob_handle_->uuid() : "NotFound");
225 if (result < 0) {
226 NotifyFailure(result);
227 return;
228 }
229 // Clear the IO_PENDING status
230 SetStatus(net::URLRequestStatus());
231 NotifyReadComplete(result);
232 }
233
234 void BlobURLRequestJob::NotifyFailure(int error_code) { 543 void BlobURLRequestJob::NotifyFailure(int error_code) {
235 error_ = true; 544 error_ = true;
236 545
237 // If we already return the headers on success, we can't change the headers 546 // If we already return the headers on success, we can't change the headers
238 // now. Instead, we just error out. 547 // now. Instead, we just error out.
239 if (response_info_) { 548 if (response_info_) {
240 NotifyDone( 549 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
241 net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); 550 error_code));
242 return; 551 return;
243 } 552 }
244 553
245 net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; 554 net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR;
246 switch (error_code) { 555 switch (error_code) {
247 case net::ERR_ACCESS_DENIED: 556 case net::ERR_ACCESS_DENIED:
248 status_code = net::HTTP_FORBIDDEN; 557 status_code = net::HTTP_FORBIDDEN;
249 break; 558 break;
250 case net::ERR_FILE_NOT_FOUND: 559 case net::ERR_FILE_NOT_FOUND:
251 status_code = net::HTTP_NOT_FOUND; 560 status_code = net::HTTP_NOT_FOUND;
252 break; 561 break;
253 case net::ERR_METHOD_NOT_SUPPORTED: 562 case net::ERR_METHOD_NOT_SUPPORTED:
254 status_code = net::HTTP_METHOD_NOT_ALLOWED; 563 status_code = net::HTTP_METHOD_NOT_ALLOWED;
(...skipping 11 matching lines...) Expand all
266 } 575 }
267 576
268 void BlobURLRequestJob::HeadersCompleted(net::HttpStatusCode status_code) { 577 void BlobURLRequestJob::HeadersCompleted(net::HttpStatusCode status_code) {
269 std::string status("HTTP/1.1 "); 578 std::string status("HTTP/1.1 ");
270 status.append(base::IntToString(status_code)); 579 status.append(base::IntToString(status_code));
271 status.append(" "); 580 status.append(" ");
272 status.append(net::GetHttpReasonPhrase(status_code)); 581 status.append(net::GetHttpReasonPhrase(status_code));
273 status.append("\0\0", 2); 582 status.append("\0\0", 2);
274 net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status); 583 net::HttpResponseHeaders* headers = new net::HttpResponseHeaders(status);
275 584
276 set_expected_content_size(0);
277
278 if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) { 585 if (status_code == net::HTTP_OK || status_code == net::HTTP_PARTIAL_CONTENT) {
279 set_expected_content_size(blob_reader_->remaining_bytes());
280 std::string content_length_header(net::HttpRequestHeaders::kContentLength); 586 std::string content_length_header(net::HttpRequestHeaders::kContentLength);
281 content_length_header.append(": "); 587 content_length_header.append(": ");
282 content_length_header.append( 588 content_length_header.append(base::Int64ToString(remaining_bytes_));
283 base::Int64ToString(blob_reader_->remaining_bytes()));
284 headers->AddHeader(content_length_header); 589 headers->AddHeader(content_length_header);
285 if (status_code == net::HTTP_PARTIAL_CONTENT) { 590 if (status_code == net::HTTP_PARTIAL_CONTENT) {
286 DCHECK(byte_range_set_); 591 DCHECK(byte_range_set_);
287 DCHECK(byte_range_.IsValid()); 592 DCHECK(byte_range_.IsValid());
288 std::string content_range_header(net::HttpResponseHeaders::kContentRange); 593 std::string content_range_header(net::HttpResponseHeaders::kContentRange);
289 content_range_header.append(": bytes "); 594 content_range_header.append(": bytes ");
290 content_range_header.append(base::StringPrintf( 595 content_range_header.append(base::StringPrintf(
291 "%" PRId64 "-%" PRId64, byte_range_.first_byte_position(), 596 "%" PRId64 "-%" PRId64,
292 byte_range_.last_byte_position())); 597 byte_range_.first_byte_position(), byte_range_.last_byte_position()));
293 content_range_header.append("/"); 598 content_range_header.append("/");
294 content_range_header.append( 599 content_range_header.append(base::StringPrintf("%" PRId64, total_size_));
295 base::StringPrintf("%" PRId64, blob_reader_->total_size()));
296 headers->AddHeader(content_range_header); 600 headers->AddHeader(content_range_header);
297 } 601 }
298 if (!blob_handle_->content_type().empty()) { 602 if (!blob_data_->content_type().empty()) {
299 std::string content_type_header(net::HttpRequestHeaders::kContentType); 603 std::string content_type_header(net::HttpRequestHeaders::kContentType);
300 content_type_header.append(": "); 604 content_type_header.append(": ");
301 content_type_header.append(blob_handle_->content_type()); 605 content_type_header.append(blob_data_->content_type());
302 headers->AddHeader(content_type_header); 606 headers->AddHeader(content_type_header);
303 } 607 }
304 if (!blob_handle_->content_disposition().empty()) { 608 if (!blob_data_->content_disposition().empty()) {
305 std::string content_disposition_header("Content-Disposition: "); 609 std::string content_disposition_header("Content-Disposition: ");
306 content_disposition_header.append(blob_handle_->content_disposition()); 610 content_disposition_header.append(blob_data_->content_disposition());
307 headers->AddHeader(content_disposition_header); 611 headers->AddHeader(content_disposition_header);
308 } 612 }
309 } 613 }
310 614
311 response_info_.reset(new net::HttpResponseInfo()); 615 response_info_.reset(new net::HttpResponseInfo());
312 response_info_->headers = headers; 616 response_info_->headers = headers;
313 617
618 set_expected_content_size(remaining_bytes_);
619
314 NotifyHeadersComplete(); 620 NotifyHeadersComplete();
315 } 621 }
316 622
623 FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) {
624 const auto& items = blob_data_->items();
625 DCHECK_LT(index, items.size());
626 const BlobDataItem& item = *items.at(index);
627 if (!IsFileType(item.type()))
628 return nullptr;
629 if (index_to_reader_.find(index) == index_to_reader_.end()) {
630 if (!CreateFileStreamReader(index, 0))
631 return nullptr;
632 }
633 DCHECK(index_to_reader_[index]);
634 return index_to_reader_[index];
635 }
636
637 bool BlobURLRequestJob::CreateFileStreamReader(size_t index,
638 int64 additional_offset) {
639 const auto& items = blob_data_->items();
640 DCHECK_LT(index, items.size());
641 const BlobDataItem& item = *items.at(index);
642 DCHECK(IsFileType(item.type()));
643 DCHECK_EQ(0U, index_to_reader_.count(index));
644
645 FileStreamReader* reader = nullptr;
646 switch (item.type()) {
647 case DataElement::TYPE_FILE:
648 reader = FileStreamReader::CreateForLocalFile(
649 file_task_runner_.get(), item.path(),
650 item.offset() + additional_offset, item.expected_modification_time());
651 DCHECK(reader);
652 index_to_reader_[index] = reader;
653 return true;
654
655 case DataElement::TYPE_FILE_FILESYSTEM:
656 reader = file_system_context_
657 ->CreateFileStreamReader(
658 storage::FileSystemURL(file_system_context_->CrackURL(
659 item.filesystem_url())),
660 item.offset() + additional_offset,
661 item.length() == std::numeric_limits<uint64>::max()
662 ? storage::kMaximumLength
663 : item.length() - additional_offset,
664 item.expected_modification_time())
665 .release();
666 if (reader) {
667 index_to_reader_[index] = reader;
668 return true;
669 }
670
671 // The file stream reader may not be obtainable if the file is on an
672 // isolated file system, which has been unmounted.
673 return false;
674
675 default:
676 break;
677 }
678
679 NOTREACHED();
680 return false;
681 }
682
317 } // namespace storage 683 } // namespace storage
OLDNEW
« no previous file with comments | « storage/browser/blob/blob_url_request_job.h ('k') | storage/browser/blob/blob_url_request_job_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698